国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

詳解Android_性能優化之ViewPager加載成百上千高清大圖oom解決方案

2019-12-12 04:10:47
字體:
來源:轉載
供稿:網友

一、背景

最近做項目需要用到選擇圖片上傳,類似于微信、微博那樣的圖片選擇器,ContentResolver讀取本地圖片資源并用RecyclerView+Glide加載圖片顯示就搞定列表的顯示,這個沒什么大問題,重點是,點擊圖片進入大圖瀏覽,比如你相冊有幾百張圖片,也就意味著在ViewPager中需要加載幾百個view,況且手機拍出來的圖片都是1-2千萬左右像素的高清大圖(筆者手機2千萬像素 也就是拍照出來的照片3888*5152),大小也有5-7個兆,ViewPager滑動不了十幾張就oom了,即是對圖片做了壓縮處理,把圖片分辨率降低至1366*960,大小壓縮至150k以下,并且在ViewPager的destroyItem方法做了bitmap資源的回收,雖然效果好了點,這也抵擋不了oom的降臨(網上查找的方案都是壓縮、使用第三方控件、回收,其實這都沒用,可能他們沒有真正體驗過ViewPager加載幾百上千張大圖的感受),瀏覽到了第50-70張的時候就oom了 內存一直暴漲,根本回收不了的,不信你們試試,壓縮和回收根本不能根治問題,那么怎么解決呢?研究了微信和微博,他們怎么也不會oom,最后我想到了一種解決方案。

二、方案實施

1、以往的普通做法

部分代碼:

List<SubsamplingScaleImageView> mViews = new ArrayList<>();          int size = mDatas.size();     for (int i = 0; i < size; i++) {       SubsamplingScaleImageView view = new SubsamplingScaleImageView(this);       mViews.add(view);     }      mBinding.viewpager.setAdapter(new MyAdapter()); 
class MyAdapter extends PagerAdapter {      @Override     public int getCount() {       return mDatas.size();     }      @Override     public boolean isViewFromObject(View view, Object object) {       return view == object;     }      @Override     public Object instantiateItem(ViewGroup container, final int position) {        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(           ViewPager.LayoutParams.MATCH_PARENT,ViewPager.LayoutParams.MATCH_PARENT);       final SubsamplingScaleImageView imageView = mViews.get(position);       imageView.setLayoutParams(params);        final String url = mDatas.get(position);       String cacheExists = cacheExists(url);       if(TextUtils.isEmpty(cacheExists)) {//沒緩存 需要壓縮(壓縮耗時 異步)         new AsyncTask<Void, Void, String>() {           @Override           protected String doInBackground(Void... voids) {             String cacheNoExistsPath = getCacheNoExistsPath(url);             BitmapCompressUtils.compressBitmap(url, cacheNoExistsPath);             File file = new File(cacheNoExistsPath);             if (file.exists()) {//存在表示成功               return cacheNoExistsPath;             } else {               return url;             }           }            @Override           protected void onPostExecute(String s) {             imageView.setImage(ImageSource.uri(s));           }          }.execute();         } else {//有緩存 直接顯示         imageView.setImage(ImageSource.uri(cacheExists));       }        container.addView(imageView);       return imageView;      }      @Override     public void destroyItem(ViewGroup container, int position, Object object) {        SubsamplingScaleImageView imageView = mViews.get(position);       if(imageView != null) {         imageView.recycle();       }        container.removeView(imageView);      }   } 
/**    * 判斷當前圖片url對應的壓縮過的緩存是否存在 ""表示不存在    *    * @param url 圖片路徑    * @return    */   private String cacheExists(String url) {     try {       File fileDir = new File(mCacheRootPath);       if(!fileDir.exists()) {         fileDir.mkdirs();       }        File file = new File(mCacheRootPath,new StringBuffer().append(MD5EncryptorUtils.md5Encryption(url)).toString());       if(file.exists()) {         return file.getAbsolutePath();       }     } catch (Exception e) {       e.printStackTrace();     }      return "";   }    public String getCacheNoExistsPath(String url) {     File fileDir = new File(mCacheRootPath);     if(!fileDir.exists()) {       fileDir.mkdirs();     }       return new StringBuffer().append(mCacheRootPath)         .append(MD5EncryptorUtils.md5Encryption(url)).toString();   } 

可以看到,這里筆者通過自己的壓縮算法(上一篇文章Android_NDK圖片壓縮之Libjpeg庫使用 )做了圖片壓縮,并緩存,細心的朋友應該有發現mViews集合添加的view個數是mDatas的size大小個數,這樣就會導致一個問題ViewPager一直向下滑動的時候,內存一直是增加的,即是做了資源回收,也是不能解決問題(況且筆者這里展示圖片的控件是SubsamplingScaleImageView 很不錯的大圖局部加載控件 能有效防止oom),大家可以試試,大量圖片的時候還是會oom,這得歸根于viewpager加載的圖片數量問題。

2、解決方案:

圖片壓縮也做了,資源回收也做了,但是ViewPager加載越來越多圖片的時候就會oom 你避免不了,不信你試試;

這里就要用到ViewPager的view的重用機制(自己理解的),也就是mViews我們固定給定個數量,如4,這樣ViewPager的i實際所需要的item也就只有4個。

修改后的部分代碼:

for (int i = 0; i < 4; i++) {       SubsamplingScaleImageView view = new SubsamplingScaleImageView(this);       mViews.add(view);     }      mBinding.viewpager.setAdapter(new MyAdapter()); 
class MyAdapter extends PagerAdapter {      @Override     public int getCount() {       return mDatas.size();     }      @Override     public boolean isViewFromObject(View view, Object object) {       return view == object;     }      @Override     public Object instantiateItem(ViewGroup container, final int position) {        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(           ViewPager.LayoutParams.MATCH_PARENT,ViewPager.LayoutParams.MATCH_PARENT);        int i = position % 4;       final SubsamplingScaleImageView imageView = mViews.get(i);       imageView.setLayoutParams(params);        final String url = mDatas.get(position);       String cacheExists = cacheExists(url);       if(TextUtils.isEmpty(cacheExists)) {//沒緩存 需要壓縮(壓縮耗時 異步)         new AsyncTask<Void, Void, String>() {           @Override           protected String doInBackground(Void... voids) {             String cacheNoExistsPath = getCacheNoExistsPath(url);             BitmapCompressUtils.compressBitmap(url, cacheNoExistsPath);             File file = new File(cacheNoExistsPath);             if (file.exists()) {//存在表示成功               return cacheNoExistsPath;             } else {               return url;             }           }            @Override           protected void onPostExecute(String s) {             imageView.setImage(ImageSource.uri(s));           }          }.execute();         } else {//有緩存 直接顯示         imageView.setImage(ImageSource.uri(cacheExists));       }        container.addView(imageView);       return imageView;      }      @Override     public void destroyItem(ViewGroup container, int position, Object object) {       int i = position % 4;       SubsamplingScaleImageView imageView = mViews.get(i);       if(imageView != null) {         imageView.recycle();       }        container.removeView(imageView);      } 

很簡單的修改 就能有效防止oom  利用position%4拿到第幾個控件從mViews取值,保證了viewpager加載的mViews存儲的圖片為4個

看一直向下滑動的內存走勢圖

內存基本維持穩定

三、demo演示

因為要讀取相冊就沒再模擬器運行錄制gif ,直接截圖


 

demo下載:demo

四、總結

這個只是簡單的演示,實際項目中的相冊比這個復雜多了,簡單說就是要壓縮,要回收,View重用。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 岳普湖县| 乡宁县| 廉江市| 景德镇市| 信阳市| 民丰县| 岑巩县| 大方县| 桃源县| 双城市| 南京市| 南投市| 龙川县| 丰原市| 柳江县| 夏河县| 彰武县| 邛崃市| 集贤县| 洛浦县| 阿尔山市| 通许县| 紫云| 华宁县| 剑阁县| 浙江省| 鹿泉市| 会东县| 宁德市| 新竹县| 石门县| 古蔺县| 贺兰县| 西乌珠穆沁旗| 扎赉特旗| 泸州市| 沁阳市| 沙湾县| 若羌县| 宜黄县| 额济纳旗|