zoukankan      html  css  js  c++  java
  • Bitmap(三)

      Bitmap(一)  http://www.cnblogs.com/fishbone-lsy/p/4486571.html

      Bitmap(二)    http://www.cnblogs.com/fishbone-lsy/p/4496166.html

      在Bitmap(一)中介绍了,Bitmap如何通过BitmapFactory获得图片资源。在Bitmap(二)中,介绍了将Bitmap进行预加载,缩放,再载入ImageView。

      显而易见,上面的过程已经是一个略复杂的耗时过程了。在移动开发中,所有的耗时过程,我们都不应该放在UI线程中,因为这样会造成卡顿甚至ANR等种种不良的用户体验。因此,我们应该为图片的加载开一个新的线程。Android中新开线程有很多种方法,在此只记录一种我认为最简单的方法,因为这不是重点。

      首先,可以思考一下,我们希望这个方法是什么样的,它有怎样的输入,怎样的输出。既然是一个图片加载,我们一定至少需要4个输入,图片从哪里来,图片到哪里去,图片的宽和图片的高。

      因此,图片从哪里来,可以参考Bitmap(一),在此,我们就选最简单的从Resourse里面来,到哪里去当然是一个ImageView,宽高就不用说了,跟Bitmap(二)里面一样。至于,输出,似乎不需要什么输出~

      先上代码,代码来此Google Training

      

        private class LoadImageTask extends AsyncTask<Integer , Void , Bitmap>{
          public LoadImageTask(ImageView imageView , int reqWidth , int reqHeight){
                imageViewReference = new WeakReference<ImageView>(imageView);
                mReqWidth = reqWidth;
                mReqHeight = reqHeight;
            }
            @Override
            protected Bitmap doInBackground(Integer... params) {
                return decodeSampledBitmapFromResource(getResources() , params[0],mReqWidth , mReqHeight);
            }
            @Override
            protected void onPostExecute(Bitmap bitmap) {
                if(bitmap!=null && imageViewReference !=null){
                    final ImageView imageView = (ImageView) imageViewReference.get();
                    if(imageView != null){
                        imageView.setImageBitmap(bitmap);
                    }
                }
            }
        }

      这是一段看起来略繁琐的代码,但是,繁琐是有它的道理的。这里最有趣的地方无疑是WeakReference<ImageView>这个软引用。既然说到软引用,在这里做一个简单的记录。

      在Java中,对象的引用有4种方法,分别是,强引用、软引用、弱引用、虚引用。

      强引用是很难被回收的对象。通常应用宁愿OOM也不会回收强引用;软引用相较于强引用偏弱,是在当系统内存不足时,会选择回收软引用;弱引用更弱,只要GC启动,并发现了它,必定把它回收了;虚引用就“形同虚设”了,在任何时候都可能被GC回收,它的存在主要是为了跟踪GC的活动。

      在这个图片加载的异步任务中,使用的是弱引用。之前我一直不明白,为什么不使用软引用,弱引用不是有被回收使这个异步任务失败的风险吗?后来查询资料得知,这个风险是必须承坦的。如果使用软引用,只有当系统快要OOM时,才会回收这个ImageView,而GC本身又是一个极耗内存的东西,因此,使用软引用才是真正在冒大风险。而弱引用,在一般的时候,GC是不会启动的。万一GC启动了,大多数情况也确实应该中止这个图片的载入,腾出内存,做更重要的事。大不了在内存充足后,重新加载就好了。

      还有一个我过去常有的做法就是,直接在异步任务里调用全局的ImageView或者直接在异步任务里写ImageView tempImageView  = imageView。这是很危险的。万一,我加载图片的任务刚开始,用户突然开始进行疯狂的操作(像我就是2333),或者网断了。此时,为了保证应用不闪退,我们很有可能不得不放弃这一次图片加载,如果这里用了ImageView tempImageView  = imageView的方式,那么这个tempImageView是无法释放的,来来回回几次,app就炸(OOM)了。因此,在这里使用弱引用是非常安全的。在加载完成之后,我们需要谨慎地检查一遍所有的对象还是不是存在,有没有被回收,检查完毕之后,我们才ImageView tempImageView  =(ImageView)imageViewReference.get();这样消耗内存的操作,赶紧加载完图片完事儿。

      最后,我们再在UI线程里开启这个线程。

            LoadImageTask task = new LoadImageTask(imageView1 , 100 , 100);
            task.execute(R.drawable.images);

      以上就是一次“优雅”的图片加载。

      但是,这个方法在高并发时是非常不适合的。(“谁允许你同时开这么多线程和Bitmap的”——GC)。所以,当我们要同时加载多个图片时,还有更深的套路,下次再记~。

    Duang

  • 相关阅读:
    sql优化-mysql的慢查询
    LInux服务器防火墙-开放端口
    vim打开文件中文乱码解决方法总结
    查看指定文件夹或文件总的大小,文件夹下各个文件的大小
    grep -v 反选匹配内容(not操作)以及grep -E(or操作)
    查看Liunx服务器的磁盘使用情况df命令,以及查看磁盘分区lsblk命令
    top发现僵尸进程
    查看linux服务器内存使用情况
    GitHub 和 GitLab对比
    git与svn
  • 原文地址:https://www.cnblogs.com/fishbone-lsy/p/4526922.html
Copyright © 2011-2022 走看看