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

  

        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

时间: 2024-10-11 13:19:00

Bitmap(三)的相关文章

LruCache缓存bitmap(三)

应用在网络连接上,onrestart后不会重新联网获取图片,省去了流量, public class MainActivity extends AppCompatActivity { ImageView imageView; private LruCache<String, Bitmap> lruCache; Bitmap bitmap; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.

【Android应用开发技术:图像处理】Bitmap显示性能优化分析

作者:郭孝星 微博:郭孝星的新浪微博 邮箱:[email protected] 博客:http://blog.csdn.net/allenwells Github:https://github.com/AllenWells [Android应用开发技术:图像处理]章节列表 Bitmap经常会消耗大量内存而导致程序崩溃,常见的异常如下所示:java.lang.OutofMemoryError:bitmap size extends VM budget,因此为了保证程序的稳定性,我们应该小心处理程序

Bitmap(四)

Bitmap(一) http://www.cnblogs.com/fishbone-lsy/p/4486571.html Bitmap(二)   http://www.cnblogs.com/fishbone-lsy/p/4496166.html Bitmap(三)   http://www.cnblogs.com/fishbone-lsy/p/4526922.html 在Bitmap(一)中介绍了,Bitmap如何通过BitmapFactory获得图片资源.在Bitmap(二)中,介绍了将Bi

WPF(C#)中Bitmap与BitmapImage相互转换

一.WPF的Image控件中设置ImageSource image1.Source = new BitmapImage(new Uri(@"image file path", Urikind.RelativeOrAbsolute)); 还可以使用: System.IO.FileStream fs = new System.IO.FileStream(filepath, System.IO.FileMode.Open, System.IO.FileAccess.Read); byte[]

Android实战简易教程-第四十九枪(两种方式实现网络图片异步加载)

加载图片属于比较耗时的工作,我们需要异步进行加载,异步加载有两种方式:1.通过AsyncTask类进行:2.通过Handler来实现,下面我们就来看一下如何通过这两种方式实现网络图片的异步加载. 一.AsyncTask方式 1.main.xml: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.co

用仿ActionScript的语法来编写html5——第一篇,显示一张图片

第一篇,显示一张图片 一,代码对比 as代码: public var loader:Loader; public function loadimg():void{ loader = new Loader(); loader.contentLoaderInfo.addEventListener(Event.COMPLETE,complete); loader.load(new URLRequest("10594855.png")); } public function complete(

android-数据存储之手机内部file存储

一.基础概要 1.说明: 1>应用程序运行需要一些较大的数据或者图片可保存在手机内部 2>文件类型:任意 3>路径:/data/data/packageName/files/ 4>卸载应用时会删除此数据文件 5>也可以设置操作数据文件的权限(同SharedPreferences) 二.练习 1>FileInputStream fis=openFileInput("logo.png");     读取文件 2>FileOutputStream f

从原始位图剪切图像

public static Bitmap createBitmap (Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter) 从原始位图剪切图像,这是一种高级的方式.可以用Matrix(矩阵)来实现旋转等高级方式截图 参数说明: Bitmap source:要从中截图的原始位图 int x:起始x坐标 int y:起始y坐标 int width:要截的图的宽度 int height:要截的图的宽度

Android实现对图片的缩放、剪切、旋转、存储

Android实现对图片的缩放.剪切.旋转.存储 一.问题描述 在开发中,当我们需要的有一张大图片同时还需要一些小图片时,我们只需要通过代码对此图片进行不同比例的缩放即可,这样大大节约资源,减小了安装包的尺寸 .除缩放外,我们还经常对图片进行其他操作如裁剪.旋转.存储等. 这样我们可以编写对于图片进行处理的通用组件,方便开发.下面就分享一下对图片进行处理的组件BitmapUtil,案例界面: 二.技术点描述 1.通过BitmapFactory取得Bitmap Bitmap bm=BitmapFa