最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android Bitmap的加載優(yōu)化與Cache相關(guān)介紹

 更新時間:2017年02月10日 10:07:06   投稿:daisy  
這篇文章主要介紹了Android中性能優(yōu)化之Bitmap的加載優(yōu)化與Cache相關(guān)內(nèi)容介紹,文中介紹的很詳細,對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。

一 . 高效加載 Bitmap

BitMapFactory 提供了四類方法: decodeFile,decodeResource,decodeStream 和 decodeByteArray 分別用于從文件系統(tǒng),資源,輸入流以及字節(jié)數(shù)組中加載出一個 Bitmap 對象。

高效加載 Bitmap 很簡單,即采用 BitMapFactory.options 來加載所需要尺寸圖片。BitMapFactory.options 就可以按照一定的采樣率來加載縮小后的圖片,將縮小后的圖片置于 ImageView 中顯示。

通過采樣率即可高效的加載圖片,遵循如下方式獲取采樣率:

  1. BitmapFactory.Options 的 inJustDecodeBounds 參數(shù)設(shè)置為 true 并加載圖片
  2. BitmapFactory.Options 中取出圖片的原始寬高信息,即對應于 outWidth 和 outHeight 參數(shù)
  3. 根據(jù)采樣率的規(guī)則并結(jié)合目標 View 的所需大小計算出采樣率 inSampleSize
  4. BitmapFactory.Options 的 injustDecodeBounds 參數(shù)設(shè)置為 false,然后重新加載圖片

過上述四個步驟,加載出的圖片就是最終縮放后的圖片,當然也有可能沒有縮放。

代碼實現(xiàn)如下:

public Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
 // First decode with inJustDecodeBounds=true to check dimensions
 final BitmapFactory.Options options = new BitmapFactory.Options();
 options.inJustDecodeBounds = true;
 BitmapFactory.decodeResource(res, resId, options);

 // Calculate inSampleSize
 options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

 // Decode bitmap with inSampleSize set
 options.inJustDecodeBounds = false;
 return BitmapFactory.decodeResource(res, resId, options);
}

public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
 if (reqWidth == 0 || reqHeight == 0) {
  return 1;
 }

 // Raw height and width of image
 final int height = options.outHeight;
 final int width = options.outWidth;
 Log.d(TAG, "origin, w= " + width + " h=" + height);
 int inSampleSize = 1;

 if (height > reqHeight || width > reqWidth) {
  final int halfHeight = height / 2;
  final int halfWidth = width / 2;

  // Calculate the largest inSampleSize value that is a power of 2 and
  // keeps both height and width larger than the requested height and width.
  while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {
   inSampleSize *= 2;
  }
 }

 Log.d(TAG, "sampleSize:" + inSampleSize);
 return inSampleSize;
}

實際使用就可以像下面這樣了,如加載 100*100 的圖片大小,就可以像下面這樣高效的加載圖片了:

mImageView.setImageBitmap(
decodeSampledBitmapFromResource(getResource(),R.id.myimage,100,100));

二 . Android 中的緩存策略

目前常用的算法是 LRU,即近期最少使用算法,當緩存存滿時,會優(yōu)先淘汰近期最少使用的緩存對象

2.1 LruCache

LruCache 是一個泛型類,其內(nèi)部實現(xiàn)機制是 LinkedHashMap 以強引用的方式存儲外部的緩存對象,提供了 get() put() 來完成緩存對象的存取。當緩存滿了,移除較早的緩存對象,再添加新的。LruCache 是線程安全的。

  1. 強引用:直接的對象引用
  2. 軟引用:當一個對象只有軟引用時,系統(tǒng)內(nèi)存不足時,會被 gc 回收
  3. 弱引用:當一個對象只有弱引用時,隨時會被回收

2.2 DiskLriCache

DiskLruCache 用于實現(xiàn)存儲設(shè)備緩存,即磁盤緩存。

2.2.1 DiskLruCache 的創(chuàng)建

由于它不屬于 Android SDK的一部分,所以不能通過構(gòu)造方法來創(chuàng)建,提供了 open() 方法用于自身的創(chuàng)建

public static DiskLruCache open(File directory,int appversion,int valueCount,long maxSize);

典型的 DiskLruCache 的創(chuàng)建過程

private static final Disk_CACHE_SIZE = 1024*1024*50;//50M

File diskCaCheDir = getDiskCacheDir(mContext,"bitmap");
if(!diskCacheDir.exists()){
 diskCacheDir.mkdirs();
}
mDiskLruCache = DiskLruCache.open(diskCaCheDir,1,1,Disk_CACHE_SIZE);

第三個參數(shù)表示單個節(jié)點所對應的數(shù)據(jù),一般設(shè)置為1即可。

2.2.2 DiskLruCache 的緩存添加 緩存的添加操作是通過 Editor 完成的, Editor 表示一個緩存對象的編輯對象。DiskLruCache 不允許同時編輯一個緩存對象。

2.2.3 DiskLruCache 的緩存查找

緩存查找過程也需要將 url 轉(zhuǎn)換為 key,通過 DiskLruCache 的 get() 得到一個 Snapshot 對象,然后通過該對象即可得到緩存的文件輸入流,得到文件輸入流即可得到 Bitmap 對象了。為了避免加載過程中 OOM,一般不會直接加載原始圖片。在前面介紹通過 BitmapFactory.Options 來加載一張縮放后的圖片,但是那種方法對 FileInputStream 的縮放存在問題,原因是 FileInputStream 是一種有序的文件流,而兩次 decodeStream 調(diào)用影響了文件流的位置屬性,導致了第二次 decodeStream 時得到的是 null。為了解決這個問題,可以通過文件流得到其對應的文件描述符,然后通過 BitmapFactory.decodeFileDescriptor 方法來加載一張縮放過后的圖片。

 Bitmap bitmap = null;
 String key = hashKeyFormUrl(url);
 DiskLruCache.Snapshot snapShot = mDiskLruCache.get(key);
  if (snapShot != null) {
   FileInputStream fileInputStream = (FileInputStream)snapShot.getInputStream(DISK_CACHE_INDEX);
   // 獲取文件描述符
   FileDescriptor fileDescriptor = fileInputStream.getFD();
   // 通過 BitmapFactory.decodeFileDescriptor 來加載一張縮放后的圖片
   bitmap = mImageResizer.decodeSampledBitmapFromFileDescriptor(fileDescriptor,
     reqWidth, reqHeight);
   if (bitmap != null) {
    addBitmapToMemoryCache(key, bitmap);
   }
  }

  return bitmap;
 }

三 . ImageLoader 的實現(xiàn)

具備的功能,即圖片的同步加載,異步加載,圖片的壓縮,內(nèi)存緩存,磁盤緩存以及網(wǎng)絡(luò)拉取。

3.1 圖片壓縮功能

如前面所述。

3.2 內(nèi)存緩存和磁盤緩存的實現(xiàn)

選擇 LruCache 和 DiskLruCache 來分別完成內(nèi)存緩存和磁盤緩存的工作

3.3 同步加載和異步加載的接口設(shè)計

關(guān)于同步加載:從 loadBitmap 的實現(xiàn)可以看出,其工作過程遵循如下幾個步驟:先試著從內(nèi)存緩存中讀取圖片,接著從磁盤緩存中讀取圖片,最后試著從網(wǎng)絡(luò)拉取圖片。另外該方法不能在主線程中調(diào)用,否則就會拋出異常。因為加載圖片是一個耗時的操作。

關(guān)于異步加載:從 bindBitmap 中可以看出,binfBitmap 會先試著從內(nèi)存緩存中讀取結(jié)果,如果成功就直接返回,否則會從線程池中去調(diào)用 loadBitmap() ,當加載成功后,再講圖片,圖片地址以及需要綁定的 ImageView 封裝成一個 loaderResult 對象,通過 mMainHandler 向主線程發(fā)送一個消息,這樣就可以在主線程中給 ImageView 設(shè)置圖片了。圖片的異步加載是一個很有用的功能,很多時候調(diào)用者不想在單獨的線程中以同步的方式來加載圖片,并將圖片設(shè)置給需要的 ImageVIew, 從而ImageLoader 內(nèi)部需要自己需要在內(nèi)部線程中加載圖片,并且將圖片設(shè)置給所需要的 ImageView。

ImageLoader源碼可以點擊這里:下載 查看ImageLoader的實現(xiàn)

四 . ImageLoader 的使用

核心是 ImageAdapter , 其中的 getView() 的核心方法如下:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
   ViewHolder holder = null;
   if (convertView == null) {
    convertView = mInflater.inflate(R.layout.image_list_item,parent, false);
    holder = new ViewHolder();
    holder.imageView = (ImageView) convertView.findViewById(R.id.image);
    convertView.setTag(holder);
   } else {
    holder = (ViewHolder) convertView.getTag();
   }
   ImageView imageView = holder.imageView;
   final String tag = (String)imageView.getTag();
   final String uri = getItem(position);
   if (!uri.equals(tag)) {
    imageView.setImageDrawable(mDefaultBitmapDrawable);
   }
   if (mIsGridViewIdle && mCanGetBitmapFromNetWork) {
    imageView.setTag(uri);
    // 這句話將圖片的復雜加載過程交給 ImageLoader 了
    mImageLoader.bindBitmap(uri, imageView, mImageWidth, mImageWidth);
   }
   return convertView;
  }

對于上述代碼 ImageAdapter 來說, ImageLoader 的加載圖片的復雜過程,更不需要知道。

優(yōu)化列表卡頓現(xiàn)象:

  1. 不要在 getView() 中做加載圖片的操作,那樣肯定會耗時,像這個例子中一樣,交給 ImageLoaer 來實現(xiàn)。
  2. 控制異步加載頻率, 如果用戶刻意的頻繁的上下滑動,可能在一瞬間加載幾百個異步任務,這樣會給線程池造成擁堵。解決的辦法是考慮在用戶滑動列表時,停止加載圖片。等到列表停下來時,在進行異步加載任務。
  3. 開啟硬件加速:給Activity添加配置android:hardwareAccelerated=”true”

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對給我Android開發(fā)者們能帶來一定的幫助,如果有疑問大家可以留言交流。

相關(guān)文章

  • android開發(fā)中獲取手機分辨率大小的方法

    android開發(fā)中獲取手機分辨率大小的方法

    不管是在我們的布局還是在實現(xiàn)代碼中進行操控,我們的靈活性都不是局限于一個固定的數(shù)值,而是面對不同的手機對象都有一個適應的數(shù)值。
    2013-04-04
  • android預置默認的語音信箱號碼具體實現(xiàn)

    android預置默認的語音信箱號碼具體實現(xiàn)

    在此介紹以xml的方式預置VM number的方法,以及如何允許用戶去修改并能夠記住用戶的選擇
    2013-06-06
  • Android開發(fā)高級組件之自動完成文本框(AutoCompleteTextView)用法示例【附源碼下載】

    Android開發(fā)高級組件之自動完成文本框(AutoCompleteTextView)用法示例【附源碼下載】

    這篇文章主要介紹了Android開發(fā)高級組件之自動完成文本框(AutoCompleteTextView)用法,簡單描述了自動完成文本框的功能并結(jié)合實例形式分析了Android實現(xiàn)自動完成文本框功能的具體步驟與相關(guān)操作技巧,并附帶源碼供讀者下載參考,需要的朋友可以參考下
    2018-01-01
  • Android中Service和Activity相互通信示例代碼

    Android中Service和Activity相互通信示例代碼

    在android中Activity負責前臺界面展示,service負責后臺的需要長期運行的任務。下面這篇文章主要給大家介紹了關(guān)于Android中Service和Activity相互通信的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-09-09
  • Android10 App 啟動分析進程創(chuàng)建源碼解析

    Android10 App 啟動分析進程創(chuàng)建源碼解析

    這篇文章主要為大家介紹了Android10 App啟動分析進程創(chuàng)建源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • android viewpager實現(xiàn)豎屏滑動效果

    android viewpager實現(xiàn)豎屏滑動效果

    這篇文章主要為大家詳細介紹了android viewpager實現(xiàn)豎屏滑動效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • android實現(xiàn)Splash閃屏效果示例

    android實現(xiàn)Splash閃屏效果示例

    這篇文章主要介紹了android實現(xiàn)Splash閃屏效果的方法,涉及Android中postDelayed方法及AndroidManifest.xml權(quán)限控制的相關(guān)使用技巧,需要的朋友可以參考下
    2016-08-08
  • Flutter 日期時間DatePicker控件及國際化

    Flutter 日期時間DatePicker控件及國際化

    這篇文章主要介紹了Flutter 日期時間DatePicker控件及國際化,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-03-03
  • Android BroadcastReceiver廣播機制概述

    Android BroadcastReceiver廣播機制概述

    這篇文章主要為大家詳細介紹了Android BroadcastReceiver廣播機制,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-08-08
  • Android實現(xiàn)蒙板效果

    Android實現(xiàn)蒙板效果

    這篇文章主要為大家詳細介紹了Android實現(xiàn)蒙板效果的關(guān)鍵性代碼,感興趣的小伙伴們可以參考一下
    2016-04-04

最新評論

芦溪县| 铅山县| 隆林| 栖霞市| 梨树县| 秀山| 山丹县| 武义县| 罗平县| 商水县| 冕宁县| 巫溪县| 马鞍山市| 浦城县| 万山特区| 台东市| 平陆县| 平定县| 长寿区| 溧阳市| 岫岩| 万盛区| 安阳市| 台南县| 镇雄县| 苍梧县| 原阳县| 奉贤区| 佳木斯市| 隆尧县| 乡城县| 综艺| 彭山县| 洱源县| 惠安县| 广水市| 开鲁县| 北票市| 紫金县| 伽师县| 永修县|