接上节,上节记录了Bitmap的加载,用上节的方法,我们可以方便地压缩图片,进行加载。

  然而,有时候,当出来大量的图片或者是一张大图要加载时,这一过程所花的时间就会显得很长。甚至长到用户可以感觉出来,即UI的卡顿。因此,我们需要一个方法让图片自己加载去吧,不能干扰用户的操作。所以,我们需要用一个新的线程来完成图片加载的操作。其中最简单便捷的方法,就是Use an AsyncTask

  首先创建一个AsyncTask的子类:

    class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
        private final WeakReference<ImageView> imageViewReference;
        private int data = 0;
        private int width , height;
        public BitmapWorkerTask(ImageView imageView , int width , int height) {
            // Use a WeakReference to ensure the ImageView can be garbage collected
            imageViewReference = new WeakReference<ImageView>(imageView);
            this.width = width;
            this.height = height;
        }
        // Decode image in background.
        @Override
        protected Bitmap doInBackground(Integer... params) {
            data = params[0];
            return decodeSampledBitmapFromResource(getResources(), data, width, height);
        }
        // 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);
                }
            }
        }
    }

  其中,第一个参数是需要加载的图片的Id;

  PS:WeakReference<ImageView> imageViewReference 为弱引用。  

  • WeakReference may be cleared and enqueued as soon as is known to be weakly-referenced.

  当GC启动时弱引用会自动被回收,这里使用弱引用,防止了内存溢出。

  然后,创建这个加载图片类的对象,并在合适的时候执行这个异步任务。

        testButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int width = gridLayout.getWidth()/50;
                int height = gridLayout.getHeight()/50;
                Toast.makeText(getApplicationContext(),width+","+height,Toast.LENGTH_SHORT).show();
                BitmapWorkerTask task = new BitmapWorkerTask(imageView1,width,height);
                task.execute(R.drawable.ic_launcher_big);
            }
        });

  以上。

  然而,这也是有缺陷的。有时候我们需要加载的不只一张图。为了在存在多张图可能需要加载时,不影响系统的效率。组件回收器会在用户滑动屏幕时进行回收,将不出现在用户视野中的界面回收掉。在上面的方法中,每次加载都需要重开一个AsyncTask。有可能这张图还没有加载完,用户已经把这张图滑走了,我们需要用内存加载下一张图了。怎么处理?下回再写吧。。。

 

posted on 2015-04-10 15:06  Fishbonell  阅读(162)  评论(0编辑  收藏  举报