首页 > 系统 > Android > 正文

详谈Android从文件读取图像显示的效率问题

2019-12-12 03:25:46
字体:
来源:转载
供稿:网友

因为从文件读取图像到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从文件读取图像显示的效率问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表