美文网首页今日看点程序员Android开发
有关RecyclerView瀑布流的问题处理

有关RecyclerView瀑布流的问题处理

作者: ustcmio | 来源:发表于2017-01-31 16:42 被阅读0次

    一、随机高度问题

    一般使用RecyclerView+StaggeredGridLayoutManager构建瀑布流时,如果事先知道图片的长宽比,则直接设置就好,如果不知道的一般也采用随机高度,但是会导致图片不完整问题。可以尝试使用Glide加载图片时,通过Target对象获取图片长宽比。

    • 每个Item的布局文件高度采用wrap_content
    android:layout_height="wrap_content"
    
    • 每个 Item宽度固定,高度保存在Map中imageHeightMap,方便复用
    • 重写getItemViewType(int position)因为每个Item高度都不同,导致每个ViewHolder都不一样,为每个ViewHolder制定唯一的viewType值。(用途:处理Item乱跳的问题)
    • 使用Glide加载
    if (!this.imageHeightMap.containsKey(position)){
    //当首次加载图片时,调用 loadImageFirst(),保存图片高度
                loadImageFirst(imageVH.imageView,position);
            }else{  
    //非首次加载,直接根据保存的长宽,获取图片          
                Glide.with(this.mContext)
                        .load(this.entities.get(position).getUrl())                    .override(this.imageWidth,this.imageHeightMap.get(position))
                        .into(imageVH.imageView);
            }
    

    loadImageFirst()方法代码:

        public void loadImageFirst(View view, final int position){
            //构造方法中参数view,就是回调方法中的this.view
            ViewTarget<View,Bitmap> target = new ViewTarget<View, Bitmap>(view) {
                @Override
                public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                    //加载图片成功后调用
                    float scaleType = ((float) resource.getHeight())/resource.getWidth();
                    int imageHeight = (int) (imageWidth*scaleType);
                    //获取图片高度,保存在Map中
                    imageHeightMap.put(position,imageHeight);
                    //设置图片布局的长宽,Glide会根据布局的自动加载适应大小的图片
                    ViewGroup.LayoutParams lp = this.view.getLayoutParams();
                    lp.width=imageWidth;
                    lp.height=imageHeight;
                    this.view.setLayoutParams(lp);
                    //resource就是加载成功后的图片资源
                    ((ImageView)view).setImageBitmap(resource);
                }
                @Override
                public void onLoadFailed(Exception e, Drawable errorDrawable) {
                    //加载图片失败后调用
                    super.onLoadFailed(e, errorDrawable);
                    int imageHeight = imageWidth;
                    imageHeightMap.put(position,imageHeight);
                    ViewGroup.LayoutParams lp = this.view.getLayoutParams();
                    lp.width=imageWidth;
                    lp.height=imageHeight;
                    this.view.setLayoutParams(lp); 
                   ((ImageView)view).setImageResource(R.mipmap.ic_launcher);
                }
            };
            Glide.with(this.mContext)
                    .load(this.entities.get(position).getUrl())
                    .asBitmap()                 //作为Bitmap加载,对应onResourceReady回调中第一个参数的类型
                    .into(target);
        }
    

    二、快速上拉时Item乱跳的问题

    解决方法:在RecyclerView.adapter中重写getItemViewType(int position)方法
    原理分析
    查看源码,针对该方法的注释为:

    Return the view type of the item at <code>position</code> for the purposes of view recycling.The default implementation of this method returns 0, making the assumption of a single view type for the adapter. Unlike ListView adapters, types need not be contiguous. Consider using id resources to uniquely identify item view types.

    大概的意思是view type作为View复用时的标记,可以是不连续的整数,默认返回为0。
    RecyclerView.adapter复用ViewHolder构建列表视图的过程来看:

    1. 针对不同的position调用getViewForPosition(int position, boolean dryRun)。依次从 mChangedScrapmAttachedScrapmCachedViews中获取。都得不到的话,则从RecyclerViewPool中通过viewType来取,如果有多个ViewHolderviewType一样,则取最后一个。仍然取不到的话,则通过final方法createViewHolder创建
    • createViewHolder方法调用我们重写的onCreateViewHolder方法。如果没有重写getItemViewType()方法,则创建过程中的viewType值为0。即RecyclerViewPool中有多个以0为标志的ViewHolder
    • 所以当上拉时,之前的ViewHolder重新从RecyclerViewPool获取,而不是调用onCreateViewHolder方法创建。因为之前多次创建了viewType为0的ViewHolder,所以获取的并不是当前我们需要的,而是最后一次由onCreateViewHolder方法创建的。从而导致该position位置的图片高度不合适,出现一定的gaps(空隙)。而在StaggeredGridLayoutManager有专门的一个线程,每当滚动停止时对出现的gaps进行重新布局,导致Item乱跳

    相关文章

      网友评论

        本文标题:有关RecyclerView瀑布流的问题处理

        本文链接:https://www.haomeiwen.com/subject/ylhkittx.html