詳談Android從文件讀取圖像顯示的效率問題
因為從文件讀取圖像到Bitmap是一件比較費時的事情,所以研究了一下幾種可行的辦法,并做了對比。
首先解釋一下為什么耗時,這是因為,在從jpg或者png文件中讀取Bitmap時,一來需要對外存進行操作并且圖像文件一般都比較大,二來在創(chuàng)建Bitmap時,基本都需要對原始圖像做操作,例如:降采樣、剪切、旋轉(zhuǎn)等等。所以如何高效的讀取圖片并呈現(xiàn)出來,是一個很值得研究的問題。
根據(jù)我的想法,大致想出了3種方案:
1、在當前的UI線程直接讀取并操作圖像,然后呈現(xiàn)。
2、新開一個子線程讀取并操作圖像,然后利用Bundle中Serializable的相關(guān)方法將其傳回UI線程并呈現(xiàn)。
3、其他做法與2一樣,但是利用的是Bundle中Parcelable的相關(guān)方法。
方法一
start_time = System.currentTimeMillis();
BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bitmap=BitmapFactory.decodeFile(path,options);
options.inSampleSize=calculateSize(options,width,height);
options.inJustDecodeBounds=false;
//整個圖像,下采樣
bitmap=BitmapFactory.decodeFile(path,options);
//部分圖像
Bitmap patch=Bitmap.createBitmap(bitmap, 10, 10, 100, 100);
end_time = System.currentTimeMillis();
Log.v("BitmapTest", "UI time consume:"+(end_time - start_time));
imageView.setImageBitmap(bitmap);
patchView.setImageBitmap(patch);
操作很簡單,先將圖片文件的尺寸等信息讀取出來, 然后根據(jù)其尺寸計算其縮放比例,并將圖片中的一部分剪切出來。最后將圖片顯示在ImageView空間上。大致測了幾十次,得到的平均消耗時間為:72.75ms
方法二
啟動子線程
start_time = System.currentTimeMillis(); String path=Environment.getExternalStorageDirectory().getPath()+File.separator+"image1.jpg"; ImgThread imgThread=new ImgThread(msgHandler,path,width,height); imgThread.start();
子線程中的操作,與1基本相同
BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bitmap=BitmapFactory.decodeFile(path,options);
options.inSampleSize=calculateSize(options,width,height);
options.inJustDecodeBounds=false;
//整個圖像,下采樣
bitmap=BitmapFactory.decodeFile(path,options);
//部分圖像
Bitmap patch=Bitmap.createBitmap(bitmap, 10, 10, 100, 100);
array=new ArrayList<Bitmap>(2);
array.add(bitmap);
array.add(patch);
//Serializable傳遞
Bundle bundle=new Bundle();
bundle.putSerializable("img", array);
//Parcelable傳遞
/*
MyList l=new MyList(Parcel.obtain());
l.array=array;
bundle.putParcelable("img", l);
*/
Message msg= new Message();
msg.what=1;
msg.setData(bundle);
handler.sendMessage(msg);
將Bitmap傳回到UI線程并呈現(xiàn)
Bundle bundle=msg.getData();
//Serializable傳遞
ArrayList<Bitmap> array=(ArrayList<Bitmap>) bundle.getSerializable("img");
//Parcelable傳遞
//MyList l=(MyList)bundle.getParcelable("img");
//ArrayList<Bitmap> array=l.array;//=(ArrayList<Bitmap>) bundle.getParcelable("img");
Bitmap bitmap=array.get(0);
Bitmap patch=array.get(1);
end_time = System.currentTimeMillis();
Log.v("BitmapTest", "Th time consume:"+(end_time - start_time));
imageView.setImageBitmap(bitmap);
patchView.setImageBitmap(patch);
方法二的平均消耗時間為:83.93ms
方法三
該方法需要新建一個類用來實現(xiàn)Parcelable接口
package com.example.bitmaptest;
import java.util.ArrayList;
import android.os.Parcel;
import android.os.Parcelable;
public class MyList implements Parcelable{
public ArrayList array;
public MyList(Parcel in)
{
in.readValue(null);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(array);
}
public static final Parcelable.Creator<MyList> CREATOR = new Parcelable.Creator<MyList>() {
@Override
public MyList createFromParcel(Parcel source) {
return new MyList(source);
}
@Override
public MyList[] newArray(int size) {
return new MyList[size];
}
};
}
在子線程中的操作
//Parcelable傳遞
MyList l=new MyList(Parcel.obtain());
l.array=array;
bundle.putParcelable("img", l);
方法三的平均消耗時間為:87.35ms
結(jié)果分析
三種方法都是在魅族MX1型號的手機上測試的,理論上方法三應(yīng)該比方法二快,但至少根據(jù)我的實驗結(jié)果來看,在傳送小數(shù)據(jù)量時(圖像大概是幾mB或幾百kB),數(shù)據(jù)的傳遞耗時并不是關(guān)鍵,兩種方法的耗時差不多。方法一由于沒有使用線程間的數(shù)據(jù)傳遞,因此耗時是最少的。
因此,我總結(jié)得到如下結(jié)論:
1、如果必須等到圖像加載完成才允許用戶操作的這種場景,可以直接在UI線程做圖像的操作,這時可以添加一個ProgressDialog用來提示正在加載。
2、如果需要一邊允許用戶操作一邊加載圖像的話,應(yīng)該新開一個子線程,但是在數(shù)據(jù)量不大的情況下,Serializable和Parcelable差距不大。
3、總而言之,圖像的尺寸和數(shù)量不大時,在UI線程直接做圖像讀取等操作即可,但比較大時還是最好開個子線程。
以上這篇詳談Android從文件讀取圖像顯示的效率問題就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Android使用Notification實現(xiàn)通知功能
這篇文章主要為大家詳細介紹了Android使用Notification實現(xiàn)通知功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-11-11
代碼從windows下visual studio到andriod平臺遷移實現(xiàn)步驟
這篇文章主要介紹了代碼從windows下visual studio到andriod平臺遷移的修改記錄的相關(guān)資料,需要的朋友可以參考下2017-01-01
Android?Jetpack組件中LifeCycle作用詳細介紹
Jetpack是谷歌在Google?I/O?2017大會上發(fā)布一套幫助開發(fā)者解決Android架構(gòu)設(shè)計的方案,而Lifecycle是Jetpack?architecture下的一部分,一起來看一下Lifecycle的使用及原理分析2022-09-09

