Android从文件读取图像显示的效率问题
因为从文件读取图像到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从文件读取图像显示的效率问题的更多相关文章
- Android 12(S) 图像显示系统 - SurfaceFlinger 之 VSync - 中篇(十七)
必读: Android 12(S) 图像显示系统 - 开篇 1 前言 这一篇文章,将继续讲解有关VSync的知识,前一篇文章 Android 12(S) 图像显示系统 - SurfaceFlinger ...
- Android 12(S) 图像显示系统 - GraphicBuffer同步机制 - Fence
必读: Android 12(S) 图像显示系统 - 开篇 一.前言 前面的文章中讲解Android BufferQueue的机制时,有遇到过Fence,但没有具体讲解.这篇文章,就针对Fence这种 ...
- Android 12(S) 图像显示系统 - drm_hwcomposer 简析(上)
必读: Android 12(S) 图像显示系统 - 开篇 前言 Android源码中有包含drm_hwcomposer:/external/drm_hwcomposer/ drm_hwcompose ...
- Loadrunner 脚本开发-从文件读取数据并参数化
脚本开发-从文件读取数据并参数化 by:授客 QQ:1033553122 直接上代码: char* testfn() { int count, total = 0; //char buffer[1 ...
- JMeter 参数化之利用CSV Data Set Config从文件读取参数并关联变量
参数化之利用CSV Data Set Config从文件读取参数并关联变量 by:授客 QQ:1033553122 1. 添加CSV Data Set Config 右键线程组->配置元 ...
- 使用file_get_contents()和curl()抓取网络资源的效率对比
使用file_get_contents()和curl()抓取网络资源的效率对比 在将小程序用户头像合成海报的时候,用到了抓取用户头像对应的网络资源,那么抓取方式有很多,比如 file_get_cont ...
- Java简单从文件读取和输出
Java简单从文件读取和输出 用Scanner输入,用PrintStream输出 功能:从in.txt读入,输出到out.txt 代码: package ioTest; import java.io. ...
- logstash设置从文件读取的重要参数说明及如何强置重新读取
问题描述: 如果运行logstash时从文件读取数据时,就会遇到一个问题,如果读取的目标文件未经修改,而仅修改了conf文件,则即使重新运行logstash,或是执行时使用-r时输出也无法更新. 解决 ...
- 爬虫必知必会(6)_提升scrapy框架爬取数据的效率之配置篇
如何提升scrapy爬取数据的效率:只需要将如下五个步骤配置在配置文件中即可 增加并发:默认scrapy开启的并发线程为32个,可以适当进行增加.在settings配置文件中修改CONCURRENT_ ...
随机推荐
- 使用卷积神经网络CNN训练识别mnist
算的的上是自己搭建的第一个卷积神经网络.网络结构比较简单. 输入为单通道的mnist数据集.它是一张28*28,包含784个特征值的图片 我们第一层输入,使用5*5的卷积核进行卷积,输出32张特征图, ...
- poj1679(判断最小生成树是否唯一)
题意:给出n个点,m条边,要你判断最小生成树是否唯一. 思路:先做一次最小生成树操作,标记选择了的边,然后枚举已经被标记了的边,判断剩下的边组成的最小生成树是否与前面的相等,相等,则不唯一,否则唯一. ...
- java基础篇---正则表达式
正则表达式在许多语言,例如Perl.PHP.Python.JavaScript和JScript,都支持用正则表达式处理文本,一些文本编辑器用正则表达式实现高级“搜索-替换”功能. 正则表达式是一种可以 ...
- docker原理
Docker原理11 Linux Namespace 11 AUFS文件系统17 重新理解Docker的各种命令18 Docker原理 Linux Namespace docker是一个容器引擎,容器 ...
- Fine-tuning Convolutional Neural Networks for Biomedical Image Analysis: Actively and Incrementally如何使用尽可能少的标注数据来训练一个效果有潜力的分类器
作者:AI研习社链接:https://www.zhihu.com/question/57523080/answer/236301363来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载 ...
- Drupal 7 配置ckeditor和ckfinder编辑器实现图片上传--不用wysisyg
注意: 1.这里的ckeditor编辑器是独立模块,不是那个wysiwyg模块. 2.这里的图片上传仅仅为文章内图片,非字段图片. 1.下载文件(1) http://drupal.org/proj ...
- Apche Kafka 的生与死 – failover 机制详解
转自:http://www.cnblogs.com/fxjwind/p/4972244.html Kafka 作为 high throughput 的消息中间件,以其性能,简单和稳定性,成为当前实时流 ...
- “System Volume Information”文件夹里的NTFS木马(安全问题)
病毒保护伞 原因:由于NTFS的分区里该目录只有SYSTEM权限,导致杀毒软件没有权限查杀藏匿于该目录的病毒.(现在大多数软件都能查杀) 解决方案:阻止“System Volume Informati ...
- 树莓派 NOOBS 安装系统
Raspberry Pi Foundation发布了一个名为“New Out of Box Software”(NOOBS)的工具,可以用来方便的安装系统,让我们尝试一下这个新的安装工具. 以我的树莓 ...
- C语言课程设计-保安值班系统支持任意输入保安值班时间
//.cpp : Defines the entry point for the console application. // #include "string.h" #incl ...