• Android框架 加载图片 库 Picasso 的使用简介


    0 说明

    现在Android开源库中有许多图片加载框架,本文以picasso为例,总结下开发过程中的一些优化经验,使用的picasso版本如下

    compile 'com.squareup.picasso:picasso:2.5.2'

    1 图片裁剪

    在列表页尽量使用裁剪后的图片,在查看大图模式下才加载完整的图片。

    图片裁剪示例

    Picasso.with( imageView.getContext() )
    .load(url)
    .resize(dp2px(250),dp2px(250))
    .centerCrop()
    .into(imageView);

    picasso默认情况下会使用全局的ApplicationContext,即开发者传进去Activity,picasso也会通过activity获取ApplicationContext。

    2 查看大图放弃memory cache

    Picasso默认会使用设备的15%的内存作为内存图片缓存,且现有的api无法清空内存缓存。我们可以在查看大图时放弃使用内存缓存,图片从网络下载完成后会缓存到磁盘中,加载会从磁盘中加载,这样可以加速内存的回收。

    Picasso.with(getApplication())
    .load(mURL)
    .memoryPolicy(NO_CACHE, NO_STORE)
    .into(imageView);

    其中memoryPolicy的NO_CACHE是指图片加载时放弃在内存缓存中查找,NO_STORE是指图片加载完不缓存在内存中。

    3 RecyclableImageView

    重写ImageView的onDetachedFromWindow方法,在它从屏幕中消失时回调,去掉drawable引用,能加快内存的回收。

    public class RecyclerImageView extends ImageView
    { 
        ...
    
        @Override    
        protected void onDetachedFromWindow() {
            super.onDetachedFromWindow();
            setImageDrawable(null);   
        }
    }

    实验环境:加载大图不使用内存缓存。
    实验场景:从图片列表页切换到详情页看大图,然后返回,不停重复。


    普通ImageView

    RecyclableImageView

    可以看到使用了RecyclableImageView的实验在切换过程中产生的内存谷值明显优于ImageView,说明drawable更容易被回收。

    4 新进程中查看大图

    列表页的内存已经非常稳定,但是查看大图时,大图往往占用了20+m内存,加上现有进程中的内存,非常容易oom,在新进程中打开Activity成为比较取巧的避免oom的方式。

    <activity android:name=".DetailActivity" android:process=":picture"/>

    只要在AndroidManifest.xml中定义Activity时加入process属性,即可在新进程中打开此Activity。由此,picasso也将在新进程中创建基于新ApplicationContext的单例。

    5 列表页滑动优化

    picasso可以对多个加载请求设置相同的tag,即

    Object tag = new Object();
    Picasso.with( imageView.getContext() )
    .load(url)
    .resize(dp2px(250),dp2px(250))
    .centerCrop()
    .tag(tag)
    .into(imageView);

    例如在RecyclerView滑动时监听,处理不同的表现:

    mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener(){
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState)
        {
            if (newState == RecyclerView.SCROLL_STATE_IDLE)
            {
                Picasso.with(context).resumeTag(tag);
            }
            else
            {
                Picasso.with(context).pauseTag(tag);
            }
        }
    });

    6 RGB_565

    对于不透明的图片可以使用RGB_565来优化内存。

    Picasso.with( imageView.getContext() )
    .load(url)
    .config(Bitmap.Config.RGB_565)
    .into(imageView);

    默认情况下,Android使用ARGB_8888

    Android中有四种,分别是:
    ALPHA_8:每个像素占用1byte内存
    ARGB_4444:每个像素占用2byte内存
    ARGB_8888:每个像素占用4byte内存
    RGB_565:每个像素占用2byte内存

    RGB_565呈现结果与ARGB_8888接近,内存对比如下图


    默认ARGB_8888,列表滑动时平均内存10m

    RGB_565,列表滑动时,平均7M

    7 reference

    Picasso and Context
    JakeWharton的避免OOM建议
    Clear Cache mem



    原文链接:http://www.jianshu.com/p/6b746c904a49

    Picasso使用的方法汇总:

    Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
    Picasso.with(context).load(url).into(view);
    Picasso.with(context).load(url) .resize(50, 50).centerCrop().into(imageView)
    //这里的placeholder将resource传入通过getResource.getDrawable取资源,所以可以是张图片也可以是color id
    Picasso.with(context).load(url).placeholder(R.drawable.user_placeholder).error(R.drawable.user_placeholder_error).into(imageView);

    Picasso.with(context).load(R.drawable.landing_screen).into(imageView1);
    Picasso.with(context).load("file:///android_asset/DvpvklR.png").into(imageView2);
    Picasso.with(context).load(new File(...)).into(imageView3);
    //这里显示notification的图片
    Picasso.with(activity).load(Data.URLS[new Random().nextInt(Data.URLS.length)]).resizeDimen(R.dimen.notification_icon_width_height,    R.dimen.notification_icon_width_height).into(remoteViews, R.id.photo, NOTIFICATION_ID, notification);
    //这里是通过设置tag标签,就是当前传过来的context,这样就可以根据这个context tag来pause和resume显示了
    Picasso.with(context).load(url).placeholder(R.drawable.placeholder).error(R.drawable.error).fit().tag(context).into(view);
    //监听onScrollStateChanged的时候调用执行
    picasso.resumeTag(context);
    picasso.pauseTag(context);

    Picasso.with(context).load(contactUri).placeholder(R.drawable.contact_picture_placeholder).tag(context).into(holder.icon);
    //这个onpause方法里的这段代码还是很有意思的
    @Override protected void onPause() {
        super.onPause();
        if (isFinishing()) {
          // Always cancel the request here, this is safe to call even if the image has been loaded.
          // This ensures that the anonymous callback we have does not prevent the activity from
          // being garbage collected. It also prevents our callback from getting invoked even after the
          // activity has finished.
          Picasso.with(this).cancelRequest(imageView);
        }
      }
    // Trigger the download of the URL asynchronously into the image view.
        Picasso.with(context)
            .load(url)
            .placeholder(R.drawable.placeholder)
            .error(R.drawable.error)
            .resizeDimen(R.dimen.list_detail_image_size, R.dimen.list_detail_image_size)
            .centerInside()
            .tag(context)
            .into(holder.image);
    //Picasso.with使用的是单例模式
    Picasso.with(this).cancelTag(this);

    然后呢,Picasso还提供了debug的标示,调用picasso的setIndicatorsEnabled方法,true是debug模式,跟踪代码其实就是在最后生成的PicassoDrawable类的ondraw里绘制了个左上角小三角,根据

    public enum LoadedFrom {
        MEMORY(Color.GREEN),
        DISK(Color.BLUE),
        NETWORK(Color.RED);

    枚举里的不同值标示不同加载来源,这对分析图片加载有好处。

    另外链接个分析picasso源码不错的博客地址http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0731/1639.html

    不要感谢我哦!


    Picasso真心是个很强大的图片加载框架,之前用过universal-Image-Loader图片加载框架也挺不错的

    开源的力量很强大啊☻



  • 相关阅读:
    ASP.NET MVC EF4.1
    RabbitMQ Boot Step
    图书商城项目总论
    CodeSharp.EventSourcing框架介绍如何实现异步事件订阅
    asp.net的cms 原理篇
    异步编程:线程概述及使用
    2012
    CodeSharp.EventSourcing框架介绍
    最近开发的一个文档管理系统
    团队项目开发
  • 原文地址:https://www.cnblogs.com/sharecenter/p/5620991.html
Copyright © 2020-2023  润新知