zoukankan      html  css  js  c++  java
  • 线程方法Bitmap 处理之不要在UI主线程中处理Bitmap

    上班之余抽点时间出来写写博文,希望对新接触的朋友有帮助。今天在这里和大家一起学习一下线程方法

        原文链接 http://developer.android.com/intl/zh-CN/training/displaying-bitmaps/process-bitmap.html

        在用使BitmapFactory.decode*剖析图片时,最好不要在UI线主程中处置,因为图片的源来是未知的,有多是从硬盘取读的,也有多是是网络的图片源资,这时在剖析图片时,会有一些不可控的要素,如(网速较慢等),如果在UI线主中处置,就会有可能block线主程,从而致导用应无应相(ANR),会形成很欠好的用户体验。Android本身供提很多的方法,在非UI线程中处置一些比拟耗时的作操,如Handler,AsyncTask等,面下是用使AsyncTask的一种方法。

        

    用使AsyncTask

        

    AsyncTask供提了一种很简单的式方,在后台线程处置庞杂的作操,处置成完后之,会将处置后之的结果返回到UI线主程,详细的现实入下:

        


    class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> { 
    
       private final WeakReference<ImageView> imageViewReference;
    
       private int data = 0;
    
       public BitmapWorkerTask(ImageView imageView) {
    
           // Use a WeakReference to ensure the ImageView can be garbage collected
    
           imageViewReference = new WeakReference<ImageView>(imageView);
    
       }
    
       // Decode image in background.
    
       @Override
    
       protected Bitmap doInBackground(Integer... params) {
    
           data = params[0];
    
           return decodeSampledBitmapFromResource(getResources(), data, 100, 100));
    
       }
    
       // Once complete, see if ImageView is still around and set bitmap.
    
       @Override
    
       protected void onPostExecute(Bitmap bitmap) {
    
           if (imageViewReference != null && bitmap != null) {
    
               final ImageView imageView = imageViewReference.get();
    
               if (imageView != null) {
    
                   imageView.setImageBitmap(bitmap);
    
               }
    
           }
    
       }
    
    }
    

    这个例子是ImageView在置设大的图片的一个用应 WeakReference<ImageView> imageViewReference 用使一个软用引,保障ImageView可以被回收, 要主的耗时的作操在doInBackground(Integer... params) 方法中施实,处置成完后之的返回的结果在onPostExecute方法中用使,onPostExecute是在线主程运行的。 方法decodeSampledBitmapFromResource 的详细现实请参考 “Bitmap处置之畅流的加载大的Bitmap”
    际实的用应:

     public void loadBitmap(int resId, ImageView imageView) {
    
       BitmapWorkerTask task = new BitmapWorkerTask(imageView);
    
       task.execute(resId);
    
     }

    两个参数分别是 resId是通过R.drawable 得获的源资图片,imageView是 要表现的图片的ImageView

        

    处置并发问题

        

    对于一般的View如ListViwe和GridView在结合上述的AsyncTask加载源资时,会致导其他的问题。为了更好的利用存内源资,这些Viwe在滑动时,会对子View做源资回收,如果子View用使AsyncTask加载源资时,就不能保障子View可以实时的回收源资,也就是说开始一步加载的序顺和成完的序顺会不一致。 关于多线程处置的问题可以参考 “Multithreading for Performance ”的一篇Blog 可以建创一个专有的BitmapDrawable,在AsyncTask加载图片成完之前,可以用使一个empty(预览图)bitmap来表现

        


    static class AsyncDrawable extends BitmapDrawable {
    
       private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
    
       public AsyncDrawable(Resources res, Bitmap bitmap,
    
               BitmapWorkerTask bitmapWorkerTask) {
    
           super(res, bitmap);
    
           bitmapWorkerTaskReference =
    
               new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);
    
       }
    
      public BitmapWorkerTask getBitmapWorkerTask() {
    
           return bitmapWorkerTaskReference.get();
    
       }
    
     }

    在BitmapWorkerTask 执行之前,可以先用使一个预览图表现(或者一张空的图片)
        每日一道理
    翻开早已发黄的页张,试着寻找过去所留下的点点滴滴的足迹。多年前的好友似乎现在看来已变得陌生,匆忙之间,让这维持了多年的友谊变淡,找不出什么亲切感,只是偶尔遇上,淡淡地微笑,如今也只能在这发黄的页张中找寻过去的那些让人难忘的,至少我可以握住这仅剩下一段的“丝线头”……

    public void loadBitmap(int resId, ImageView imageView) {
    
       if (cancelPotentialWork(resId, imageView)) {
    
           final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
    
           final AsyncDrawable asyncDrawable =
    
                   new AsyncDrawable(getResources(), mPlaceHolderBitmap, task);
    
           imageView.setImageDrawable(asyncDrawable);
    
           task.execute(resId);
    
       }
    
     }
    

    mPlaceHolderBitmap可是以一个empty_photo.png的图片
    cancelPotentialWork 方法是检查是不是有另外一个running task和ImageView绑定,如果是,则前一个task会执行cancel()

    public static boolean cancelPotentialWork(int data, ImageView imageView) {
    
       final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
    
       if (bitmapWorkerTask != null) {
    
           final int bitmapData = bitmapWorkerTask.data;
    
           if (bitmapData != data) {
    
               // Cancel previous task
    
               bitmapWorkerTask.cancel(true);
    
           } else {
    
               // The same work is already in progress
    
               return false;
    
           }
    
       }
    
       // No task associated with the ImageView, or an existing task was cancelled
    
       return true;
    
    }

    如果返回false,说明已有一个工作者线程在运行 getBitmapWorkerTask方法是得获以后ImageView相干的工作者线程

    private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
    
      if (imageView != null) {
    
          final Drawable drawable = imageView.getDrawable();
    
          if (drawable instanceof AsyncDrawable) {
    
              final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
    
              return asyncDrawable.getBitmapWorkerTask();
    
          }
    
       }
    
       return null;
    
    }

    新更BitmapWorkerTask类

    class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
    
       ...
    
       @Override
    
       protected void onPostExecute(Bitmap bitmap) {
    
           if (isCancelled()) {
                bitmap = null;
            }
    
           if (imageViewReference != null && bitmap != null) {
    
               final ImageView imageView = imageViewReference.get();
    
               final BitmapWorkerTask bitmapWorkerTask =
    
                       getBitmapWorkerTask(imageView);
    
               if (this == bitmapWorkerTask && imageView != null) {
    
                   imageView.setImageBitmap(bitmap);
    
               }
    
           }
    
       }
    
    }

    加入了断判条件,断判以后的线程是不是已被cancel,ImageView的线程是不是和以后的线程是不是是同一个线程


    用应场景
    如在ListView或者GridView的getView()方法中,可以点用loadBitmap()方法来加载子view的源资

    文章结束给大家分享下程序员的一些笑话语录: 姿势要丰富,经常上百度!

  • 相关阅读:
    Java四种引用类型+ReferenceQueue+WeakHashMap
    浅谈怎样写好一篇(技术)博客?
    MySQL-5.7.14-WinX64安装配置详解
    网络编程梳理:Android网络基础知识复习
    Git时间:常用Git命令收集整理(持续更新)
    一些常见技术问题收集(二)持续更新
    开源库AndroidSwipeLayout分析(一),炫酷ItemView滑动呼出效果
    开源库AndroidSwipeLayout分析(二),SwipeLayout源码探究
    ES 基础操作
    pymongo
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3047885.html
Copyright © 2011-2022 走看看