Android Weex 图片适配器 ImageAdapter 优化

Weex Android 图片加载优化

      Android的weex界面中的图片加载是通过ImageAdapterl类来加载,阿里官方的例子中使用了Picasso图片加载框架来加载图片(鄙视他们),我们项目使用更好更优秀的Google官方推荐的Glide图片加载框架来为weex界面加载图片(一个隐藏的优化意见->使用Glide框架),所以以下优化方案都是针对Glide的优化。
 

一、优化weex图片加载速度

     weex加载的图片大小不一,有的很大的图片会加载缓慢,所以可以使用缩略图,让weex先加载出模糊的缩略图,再加载出清晰的图片,Glide的缩略图加载如下
 

//使用.thumbnail(0.2f) 0.2是原图大小的倍数既缩小5倍质量 

Glide.with(context).load(url).thumbnail(0.2f).into(view);

二、weex图片加载内存优化

      图片在加载完成后,会占用很多内存,当weex界面有大量大图片时,会消耗很多内存,造成界面卡顿、图片加载失败,甚至是app奔溃。因此要在内存优化方面做的更好有以下方法。
 

1、app申请更大内存(慎用)

       安卓系统会给app申请固定的内存,对于每个应用都有内存使用的限制,并不是还剩多少内存就可以用多少内存,机器的内存限制,可以在/system/build.prop文件中配置的。所以有时候你会看到手机还有内存,app就已经内存不足闪退了。我们可以在app中的AndroidManifest.xml设置largeHeap="true"以增加内存的申请量。但不是系统有多少内存就可以申请多少,而是由手机的dalvik.vm.heapsize限制。
    慎用!作为程序员的我们应该努力减少内存的使用,尽量想回收和复用的方法,而不是想方设法增大内存。当内存很大的时候,每次gc的时间也会长一些,性能会下降的。

2、加载图片资源的释放

     Glide加载weex图片时,Glide.with(context)需要传输一个上下文,不使用application作为context。当context为application时,会把imageView是生命周期延长到整个运行过程中,imageView不能被回收,从而造成OOM异常。传输当前Activity的context,当Activity结束时,glide会自动释放图片资源(glide真强)。

3、按照imageview大小加载图片

      glide本来是自动实现了该优化点,可是weex源码带来的一个坑导致glide不会自动按照view大小加载图片,会加载出原图大小,导致一些大图加载出来占用内存过大,像素点极高,增加了GPU的绘制压力,从而界面卡顿。我们先来看看weex的坑。

Android Weex 图片适配器 ImageAdapter 优化_第1张图片

    这是weex中的image标签在sdk中的实现,该方法为加载src

Android Weex 图片适配器 ImageAdapter 优化_第2张图片

 

         在该方法中,会生成一个WXImageStrategy的引用,负责存储一些图片的属性如锐化、圆角、图片加载完成的监听器等,也就是说不管你有没有设置这些属性,weex都要给你创建一个,并且要在图片加载完成后触发该监听器。这就无语了,很多weex界面是不需要知道你是否图片加载完成的,多此一举,应该提供一个属性来控制是否监听更合适。这就导致了glide不能直接加载图片,而是需要在加载完成后调用该监听器,则上面的glide加载代码就要通过Target来加载,如下
 

Glide.with(Application.getCurrentActivity()).load(url).thumbnail(0.2f).into(new SimpleTarget(view.getLayoutParams().width,view.getLayoutParams().height) {
                        @Override
                        public void onResourceReady(Drawable resource, @Nullable Transition transition) {
                            if (strategy.getImageListener() != null) {
                                strategy.getImageListener().onImageFinish(url, view, true, null);
                            }
                            if (resource.getIntrinsicWidth() >= 4096 || resource.getIntrinsicHeight() >= 4096) {
                                view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
                            }
                            view.setImageDrawable(resource);
                        }
                        @Override
                        public void onLoadFailed(@Nullable Drawable errorDrawable) {
                            super.onLoadFailed(errorDrawable);
                            if (strategy.getImageListener() != null) {
                                strategy.getImageListener().onImageFinish(url, view, false, null);
                            }
                        }
                    });

       这里将into(view)改为into(SimpleTarget(){}),Target的onResourceReady()中可以调动事件的监听。坑就在这里,当glide使用这个方式时,不会根据view的大小自动调整图片大小,会加载出原图大小,当图片特别大的时候就炸了,网上各种教程都有这个坑,因此代码中我在SimpleTarget()中传了view的宽高SimpleTarget(view.getLayoutParams().width,view.getLayoutParams().height),glide会根据该宽高加载图片,从而优化大量内存。

4、超大图导致GPU超频,无法绘制图 mn0片

       在一些手机上会导致该问题,超大图过大,绘制消耗大量资源,最后绘制失败,无法显示图片。由于在Android 4.0以上系统自动开启硬件加速,但是硬件的加速会占有一定的RAM,使用GPU绘制图片,图片又大,导致超频。如果你的应用只是标准的View和Drawable,全局都打开硬件加速,是不会有任何问题的。然而,硬件加速并不支持所有的2D画图的操作,这时开着它,可能会影响到你的自定义控件或者绘画,出现异常等行为。
      因此只要关闭硬件加速即可。硬件加速可以从4个层面进行关闭,分别是app、Activity、Window、View,我们当然不能直接关闭整个app的硬件加速,这样会降低app的响应速度,我们可以在view层面进行关闭,在上一段代码中的view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);便是关闭了imageview的硬件加速,我判断加载出的Drawable resource的宽高,超过4096即关闭硬件加速。
 

5、牺牲图片质量

      这个方法在项目中并没有使用,所以研究不深,观众可以自行选择,该方法会牺牲图片的质量,进行压缩,需要使用的观众可以在Target的回调方法中,将获取的resource进行压缩。

你可能感兴趣的:(Android Weex 图片适配器 ImageAdapter 优化)