我的小鱼你醒了,
还认识早晨吗?
昨夜你曾经说,
愿夜幕永不开启

上述小诗先逗比一下,接下来切入正题;

自从RecyclerView的诞生起,人们就为她贴上了高贵的标签;她灵活华丽高度可定制,而另一边ListView确已是明日黄花;人们趋之若鹜的奔向了RecyclerView赞美她吹捧她似乎一切的一切都尽在他们的掌握中;各大技术论坛开始讲解RecyclerView是多么的好用;于是乎我也加入了使用RecyclerView的行列中,哦不!是混入了;

初识RecyclerView

说实在的我不愿意从头开始讲解她是如何工作,如何建立Adapter;因为早就有人写了相关用法的文章;再此我也不会赘述,我就当你会基本的用法了;如果还不知道她的基本用法可移至Android RecyclerView 使用完全解析 体验艺术般的控件,正所谓前人种树后人乘凉相信我们也从这些前辈的博客中学到了不少;

使用流程大概总结如下:

  • 设置RecyclerView的布局管理器:

RecyclerView.setLayoutManager(layout);

LinearLayoutManager:线性布局通常就是替换ListView布局

GridLayoutManager:表格布局通常就是替换GridView布局

StaggeredGridLayoutManager:这个布局比较灵活可以用来替换ListView,GridView还可以做出瀑布流的效果;

  • 设置Adapter

RecyclerView.setAdapter(adapter)

  • 设置增加删除动画

RecyclerView.setItemAnimator(new DefaultItemAnimator());

  • 设置分割线

RecyclerView.addItemDecoration(new DividerItemDecoration(

            getActivity(), DividerItemDecoration.HORIZONTAL_LIST));

(ps:分割线我觉得可以设置视图的margin来实现,或者自己添加边框;用这种方式做分割线反而是个累赘,当然还是根据实际情况来;)

RecyclerView你真的会用了吗?

看过不少RecyclerView的例子,大多是一些静态的测试环境;这样一看我们会认为RecyclerView果真是个好东西;于是乎我也心动了,我在上一篇文章中Android学习之优化美女图片浏览器中使用了GridView决定要替换为 RecyclerView并实现瀑布流的效果;想想还是有些小激动的,替换实现之分分钟搞定,下面是测试截图;

ScreenShot


美丽的背后总是隐藏着不为人知的故事

看了RecyclerView的使用后,我分分钟加入了上次写的项目中,本以为可以万事大吉;但是结果总是不会差强人意;当然我也怀疑过也会质疑应该没那么简单,果真遵循了墨菲定律;索性程序还是跑起来了,至少没有崩溃(ps:其实崩溃才是最好解决,哈哈:)

下面进入看图说话

上面两幅图中分别出现了两个bug

  1. 通过notifyDataSetChanged()方法后滑动到顶部图片会出现移位的效果

  2. 下拉到底部自动加载的时候全屏图片闪动(ps:相信看了我上一篇文章的同学已经知道如何避免下拉加载时整个页面闪动的问题,这里我同样采用了那种方式却失败了)

阳光总在风雨后,让我们一探究竟

由于上面的两个bug,我们已经猜出了个大概;可能得原因视图在刷新后相同位置的视图对象被替换了,这样导致他内部存储的唯一标识改变了;

下面我将对ListView和RecyclerView进行一个比较:

测试代码如下,我打印对象id看相同位置的TextView对象是否一致;

RecyclerView测试

public void onBindViewHolder(MyViewHolder holder,final int position) {if (position == 0) {Log.e(TAG, "position:" + position + " tv:" + holder.tv.toString());}else {Log.i(TAG, "position:" + position + " tv:" + holder.tv.toString());}holder.tv.setText(mDatas.get(position));}

还是进入看图说话,我经过两次刷新视图得到如上图的log信息;你会发现视图没有移动,只是刷新之后相应位置的TextView对象都已经改变了,我想这种情况我是不能容忍的;心中有万千草泥马奔腾而来,Google怎么会犯如此问题呢?(ps:哈哈,我也想是Google的问题,但是往往是我们自己的问题)

ListView测试

public View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder = null;if (convertView == null) {holder = new ViewHolder();convertView = mInflater.inflate(R.layout.item_simple, parent,false);holder.tv = (TextView) convertView.findViewById(R.id.textView);convertView.setTag(holder);}else {holder = (ViewHolder) convertView.getTag();}if (position == 0) {Log.e(TAG, "position:" + position + " tv:" + holder.tv.toString());}else {Log.i(TAG, "position:" + position + " tv:" + holder.tv.toString());}holder.tv.setText(getItem(position));return convertView;}

还是还是看图说话,发现没有看到没有这是ListView在进过两次刷新之后的结果;相同位置多次刷新之后可以完美的返回相同的对象,这样的好处是我们无需重复赋值;具体思路是可以将唯一标识保存在对象中,刷新之后我们比较标识就可以知道是否改变;

“有了新欢就抛弃了旧爱,我勤勤恳恳任劳任怨多年,最终等到的却是被遗弃的命运(@deprecated),等到你们被伤的遍体鳞伤的时候别来找我,哼…”

——ListView的告白

怎么办难道我的与时俱进就止步于此了吗,我不甘心;好吧,只能去看官方API了;

Google API的探索

功夫不负有心人终于让我找到了他,我就说Google不会这么坑吗?是谁说的拖出去斩了…:)

RecyclerView.java

    /*** Returns true if this adapter publishes a unique <code>long</code> value that can* act as a key for the item at a given position in the data set. If that item is relocated* in the data set, the ID returned for that item should be the same.** @return true if this adapter's items have stable IDs*/public final boolean hasStableIds() {return mHasStableIds;}

上述代码出自RecyclerView的源码描述,注释的大体意思是我们要重写getItemId方法给他一个不同位置的唯一标识,并且hasStableIds返回true的时候应该返回相同的数据集;

接下来我们复写getItemId()方法,并且设置setHasStableIds(true); (ps:在构造函数中设置)

好吧,眼泪不停落下… 返回对象惊人的一致…

接下来我们继续研究API:

以上是RecyclerView.Adapter的刷新数据的API,看到没如今notifyDataSetChanged()方法似乎显得黯然失色了;以上为我们提供了:

  • 更新1-n条数据;

  • 插入1-n条数据;

  • 删除1-n条数据;

具体用法我想大家看方法名称应该就会使用了,无需解释;

风雨过后会见到彩虹吗?

首先我们改进原有使用的方式:

  1. 下拉加载数据我们可以使用notifyItemRangeChanged(int, int)或者notifyItemRangeInserted(int, int) 这个方法,这样也避免了整个页面的全部刷新问题,也无需自己判断是否原来的View了;

  2. 尽量使用固定ID,这样可以正确返回position的位置否则我们可能在使用了notifyItemInserted(int)或者notifyItemRangeInserted(int, int) 的时候position出现异常

疑惑:

照Google文档描述在使用了notifyItemInserted时候原来位置的position会加1,但是事实证明数据的position位置毫无变化;可是当我设置了使用了固定ID之后,位置确实动态变化了但是插入却出现了问题,虽有动画但是结构没有变化,可是notifyItemRemoved方法却是可用的;

不设置固定ID,但是要让他position正确

public void addData(int pos){mDatas.add(pos,"Insert One");notifyItemInserted(pos);// 加入如下代码保证position的位置正确性if (pos != mDatas.size() - 1) {notifyItemRangeChanged(pos, mDatas.size() - pos);}}public void deleteData(int pos){mDatas.remove(pos);notifyItemRemoved(pos);// 加入如下代码保证position的位置正确性if (pos != mDatas.size() - 1) {notifyItemRangeChanged(pos, mDatas.size() - pos);}}

我们主要是对于插入删除之后手动更新position未变的位置,当时这样会导致新的对象创建;

设置固定ID,就无需担心position的问题了

虽然设置了固定ID无需担心position的问题,可是要记得这该死的墨菲定律 ;增加一项会在原来的位置不断增加,而删除正常;what’s a fucking bug!这个令人匪夷所思的问题很遗憾的告诉大家如今我也不知道是为什么,可是值得庆幸是删除没问题;你要知道我们在列表中增加一项和删除一项哪个用的频率会高一些呢?(ps:如大家有更好的办法也欢迎留言)
3. 这个是官方的建议,有两种事件:数据更新结构变化,但是不管是哪种方式他总是最有效和保险的方式,他能让我们得到正确的position;也就是针对上面第二条时,我们不确定position是否正确时我们可以在最后在调用他一次;

RecylerView我真的会用了?!

如今采用新的方式之后感觉还是不错的,但是我们其实还有一个问题没有解决就是第一幅图刷新之后回到顶部图片还是会移动位置,我没有办法找到解决办法可能是由于它瀑布流本生的问题;可是我们有替代方案就是让recyclerview刷新之后滚动到顶部RecyclerView.scrollToPosition(0);这样也算是间接解决了这个问题;

玫瑰玫瑰最娇美
玫瑰玫瑰最艳丽

玫瑰虽美可是往往我们没有注意到她的刺,美不美香不香只有试过才知道切不可人云亦云;好了写到这里算是告一段落了;TMD截图真的好累…

Android学习之-RecyclerView带刺的玫瑰相关推荐

  1. Android学习之RecyclerView带刺的玫瑰

    上述小诗先逗比一下,接下来切入正题: 自从RecyclerView的诞生起,人们就为她贴上了高贵的标签:她灵活华丽高度可定制,而另一边ListView确已是明日黄花:人们趋之若鹜的奔向了Recycle ...

  2. android学习日记 RecyclerView的简单使用

    android学习日记 RecyclerView的简单使用 文章目录 android学习日记 RecyclerView的简单使用 一.如何使用RecyclerView? 二.使用步骤 1.首先在bui ...

  3. Android学习笔记——RecyclerView编写气泡聊天

    声明 本次的代码部分参考郭霖--<第一行代码>,学习recyclerview章节后手动编写的. .9图制作 .9图素材是本人用Windows附件中的画图工具制作的(就是找不到资源),然后导 ...

  4. Android学习之RecyclerView的使用

    RecyclerView是Android 5.0推出的,是support-v7包中的新组件,它被用来代替ListView和GridView,并且能够实现瀑布流的布局,更加高级并且更加灵活,提供更为高效 ...

  5. Android学习之Recyclerview

    今天尝试了下Recyclerview,写了两个demo. 一个是仿短信demo.关键代码是msg_item设置左右两个linenearlayout布局,根据短信类型设置visable或gone. 另一 ...

  6. Android学习第一书

    大家好,我是一名Facebook的工程师,同时也是<第一行代码--Android>的忠实读者. 虽然我最近几年是在国外读书和工作的,但是和很多人一样,我也非常喜欢郭霖的博客以及他写的< ...

  7. Android 高级编程 RecyclerView 控件的使用

    RecyclerView 是Android 新添加的一个用来取代ListView的控件,它的灵活性与可替代性比listview更好. 看一下继承关系: ava.lang.Object    ↳ and ...

  8. Android学习路线总结

    title: Android学习路线总结,绝对干货 tags: Android学习路线,Android学习资料,怎么学习android grammar_cjkRuby: true --- 一.前言 不 ...

  9. Android:学习路线总结,绝对干货

    转载请注明出处:http://blog.csdn.net/lowprofile_coding/article/details/51252781 一.前言 不知不觉自己已经做了几年开发了,由记得刚出来工 ...

最新文章

  1. 力扣(LeetCode)刷题,简单题+中等题(第17期)
  2. python中字符串的布尔值_Python基础之字符串,布尔值,整数,列表,元组,字典,集合...
  3. python-序列化模块
  4. ntoskrnl.exe文件丢失或损坏的解决方法
  5. Shi-Tomasi算子的运用 ,用于检测角点
  6. 李宏毅深度学习——分类
  7. Java多线程面试准备:聊聊Executor框架
  8. The Security Learning
  9. 【Mybatis】分割字符串
  10. Openssl-MD5
  11. matlab程序 地震 相干噪声_地震台站台基噪声功率谱概率密度函数Matlab实现
  12. android 错误解决,Android常用错误解决汇总
  13. python 怎么样去txt中提取xml_如何使用python将.txt文件转换成xml文件?
  14. 拓端tecdat|R语言对巨灾风险下的再保险合同定价研究案例:广义线性模型和帕累托分布Pareto distributions分析
  15. 深入浅出MFC 6大关键技术之仿真 mfc程序初始化过程
  16. ARM开发5.3.4 基础实训( 1 ) 蜂鸣器输出控制--LPC21XX
  17. 手把手全面解读思科(Cisco)网络技术学院 考试折扣号申请说明
  18. 步进电机 步进电机驱动器
  19. 水木周平戏说中国网络黑幽默
  20. android判断是否安装应用程序,android如何判断一个软件是否安装以及打开手机应用商店...

热门文章

  1. 全球首个完全开源的指令跟随大模型;T5到GPT-4最全盘点
  2. Matlab异常值处理
  3. html5 canvas 画阿迪达斯logo,canvas绘图画出了的美团LOGO
  4. MATLAB汽车号码识别系统设计
  5. Java中数组复制的几种方式以及数组合并
  6. thymeleaf实现局部刷新
  7. WordPress的have_posts()和the_post()用法解析
  8. 虚拟机仅主机连接模式设置
  9. 未来工作空间,谁来保护你的安全?
  10. 不完整收录:过去一年字节开源的10个项目丨字节技术年货