ロード画像OOM問題まとめ

20397 ワード

画像oom問題のロード
1、OOMが現れるシーンと原因
シーンは次のとおりです.
123、        

主な原因:
1、         APP        ,   16M,        ,     ,      。
2、 Android                   , Android2.3         ARGB_8888,            4      。            。

2、どのように大きい図のロードの問題を解決します
実際に画像をロードするときは、元の大きな図をロードすることはめったにありません.一般的には、スケールでサンプリングしてスケールします.これにより、メモリを節約し、画像が歪まないことを保証します.具体的な実施手順は以下の通りである.
(1)、ピクチャの内容をロードしない上で、ピクチャを復号してピクチャのサイズ情報を得る
ここで必要なBitmapFactoryのdecodeシリーズメソッドとBitmapFactory.Options.decodeシリーズメソッドを使用してピクチャをロードする場合は、OptionsのinJustDecodeBoundsプロパティをtrueに設定する必要があります.
 BitmapFactory.Options options = new BitmapFactory.Options();
 options.inJustDecodeBounds=true;
 BitmapFactory.decodeFile(path, options);

(2)、取得したピクチャのサイズと、インタフェースに表示するサイズからスケーリングを計算する
public int calculateInSampleSize(BitmapFactory.Options options,
            int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {
            if (width > height) {
                inSampleSize = Math.round((float) height / (float) reqHeight);
            } else {
                inSampleSize = Math.round((float) width / (float) reqWidth);
            }
        }
        return inSampleSize;
    }

(3)、計算されたスケールに基づいて画像を拡大・縮小する
//         
 options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
 options.inJustDecodeBounds = false;
 Bitmap bitmap= BitmapFactory.decodeFile(path, options);

3、大量ロード大図
まず、インタフェースに表示される画像コントロールのサイズに基づいてスケールを決定します.
public class PhotoWallAdapter extends ArrayAdapter implements OnScrollListener {
 
    /**
     *                 。
     */
    private Set taskCollection;
 
    /**
     *           ,            ,                         。
     */
    private LruCache mMemoryCache;
 
    /**
     * GridView   
     */
    private GridView mPhotoWall;
 
    /**
     *           
     */
    private int mFirstVisibleItem;
 
    /**
     *           
     */
    private int mVisibleItemCount;
 
    /**
     *          ,             ,         。
     */
    private boolean isFirstEnter = true;
 
    public PhotoWallAdapter(Context context, int textViewResourceId, String[] objects,
            GridView photoWall) {
        super(context, textViewResourceId, objects);
        mPhotoWall = photoWall;
        taskCollection = new HashSet();
        //             
        int maxMemory = (int) Runtime.getRuntime().maxMemory();
        int cacheSize = maxMemory / 8;
        //                   1/8
        mMemoryCache = new LruCache(cacheSize) {
            @Override
            protected int sizeOf(String key, Bitmap bitmap) {
                return bitmap.getByteCount();
            }
        };
        mPhotoWall.setOnScrollListener(this);
    }
 
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final String url = getItem(position);
        View view;
        if (convertView == null) {
            view = LayoutInflater.from(getContext()).inflate(R.layout.photo_layout, null);
        } else {
            view = convertView;
        }
        final ImageView photo = (ImageView) view.findViewById(R.id.photo);
        //  ImageView    Tag,             
        photo.setTag(url);
        setImageView(url, photo);
        return view;
    }
 
    /**
     *  ImageView    。   LruCache        ,   ImageView 。  LruCache         ,
     *   ImageView        。
     * 
     * @param imageUrl
     *               URL  ,    LruCache  。
     * @param imageView
     *                     。
     */
    private void setImageView(String imageUrl, ImageView imageView) {
        Bitmap bitmap = getBitmapFromMemoryCache(imageUrl);
        if (bitmap != null) {
            imageView.setImageBitmap(bitmap);
        } else {
            imageView.setImageResource(R.drawable.empty_photo);
        }
    }
 
    /**
     *         LruCache 。
     * 
     * @param key
     *            LruCache  ,       URL  。
     * @param bitmap
     *            LruCache  ,           Bitmap  。
     */
    public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
        if (getBitmapFromMemoryCache(key) == null) {
            mMemoryCache.put(key, bitmap);
        }
    }
 
    /**
     *  LruCache       ,        null。
     * 
     * @param key
     *            LruCache  ,       URL  。
     * @return       Bitmap  ,  null。
     */
    public Bitmap getBitmapFromMemoryCache(String key) {
        return mMemoryCache.get(key);
    }
 
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        //   GridView         ,GridView              
        if (scrollState == SCROLL_STATE_IDLE) {
            loadBitmaps(mFirstVisibleItem, mVisibleItemCount);
        } else {
            cancelAllTasks();
        }
    }
 
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
            int totalItemCount) {
        mFirstVisibleItem = firstVisibleItem;
        mVisibleItemCount = visibleItemCount;
        //         onScrollStateChanged   ,        onScrollStateChanged     ,
        //
        if (isFirstEnter && visibleItemCount > 0) {
            loadBitmaps(firstVisibleItem, visibleItemCount);
            isFirstEnter = false;
        }
    }
 
    /**
     *   Bitmap  。     LruCache           ImageView Bitmap  ,
     *         ImageView Bitmap       ,             。
     * 
     * @param firstVisibleItem
     *                  ImageView   
     * @param visibleItemCount
     *                       
     */
    private void loadBitmaps(int firstVisibleItem, int visibleItemCount) {
        try {
            for (int i = firstVisibleItem; i < firstVisibleItem + visibleItemCount; i++) {
                String imageUrl = Images.imageThumbUrls[i];
                Bitmap bitmap = getBitmapFromMemoryCache(imageUrl);
                if (bitmap == null) {
                    BitmapWorkerTask task = new BitmapWorkerTask();
                    taskCollection.add(task);
                    task.execute(imageUrl);
                } else {
                    ImageView imageView = (ImageView) mPhotoWall.findViewWithTag(imageUrl);
                    if (imageView != null && bitmap != null) {
                        imageView.setImageBitmap(bitmap);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    /**
     *                 。
     */
    public void cancelAllTasks() {
        if (taskCollection != null) {
            for (BitmapWorkerTask task : taskCollection) {
                task.cancel(false);
            }
        }
    }
 
    /**
     *          。
     * 
     * @author guolin
     */
    class BitmapWorkerTask extends AsyncTask {
 
        /**
         *    URL  
         */
        private String imageUrl;
 
        @Override
        protected Bitmap doInBackground(String... params) {
            imageUrl = params[0];
            //          
            Bitmap bitmap = downloadBitmap(params[0]);
            if (bitmap != null) {
                //           LrcCache 
                addBitmapToMemoryCache(params[0], bitmap);
            }
            return bitmap;
        }
 
        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            //   Tag     ImageView  ,           。
            ImageView imageView = (ImageView) mPhotoWall.findViewWithTag(imageUrl);
            if (imageView != null && bitmap != null) {
                imageView.setImageBitmap(bitmap);
            }
            taskCollection.remove(this);
        }
 
        /**
         *   HTTP  ,   Bitmap  。
         * 
         * @param imageUrl
         *               URL  
         * @return     Bitmap  
         */
        private Bitmap downloadBitmap(String imageUrl) {
            Bitmap bitmap = null;
            HttpURLConnection con = null;
            try {
                URL url = new URL(imageUrl);
                con = (HttpURLConnection) url.openConnection();
                con.setConnectTimeout(5 * 1000);
                con.setReadTimeout(10 * 1000);
                bitmap = BitmapFactory.decodeStream(con.getInputStream());
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (con != null) {
                    con.disconnect();
                }
            }
            return bitmap;
        }
 
    }
 
}

LruCacheを使用してピクチャをキャッシュするので、メモリオーバーフローの心配はありません.LruCacheに格納されているピクチャの合計サイズが容量上限に達すると、最近最も少ないピクチャが自動的にキャッシュから削除されます.
 
転載先:https://www.cnblogs.com/zxpy/p/10563744.html