• nullnullProcessing Bitmaps Off the UI Thread 处理来自UI线程的位图


    最近研究nullnull,稍微总结一下,以后继续补充:

        The BitmapFactory.decode* methods, should not be executed on the main UI thread if the source data is read from disk or a network location (or really any source other than memory). The time this data takes to load is unpredictable and depends on a variety of factors (speed of reading from disk or network, size of image, power of CPU, etc.). If one of these tasks blocks the UI thread, the system flags your application as non-responsive and the user has the option of closing it (seeDesigning for Responsiveness for more information). http://blog.csdn.net/sergeycao

        This lesson walks you through processing bitmaps in a background thread using AsyncTask and shows you how to handle concurrency issues.

        

    Use an AsyncTask

        The AsyncTask class provides an easy way to execute some work in a background thread and publish the results back on the UI thread. To use it, create a subclass and override the provided methods. Here’s an example of loading a large image into an ImageView using AsyncTask anddecodeSampledBitmapFromResource():

        

    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);
                }
            }
        }
    }

        The WeakReference to the ImageView ensures that theAsyncTask does not prevent the ImageView and anything it references from being garbage collected. There’s no guarantee theImageView is still around when the task finishes, so you must also check the reference inonPostExecute(). The ImageView may no longer exist, if for example, the user navigates away from the activity or if a configuration change happens before the task finishes.

        To start loading the bitmap asynchronously, simply create a new task and execute it:

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

        

    Handle Concurrency

        Common view components such as ListView and GridView introduce another issue when used in conjunction with theAsyncTask as demonstrated in the previous section. In order to be efficient with memory, these components recycle child views as the user scrolls. If each child view triggers anAsyncTask, there is no guarantee that when it completes, the associated view has not already been recycled for use in another child view. Furthermore, there is no guarantee that the order in which asynchronous tasks are started is the order that they complete.

        The blog post Multithreading for Performance further discusses dealing with concurrency, and offers a solution where theImageView stores a reference to the most recent AsyncTask which can later be checked when the task completes. Using a similar method, theAsyncTask from the previous section can be extended to follow a similar pattern.

        每日一道理
    自己把自己说服了,是一种理智的胜利;自己被自己感动了,是一种心灵的升华;自己把自己征服了,是一种人生的成功。

        Create a dedicated Drawable subclass to store a reference back to the worker task. In this case, aBitmapDrawable is used so that a placeholder image can be displayed in theImageView while the task completes:

        

    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();
        }
    }

        Before executing the BitmapWorkerTask, you create anAsyncDrawable and bind it to the target ImageView:

    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);
        }
    }

        The cancelPotentialWork method referenced in the code sample above checks if another running task is already associated with theImageView. If so, it attempts to cancel the previous task by callingcancel(). In a small number of cases, the new task data matches the existing task and nothing further needs to happen. Here is the implementation ofcancelPotentialWork:

    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;
    }

        A helper method, getBitmapWorkerTask(), is used above to retrieve the task associated with a particularImageView:

    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;
    }

        The last step is updating onPostExecute() in BitmapWorkerTask so that it checks if the task is cancelled and if the current task matches the one associated with theImageView:

        

    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); } } } }

        This implementation is now suitable for use in ListView andGridView components as well as any other components that recycle their child views. Simply callloadBitmap where you normally set an image to your ImageView. For example, in aGridView implementation this would be in the getView() method of the backing adapter.

    文章结束给大家分享下程序员的一些笑话语录: 很多所谓的牛人也不过如此,离开了你,微软还是微软,Google还是Google,苹果还是苹果,暴雪还是暴雪,而这些牛人离开了公司,自己什么都不是。

  • 相关阅读:
    mongodb3.6 (四)net 客户端如何连接、访问mongodb集群
    mongodb3.6 副本集(三)mongodb 如何做数据备灾
    winform中如何使用确认对话框
    Centos6.5在线配置安装Java环境与Tomcat环境
    IBatis.Net 下使用SqlBulkCopy 大批量导入数据 问题解决
    【easyui-combobox】下拉菜单自动补全功能,Ajax获取远程数据源
    IDEA创建springboot异常(Failed to load class "org.slf4j.impl.StaticLoggerBinder")
    Elasticsearch6.5安装&&常见问题与答案解释
    JS实现多Div模块拖拽功能
    IView入门练习~CDN模式全局加载JS
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3063473.html
Copyright © 2020-2023  润新知