Picasso加载图片OOM的一些小经验

关于RecyclerView的一点小事

最近用RecyclerView做了一个图片列表,遇到了好几个OOM的坑,特别记录一下,首先是RecyclerView的使用上,原谅我是从listview转过来的一时没适应过来,listview的BaseAdapter里面有getPostion和getItem的方法重写,我们随便就能获得postion或者对应的item,到了RecyclerView我没找到getPostion方法,RecyclerView.ViewHolder里面的getAdapterPosition方法不能在初始化时获取postion,所以一时抽风重写了getItemViewType()方法返回postion,然后事情大条了,RecyclerView里是根据ItemViewType判断类型是否相同然后回收重用,所以一旦getItemViewType()方法返回postion,就表示着你的每个item不会回收复用,会一直填充新的itemView然后就oom了,虽然我知道大多数程序员没我这么傻,可是还是写给某些偶尔会脑抽的人参考一下。
我现在主要使用的还是getAdapterPosition()方法,只要不是需要在初始化时获取相对应的postion都可以用(要在初始化里面获取postion的建议放到onBindViewHolder方法里面,自带postion参数),具体的例子可以看看下面的给view加上点击事件的代码:

    public ViewHolder onCreateViewHolder(ViewGroup parent, final int viewType) {
    View view = mInflater.inflate(R.layout.recy_item_second_case,parent,false);

      final ViewHolder holder = new ViewHolder(view);
      holder.itemView.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              int position = holder.getAdapterPosition();
              Intent intent2 = new Intent(mContext, CaseActivity.class);
              intent2.putExtra("id",mDatas.get(position).getId()+"");
              mContext.startActivity(intent2);
        }
      });

       return holder;
     }

接下来是Picasso的使用上遇到的问题

以前一开始用的时候问题还不大,直到最近后台把开始把几M的缩略图传给我,3000多的宽高分辨率几张就把内存爆到100多了,不过这也怪我当初考虑不周,设计图要求图片宽度匹配屏幕,然后高度按比例自适应,图片的分辨率早就超出屏幕宽度了,所以加载这么大的图片是浪费内存资源,我就想着把bitmap缩小,一开始用的下面这个方法,在Picasso.transform(transformation)里面做处理当图片宽度大于屏幕时根据屏幕的width重新createScaledBitmap一个缩放的bitmap。

    Transformation transformation = new Transformation() {

        @Override
        public Bitmap transform(Bitmap source) {
            int targetWidth = width;

            if (source.getWidth()<=width){
                return source;
            }

            double aspectRatio = (double) source.getHeight() / (double) source.getWidth();
            int targetHeight = (int) (targetWidth * aspectRatio);
            if (targetHeight != 0 && targetWidth != 0) {
                Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
                if (result != source) {
                    source.recycle();
                }
                return result;
            } else {
                return source;
            }

        }

        @Override
        public String key() {
            return "transformation" + " desiredByWidth";
        }
    };

可是程序一跑起来内存占用并不能马上降下来,虽然我调用了source.recycle(),可是内存还是会涨到一个超过100m的峰值后面才下降,我试了用Picasso自身的resize方法的话就不会产生这么高的峰值,所以就想着不生成新的bitmap而是直接把根据屏幕宽度压缩后的宽高传给Picasso.resize(width,height)。

public static void displayCorpByResize(final ImageView img, String url, final int width){


    final double[] scaled = {0};

    Transformation transformation = new Transformation() {
        @Override
        public Bitmap transform(Bitmap source) {
            scaled[0] = (double) source.getHeight() / (double) source.getWidth();
            return source;
        }

        @Override
        public String key() {
            return "transformation" + " desiredByResize";
        }
    };

    if (!TextUtils.isEmpty(url)) {

        Picasso.with(mContext)
                .load(url)
                .config(Bitmap.Config.RGB_565)
                .transform(transformation)
                .resize(width, (int) (width*scaled[0]))
                .placeholder(R.drawable.load_photo_big)
                .into(img);

    }

}

这样虽然是解决了内存暴涨的问题,可是这代码的写法看起来连我都觉得有点别扭,各位大牛如果知道有什么好的写法请务必告诉我,网上都没找到对应的方法,所以才用这种别扭的方法。当然网络上许多朋友说Picasso内存占用大是老问题了,想要内存占用问题少点最好试试看glide和fresco框架,最后再谢谢这位老兄提供的自适应高度的ImageView。

你可能感兴趣的:(Picasso加载图片OOM的一些小经验)