recyclerView 进阶知识

一 初级篇

1. 请参照csdn上我的两篇:

a android 5.0新特性 RecyclerView使用初级
b Group分组列表的实现 RecyclerView ,实现不同类型的item组合列表

二 进阶知识点:

1. 设置Item的间距

public class SpaceItemDecoration extends RecyclerView.ItemDecoration {
   private final int mLeft;
   private final int mTop;
   private final int mRight;
   private final int mBottom;

   /**
    * @param left   padding in pixel
    * @param top    padding in pixel
    * @param right  padding in pixel
    * @param bottom padding in pixel
    */
   public SpaceItemDecoration(int left, int top, int right, int bottom) {
       mLeft = left;
       mTop = top;
       mRight = right;
       mBottom = bottom;
   }

   @Override
   public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
       outRect.set(mLeft, mTop, mRight, mBottom);
   }
}

2. 设置Item的分割线:

参考 http://blog.csdn.net/cjm2484836553/article/details/53439751
其实很简单,就是在每个item下面绘制一条带颜色的矩形即为分割线。

public class MyDeviderDecoration extends RecyclerView.ItemDecoration {  
        private int mydevider;  
        private Paint dividerPaint;  
  
        public MyDeviderDecoration(Context context) {  
            dividerPaint = new Paint();  
            //设置分割线颜色  
            dividerPaint.setColor(context.getResources().getColor(R.color.colorAccent));  
            //设置分割线宽度  
            mydevider = context.getResources().getDimensionPixelSize(R.dimen.divider_bottom);  
        }  
      
        @Override  
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {  
            super.getItemOffsets(outRect, view, parent, state);  
            outRect.bottom = mydevider;  
        }  
 
        @Override  
        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {  
            int childCount = parent.getChildCount();  
            int left = parent.getPaddingLeft();  
            int right = parent.getWidth() - parent.getPaddingRight();  
  
            for (int i = 0; i < childCount - 1; i++) {  
                View view = parent.getChildAt(i);  
                float top = view.getBottom();  
                float bottom = view.getBottom() + mydevider;  
                c.drawRect(left, top, right, bottom, dividerPaint);  
            }  
        }  
    }  

3. 如何在recyclerView 中使用 MVVM + DataBinding

将VM放在holder就好。

@Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == VIEW_TYPE_NORMAL) {
         ...
        } else {
            //更多 
         MoreItemVM viewModel = new ListMoreItemVM(...);
         // 初始化binding
         binding = BindingUtils.inflate(...)
            ...
            binding.setViewModel(viewModel);
            return new ViewHolder(binding.getRoot(), viewModel, binding);
        }

    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        //
        if (getItemViewType(position) == VIEW_TYPE_NORMAL) {
            holder.setData(...);
        } else {
            holder.setData(...);
        }
        holder.mBinding.executePendingBindings();
    }

    @Override
    public int getItemViewType(int position) {
        if (position < getItemCount() - 1) {
            return VIEW_TYPE_NORMAL;
        } else {
            return VIEW_TYPE_MORE;
        }
    }


    public static class ViewHolder extends RecyclerView.ViewHolder {

        private ListItemVM mItemViewModel;
        private ListMoreItemVM mMoreItemVM;
        public final ViewDataBinding mBinding;

        public ViewHolder(View itemView, ListItemVM itemViewModel, ViewDataBinding binding) {
            super(itemView);
            mItemViewModel = itemViewModel;
            mItemViewModel.reset();
            mBinding = binding;
        }

        public ViewHolder(View itemView, ListMoreItemVM itemViewModel, ViewDataBinding binding) {
            super(itemView);
            mMoreItemVM = itemViewModel;
            mBinding = binding;

        }

        public void setData(RunningAlbumInfo runningAlbumInfo) {
            mItemViewModel.setData(runningAlbumInfo);
        }

        public void setData(Category category) {
            mMoreItemVM.setData(category);
        }
    }

4. 如何dissmiss ViewModel中的popwindow

这个问题,即是说如何拿到当前选中的item。思路很简单,先拿到holder,然后通过holder拿到对应的VM。恩,其实这里的popwindow该放在adpter中show的,统一的逻辑都该adpter来做,VM只负责展示。

 if (mRecyclerView != null && mLinearLayoutManager != null) {
            int pos = mRecyclerView.getCurrentPosition();
            View view = mLinearLayoutManager.getChildAt(pos);
            if (view != null) {
                ListAdapter.ViewHolder holder =
                        (ListAdapter.ViewHolder) mRecyclerView.getChildViewHolder(view);
                if (holder.mBinding != null && (holder.mBinding instanceof xxxBinding)
                        && ((xxxBinding) holder.mBinding).getViewModel().isShowing()) {
                    ((xxxBinding) holder.mBinding).getViewModel().dismiss();
                    return true;
                }
            }
        }

4. 特殊的水平居中、左右两边缩放淡出的列表(Gallery画廊效果):

这里有几套方案,

1. 自己实现 较难 (这里主要指复用和缓存及性能上问题)

2. viewPager 达不到快速滑动,只支持单页

3. recyclerView + 自定义的LayoutManager 居中显示还有些问题(回弹和状态保存一不小心crash)自定义LayoutManager 实现弧形以及滑动放大效果RecyclerView http://www.jianshu.com/p/7bb7556bbe10

4. recyclerView + LinearSnapHelper 使用RecyclerView实现Gallery画廊效果(http://www.jianshu.com/p/85bf072bfeed

5. recyclerViewPager 三方框架 左右view将中间的view裁剪掉了,这是和viewPager相似的问题,绘制Item的时候存在顺序,需要自己动态调试下

三 使用recyclerView 的 可能出现bug

bug 1.https://code.google.com/p/android/issues/detail?id=77846

该问题现在还没有解决。本人是在recyclerView 从内存中重启的时候 ,想保存一个排序和原始数据恢复位置时遇到。

这里特别指出fragment的生命周期:onCreateView -> onViewCreated -> onActivityCreated -> onViewStateRestored-> onStart -> onResume

我在这里调了整整一天,都出现google的issue。原来初始化的基类,在onViewCreated中调用,让我造成了这个isssue,重新异步请求刷新了一遍数据。
基本上看stackoverflow和issue下面的回答,有帮助的大意是:recyclerView 的数据刷新不同步(导致滚动位置无法定位或调用scrollToPosition时不同步)。解决方法是检查下有木有重复的比较连续刷新数据,刷新数据和定位几乎同时调用。

bug 2 滑动问题,见第一篇文章。

http://www.jianshu.com/p/4535442d568f
该文中已提出一个workaround

3 这个坑,是我自己挖的。

这里由于产品需要,recyclerView的item的高度为动态的wrap_content(建议不要使用,recyclerView由于得不到具体宽高,会多次调用getView方法),又要求recyclerView的item进行折叠。当recyclerView的数据项不满一屏时,且此时recyclerView的item由展开到折叠,此时存在视觉上的ui缓存。即该折叠项依然占据展开式的位置。此时,进行点击事件或滑动事件时,缓存的数据消失。 而采用stackoverflow上消去drawingcache 的方法没有作用:
https://www.google.com.sg/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&ved=0ahUKEwjo_ue06vnLAhVBYqYKHQESCVkQFggmMAE&url=%68%74%74%70%3a%2f%2f%73%74%61%63%6b%6f%76%65%72%66%6c%6f%77%2e%63%6f%6d%2f%71%75%65%73%74%69%6f%6e%73%2f%31%34%34%31%39%35%39%37%2f%68%6f%77%2d%74%6f%2d%64%69%73%61%62%6c%65%2d%74%68%65%2d%64%72%61%77%69%6e%67%2d%63%61%63%68%65&usg=AFQjCNHua37wKKbmd3802rrE0wWXaTcvcw
在listView或此处,我使用的workaround均为Handler post方法解决。

4 recyclerview notifyitemchanged blink

刷新单个item的时候,出现闪屏现象。(比较常见的是,item做动画时,就存在这个问题)
1 http://stackoverflow.com/questions/29873859/how-to-implement-itemanimator-of-recyclerview-to-disable-the-animation-of-notify
2 http://stackoverflow.com/questions/29331075/recyclerview-blinking-after-notifydatasetchanged
这个查了网上的一些方案,对我起作用的ItemAnimator animator = recyclerView.getItemAnimator();
if (animator instanceof SimpleItemAnimator) {
((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,271评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,725评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,252评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,634评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,549评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,985评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,471评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,128评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,257评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,233评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,235评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,940评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,528评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,623评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,858评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,245评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,790评论 2 339

推荐阅读更多精彩内容