綁定帳號登入

Android 台灣中文網

打印 上一主題 下一主題

[求助] SurfaceView BitmapFactory 圖片問題求救

[複製連結] 查看: 1860|回覆: 9|好評: 0
跳轉到指定樓層
樓主
qk14000 | 收聽TA | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
發表於 2012-8-23 18:16

馬上加入Android 台灣中文網,立即免費下載應用遊戲。

您需要 登錄 才可以下載或查看,沒有帳號?註冊

x
我用SurfaceView 和 BitmapFactory 放圖片到程式裡  我沒放很多 但執行到一半就會錯誤
錯誤都是java.lang.OutOfMemoryError

是因為我的圖片太大嗎?
我都是用1280*800 32位元深度的png黨 大概快20張
都在同一個主要activity切換
切換到一半就出錯= =

是因為我圖片太大出錯嗎?

有高手可以幫忙嗎?!
「用Android 就來APK.TW」,快來加入粉絲吧!
Android 台灣中文網(APK.TW)
收藏收藏 分享分享 分享專題
用Android 就來Android 台灣中文網(https://apk.tw)
回覆

使用道具 舉報

沙發
iceblue7x | 收聽TA | 只看該作者
發表於 2012-8-23 22:57
png是壓縮過的圖片檔案格式

Android 載入到記憶體裡的圖片,都是未壓縮的原始影像
你可以試著把png轉成bmp格式,就知道那張圖未壓縮大概會佔用多大的空間了

Android 裡面,每個 app 被限制能使用的記憶體空間非常的小
依裝置不同,大約只有16~32MB而已
用Android 就來Android 台灣中文網(https://apk.tw)
回覆 支持 反對

使用道具 舉報

板凳
ploglin | 收聽TA | 只看該作者
發表於 2012-8-24 09:07
不需要的圖片就先釋放,如果不是要顯示原始的解析度,在讀出圖片前,也可以透過參數的方式,先降低圖片的解析度。
不然這個問題會一直存在
用Android 就來Android 台灣中文網(https://apk.tw)
回覆 支持 反對

使用道具 舉報

地板
 樓主| qk14000 | 收聽TA | 只看該作者
發表於 2012-8-24 12:03
本帖最後由 qk14000 於 2012-8-24 12:04 編輯


有喔! 但是轉能BMP不管解析度都2或3M 好大喔...

用Android 就來Android 台灣中文網(https://apk.tw)
回覆 支持 反對

使用道具 舉報

5
 樓主| qk14000 | 收聽TA | 只看該作者
發表於 2012-8-24 12:04
本帖最後由 qk14000 於 2012-8-24 12:15 編輯
ploglin 發表於 2012-8-24 09:07
不需要的圖片就先釋放,如果不是要顯示原始的解析度,在讀出圖片前,也可以透過參數的方式,先降低圖片的解 ...


該如何釋放 和 降低解析度呢?!

我一開始他就跑到14M 之後點下去會一直累加 返回會減少一點  但還是抵擋不過累加
一直到50M就擋掉... 該如何是好
用Android 就來Android 台灣中文網(https://apk.tw)
回覆 支持 反對

使用道具 舉報

6
ploglin | 收聽TA | 只看該作者
發表於 2012-8-24 12:15
釋放的部份,Bitmap 使用recycle()就好了

解析度

  1. BitmapFactory.Options options = new BitmapFactory.Options();
  2. options.inSampleSize = 1; // 數字越大,解析度越低
  3. Bitmap rltBitmap = BitmapFactory.decodeStream(imageStream, null, options);
複製代碼
用Android 就來Android 台灣中文網(https://apk.tw)
回覆 支持 反對

使用道具 舉報

7
 樓主| qk14000 | 收聽TA | 只看該作者
發表於 2012-8-24 14:04
ploglin 發表於 2012-8-24 12:15
釋放的部份,Bitmap 使用recycle()就好了

解析度

感謝!! 我這就來試試看
用Android 就來Android 台灣中文網(https://apk.tw)
回覆 支持 反對

使用道具 舉報

8
 樓主| qk14000 | 收聽TA | 只看該作者
發表於 2012-8-24 14:42
ploglin 發表於 2012-8-24 12:15
釋放的部份,Bitmap 使用recycle()就好了

解析度

謝啦  解析度可行 但好像占的記憶體還是一樣...

但是recycle會錯誤
recycle是要在哪時候用?和怎麼用?
是直接對Bitmap 的變數宣告嗎?  bmpback.recycle();像這樣?

因為我是一個主要的ACTIVITY 在一直貼上其他的SurfaceView JAVA黨圖片再跑的 所以基本上都是同一個ACTIVITY  
我都是在主要ACTIVITY裡使用
mv = new MenuView(this);                                //將螢幕切到Menu介面
        setContentView(mv);
切換的


如果我從A到B 所以要在B裡面回收A的圖片? 還是 在主要的ACTIVITY 裡面回收?
我都試過 但都錯誤 會有java.lang.NullPointerException...
用Android 就來Android 台灣中文網(https://apk.tw)
回覆 支持 反對

使用道具 舉報

9
ploglin | 收聽TA | 只看該作者
發表於 2012-8-24 15:24
recycle() 的用法沒錯,會變成null代表早就不存在或被釋放。
或者,你可以說明一下,你實際要做的功能,大家一起看看,是否哪個環結需要被注意。
用Android 就來Android 台灣中文網(https://apk.tw)
回覆 支持 反對

使用道具 舉報

10
 樓主| qk14000 | 收聽TA | 只看該作者
發表於 2012-8-24 22:45
ploglin 發表於 2012-8-24 15:24
recycle() 的用法沒錯,會變成null代表早就不存在或被釋放。
或者,你可以說明一下,你實際要做的功能,大 ...

我是先用一個主要activity當作基底(是其他圖片的father) 再用setcontentView貼上其他的圖片java黨 就像這個MenuView來切換畫面 因為是動態的畫面

這是我的第一張圖MenuView是一個JAVA黨 還有下面MenuDrawThread 好像是刷新圖片的吧 也是個java黨
因為我不太懂所以是造著書上的SAMPLE去做的...不知道是不是搞砸了

後面還有很多張圖 都是這兩種類的JAVA黨去做的 在基底activity設定rect 只要點到該畫面的該rect就會做動作或切換貼上另一張圖 一直下去 超過50M 就會出現OOM的錯誤

而且我觀察LOGCAT她一開始貼上第一張圖就超過14M 一直貼圖就會慢慢累加到報表 我都有把不到的圖層java黨設成NULL 但只會只會淺少一點 抵不過增加的記憶體...

package com.example.test03;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MenuView extends SurfaceView implements SurfaceHolder.Callback
{
        Test1 father;                //Activity的引用

        MenuDrawThread mdt;                        //後臺重繪執行緒

       
        Bitmap bmpback;                                        //背景圖片
        Bitmap bmpt11b;                                        //test1button pic
        Bitmap bmpt12b;
        Bitmap bmpt13b;
        Bitmap bmpt2b;
        Bitmap bmpt3b;
        Bitmap bmpsignin;
        Bitmap bmptopic;                                //topic pic
       
       
       
        public MenuView(Test1 father)
        {
               
                super(father);
                getHolder().addCallback(this);
                this.father = father;
               
               

                mdt = new MenuDrawThread(this,getHolder());                        //新建WelcomeDrawThread物件
               
                initBitmap(father);                                                        //初始化圖片
                               
               
        }
       
        public void initBitmap(Context context)
        {
               
                Resources r = context.getResources();                        //獲取Resources物件
               
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize = 1;
               
                bmpback =  BitmapFactory.decodeResource(r, R.drawable.menuback , options);
                bmpt11b = BitmapFactory.decodeResource(r, R.drawable.eyebutton , options);
                bmpt12b= BitmapFactory.decodeResource(r, R.drawable.earbutton , options);
                bmpt13b = BitmapFactory.decodeResource(r, R.drawable.eyeearbutton , options);
               
        }
       
        public void doDraw(Canvas canvas) //方法:用於根據不同狀態繪製螢幕
        {
                //Paint paint = new Paint();                //新建畫筆
               
                canvas.drawBitmap(bmpback, 0, 0, null);               
               
                if(father.flag1)
                {
                canvas.drawBitmap(bmpt11b, 250 , 250, null);
                }
               
                if(father.flag2)
                {
                canvas.drawBitmap(bmpt12b, 250 , 400, null);
                }
               
                if(father.flag3)
                {
                canvas.drawBitmap(bmpt13b, 250, 550, null);
                }
               
               
        }
       

        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                        int height)
        {                               
                //覆寫surfaceChanged方法
        }
        public void surfaceCreated(SurfaceHolder holder)
        {                        //覆寫surfaceCreated方法
               

                if(!mdt.isAlive()){                        //啟動後臺繪製執行緒
                        mdt.start();
                }
        }
        public void surfaceDestroyed(SurfaceHolder holder)
        {                //覆寫surfaceDestroyed方法

                if(mdt.isAlive()){                                //停止後臺繪製執行緒
                        mdt.flag = false;
                }               
        }       
       
       
}





package com.example.test03;

import android.graphics.Canvas;                                //引入相關類別
import android.view.SurfaceHolder;                        //引入相關類別
/*
* 該類別繼承自Thread,主要負責定時更新WelcomeView
*/
public class MenuDrawThread extends Thread{
        MenuView father;                                        //WelcomeView物件的引用
        SurfaceHolder surfaceHolder;                //WelcomeView物件的SurfaceHolder
        int sleepSpan = 100;                                //休眠時間
        boolean flag;                                                //執行緒執行旗標位元
        //建構式:初始化主要的成員變數
        public MenuDrawThread(MenuView father,SurfaceHolder surfaceHolder){
                this.father = father;
                this.surfaceHolder = surfaceHolder;
                this.flag = true;
        }
        //方法:執行緒執行方法
        public void run(){
                Canvas canvas = null;                        //新建一個Canvas物件
                while(flag){
                        try{
                                canvas = surfaceHolder.lockCanvas(null);//為畫布加鎖
                                synchronized(surfaceHolder){
                                        father.doDraw(canvas);                                //重新繪製螢幕
                                }
                        }
                        catch(Exception e){
                                e.printStackTrace();//捕獲異常並列印
                        }
                        finally{
                                if(canvas != null){//釋放畫布並將其傳回
                                        surfaceHolder.unlockCanvasAndPost(canvas);
                                }
                        }
                        try{
                                Thread.sleep(sleepSpan);                //休眠一段時間
                        }
                        catch(Exception e){
                                e.printStackTrace();                        //捕獲異常並列印
                        }
                }
        }
}
用Android 就來Android 台灣中文網(https://apk.tw)
回覆 支持 反對

使用道具 舉報

您需要登錄後才可以回帖 登錄 | 註冊

本版積分規則