下面小编就为大家带来一篇详谈 Android 从文件读取图像显示的效率问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
Android 是一种基于 Linux 的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由 Google 公司和开放手机联盟领导及开发。尚未有统一中文名称,中国大陆地区较多人使用 "安卓" 或 "安致"。
因为从文件读取图像到 Bitmap 是一件比较费时的事情,所以研究了一下几种可行的办法,并做了对比。
首先解释一下为什么耗时,这是因为,在从 jpg 或者 png 文件中读取 Bitmap 时,一来需要对外存进行操作并且图像文件一般都比较大,二来在创建 Bitmap 时,基本都需要对原始图像做操作,例如:降采样、剪切、旋转等等。所以如何高效的读取图片并呈现出来,是一个很值得研究的问题。
根据我的想法,大致想出了 3 种方案:
1、在当前的 UI 线程直接读取并操作图像,然后呈现。
2、新开一个子线程读取并操作图像,然后利用 Bundle 中 Serializable 的相关方法将其传回 UI 线程并呈现。
3、其他做法与 2 一样,但是利用的是 Bundle 中 Parcelable 的相关方法。
方法一
- 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);
操作很简单,先将图片文件的尺寸等信息读取出来, 然后根据其尺寸计算其缩放比例,并将图片中的一部分剪切出来。最后将图片显示在 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 线程并呈现
- 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
方法三
该方法需要新建一个类用来实现 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
结果分析
三种方法都是在魅族 MX1 型号的手机上测试的,理论上方法三应该比方法二快,但至少根据我的实验结果来看,在传送小数据量时(图像大概是几 mB 或几百 kB),数据的传递耗时并不是关键,两种方法的耗时差不多。方法一由于没有使用线程间的数据传递,因此耗时是最少的。
因此,我总结得到如下结论:
1、如果必须等到图像加载完成才允许用户操作的这种场景,可以直接在 UI 线程做图像的操作,这时可以添加一个 ProgressDialog 用来提示正在加载。
2、如果需要一边允许用户操作一边加载图像的话,应该新开一个子线程,但是在数据量不大的情况下,Serializable 和 Parcelable 差距不大。
3、总而言之,图像的尺寸和数量不大时,在 UI 线程直接做图像读取等操作即可,但比较大时还是最好开个子线程。
以上这篇详谈 Android 从文件读取图像显示的效率问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持 PHPERZ。
来源: http://www.phperz.com/article/17/0319/326178.html