博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Multithreading For Performance
阅读量:4625 次
发布时间:2019-06-09

本文共 4750 字,大约阅读时间需要 15 分钟。

阅读:http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html

 

文章通过一个图像下载器来说明:

下载代码:

static Bitmap downloadBitmap(String url) {    final AndroidHttpClient client = AndroidHttpClient.newInstance("Android");    final HttpGet getRequest = new HttpGet(url);    try {        HttpResponse response = client.execute(getRequest);        final int statusCode = response.getStatusLine().getStatusCode();        if (statusCode != HttpStatus.SC_OK) {             Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url);             return null;        }                final HttpEntity entity = response.getEntity();        if (entity != null) {            InputStream inputStream = null;            try {                inputStream = entity.getContent();                 final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);                return bitmap;            } finally {                if (inputStream != null) {                    inputStream.close();                  }                entity.consumeContent();            }        }    } catch (Exception e) {        // Could provide a more explicit error message for IOException or IllegalStateException        getRequest.abort();        Log.w("ImageDownloader", "Error while retrieving bitmap from " + url, e.toString());    } finally {        if (client != null) {            client.close();        }    }    return null;}

上面使用了AndroidHttpClient,然后这个类并不支持在main线程中执行,所以最好使用DefaultHttpClient 。

如果获取成功了,response的entity就会包含了图像的流,然后通过Bitmap的decoded获取图像。

 

接下来使用了AsyncTask进行下载:

class BitmapDownloaderTask extends AsyncTask
{ private String url; private final WeakReference
imageViewReference; public BitmapDownloaderTask(ImageView imageView) { imageViewReference = new WeakReference
(imageView); } @Override // Actual download method, run in the task thread protected Bitmap doInBackground(String... params) { // params comes from the execute() call: params[0] is the url. return downloadBitmap(params[0]); } @Override // Once the image is downloaded, associates it to the imageView protected void onPostExecute(Bitmap bitmap) { if (isCancelled()) { bitmap = null; } if (imageViewReference != null) { ImageView imageView = imageViewReference.get(); if (imageView != null) { imageView.setImageBitmap(bitmap); } } }}

onPostExecute将在UI线程中进行。

值得一提的是这个WeakReference,它声明了一个弱引用,因为在下载过程中,有可能Activity被销毁导致View消失,这也就是为什么我们在VIEW装入bitmap的时候需要检测是否为NULL了。

 

如果此时你仅仅是下载一个图片,那么看到这里就行了。但是如果考虑到当你使用listview的时候,上面的待会可能会导致这样的情况:

你有三个listview,分别是L1,L2,L3,你希望的结果是这三个listview分别绑定图片A,B,C。

但是如果使用上面的代码有可能的结果就是:L1 L2 L3绑定的图片顺序是: A C B。

出现这种情况的原因在于,onPostExecute只是在每次doInBackground之后再UI线程中运行的代码,有可能B的图片较大而C图片较小,导致绑定了L2的TASK最后将先下载完的C填充到L2上面。

解决的办法,当然就是绑定。

static class DownloadedDrawable extends ColorDrawable {    private final WeakReference
bitmapDownloaderTaskReference; public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) { super(Color.BLACK); bitmapDownloaderTaskReference = new WeakReference
(bitmapDownloaderTask); } public BitmapDownloaderTask getBitmapDownloaderTask() { return bitmapDownloaderTaskReference.get(); }}
public void download(String url, ImageView imageView) {     if (cancelPotentialDownload(url, imageView)) {         BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);         DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);         imageView.setImageDrawable(downloadedDrawable);         task.execute(url, cookie);     }}

也就是说,绑定顺序是这样的:  imageView——》DownloadedDrawable ——》BitmapDownloaderTask ,而BitmapDownloaderTask 绑定了前面的imageView。

注意使用了WeakReference,使AsyncTask能够独立。

在AsyncTask里,需要实现这个方法:

 

private static BitmapDownloaderTask getBitmapDownloaderTask(ImageView imageView) {    if (imageView != null) {        Drawable drawable = imageView.getDrawable();        if (drawable instanceof DownloadedDrawable) {            DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;            return downloadedDrawable.getBitmapDownloaderTask();        }    }    return null;}

 

最后,在绑定的时候,使用下面的方法:

if (imageViewReference != null) {    ImageView imageView = imageViewReference.get();    BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);    // Change bitmap only if this process is still associated with it    if (this == bitmapDownloaderTask) {        imageView.setImageBitmap(bitmap);    }}

到此,一切完毕。不得不承认,同一个功能,好坏程序员写得就是不一样啊!

 

 

转载于:https://www.cnblogs.com/yutoulck/p/3389406.html

你可能感兴趣的文章
记因PHP的内存溢出导致的事故之解决
查看>>
[转]Apache commons 工具包应用
查看>>
Bridge模式——设计模式学习笔记
查看>>
【python】统一转换日期格式dateutil.parser.parse
查看>>
spring的依赖注入
查看>>
CF 576A 猜数
查看>>
『重构--改善既有代码的设计』读书笔记----代码坏味道【3】
查看>>
ABAP 中JSON格式的转换与解析
查看>>
使用oschina的gitserver
查看>>
嵌入式课程学习大纲分享,零基础入门嵌入式技术
查看>>
Could not get the value for parameter encoding for plugin execution default- resources
查看>>
Android 网络通信之Socket
查看>>
python 运维自动化之路 Day3
查看>>
wp打印输出日志
查看>>
MySQLDriverCS Exception: MySQLDriverCS Error: wrong query.No database selected
查看>>
MFC工程中不要#include <windows.h>,否则会出错。 from http://applehxb.blogbus.com/logs/48742135.html...
查看>>
深入探究VC —— 资源编译器rc.exe(3)【转】http://blog.csdn.net/wangningyu/article/details/4844687...
查看>>
解析json格式
查看>>
GridView取列值
查看>>
去掉ambiguous expansion of macro警告
查看>>