RecyclerView 数据刷新的几种方式

Posted 白乾涛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RecyclerView 数据刷新的几种方式相关的知识,希望对你有一定的参考价值。

小结

  • 刷新全部可见的item,notifyDataSetChanged()
  • 刷新指定item,notifyItemChanged(int)
  • 从指定位置开始刷新指定个item,notifyItemRangeChanged(int,int)
  • 插入、移动一个并自动刷新,notifyItemInserted(int)、notifyItemMoved(int)、notifyItemRemoved(int)
  • 局部刷新,notifyItemChanged(int, Object)

Activity

  1. public class Notify_Activity extends Activity implements MyOnItemClickLitener {
  2. private RecyclerView mRecyclerView;
  3. private Notify_Adapter mAdapter;
  4. private ArrayList<PicUrls.BasicPicBean> beans;
  5. @Override
  6. protected void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.activity_main);
  9. ((SwipeRefreshLayout) findViewById(R.id.swipeLayout)).setEnabled(false);
  10. mRecyclerView = (RecyclerView) findViewById(R.id.rv);
  11. initList();
  12. initView();
  13. }
  14. protected void initView() {
  15. mAdapter = new Notify_Adapter(this, beans);
  16. mAdapter.setOnItemClickLitener(this);
  17. mRecyclerView.setAdapter(mAdapter);//设置adapter
  18. mRecyclerView.setLayoutManager(new GridLayoutManager(this, 3));//设置布局管理器
  19. mRecyclerView.setItemAnimator(new DefaultItemAnimator());//设置Item增加、移除动画
  20. mRecyclerView.addItemDecoration(new GridItemDecoration.Builder().spanCount(3)
  21. .spaceSize(1).mDivider(new ColorDrawable(0x88ff0000)).build());
  22. }
  23. private void initList() {
  24. beans = PicUrls.getPicList(PicUrls.BIG_BEANS_2);
  25. beans.get(0).name = "刷新当前,notifyItemChanged(int)";
  26. beans.get(1).name = "全部刷新,notifyDataSetChanged()";
  27. beans.get(2).name = "从此位置开始刷新2个,notifyItemRangeChanged";
  28. beans.get(3).name = "插入一个并自动刷新,notifyItemInserted";
  29. beans.get(4).name = "只更改数据源,这样当然不会刷新UI";
  30. beans.get(5).name = "插入一个并刷新当前,notifyItemChanged";
  31. beans.get(6).name = "局部刷新,tv";
  32. beans.get(7).name = "局部刷新,et";
  33. beans.get(8).name = "局部刷新,iv";
  34. }
  35. @Override
  36. public void onItemClick(View view, int position) {
  37. Toast.makeText(this, position + " 被点击了", Toast.LENGTH_SHORT).show();
  38. reInit(position);
  39. }
  40. @Override
  41. public void onItemLongClick(View view, int position) {
  42. Toast.makeText(this, position + "被长按了", Toast.LENGTH_SHORT).show();
  43. }
  44. private void reInit(int position) {
  45. switch (position) {
  46. default:
  47. mAdapter.notifyItemChanged(position);//刷新指定一个。一定会闪
  48. break;
  49. case 1:
  50. mAdapter.notifyDataSetChanged();//全部刷新。基本不会闪,刚开始个别可能会闪
  51. break;
  52. case 2:
  53. mAdapter.notifyItemRangeChanged(position, 2);//从指定位置开始刷新指定个。一定会闪
  54. break;
  55. case 3:
  56. beans.add(position, new PicUrls.BasicPicBean("http://img.mmjpg.com/2015/74/1.jpg", "新插入的图片1", 1));
  57. mAdapter.notifyItemInserted(position);//插入一个并刷新,正常
  58. break;
  59. case 4://只更改数据源,这样当然不会刷新UI
  60. beans.add(position, new PicUrls.BasicPicBean("http://img.mmjpg.com/2015/74/2.jpg", "新插入的图片2", 2));
  61. break;
  62. case 5://
  63. beans.add(position, new PicUrls.BasicPicBean("http://img.mmjpg.com/2015/74/3.jpg", "新插入的图片3", 3));
  64. mAdapter.notifyItemChanged(position);//这样只会导致当前item刷新,而不会刷新其他item,当然是不行的
  65. break;
  66. case 6:
  67. beans.set(position, beans.get(new Random().nextInt(beans.size())));
  68. mAdapter.notifyItemChanged(position, Notify_Adapter.NOTIFY_TV);//局部刷新
  69. break;
  70. case 7:
  71. beans.set(position, beans.get(new Random().nextInt(beans.size())));
  72. mAdapter.notifyItemChanged(position, Notify_Adapter.NOTIFY_ET);//局部刷新
  73. break;
  74. case 8:
  75. beans.set(position, beans.get(new Random().nextInt(beans.size())));
  76. mAdapter.notifyItemChanged(position, Notify_Adapter.NOTIFY_IV);//局部刷新
  77. break;
  78. }
  79. }
  80. }

Adapter

  1. public class Notify_Adapter extends RecyclerView.Adapter<Notify_Adapter.MyViewHolder> {
  2. private Context context;
  3. private List<PicUrls.BasicPicBean> mDatas;
  4. private MyOnItemClickLitener mOnItemClickLitener;
  5. public static final int NOTIFY_TV = 10086;
  6. public static final int NOTIFY_ET = 10087;
  7. public static final int NOTIFY_IV = 10088;
  8. public Notify_Adapter(Context context, List<PicUrls.BasicPicBean> mDatas) {
  9. this.context = context;
  10. this.mDatas = mDatas;
  11. }
  12. @Override
  13. public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  14. return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.item_notify, parent, false));
  15. }
  16. @Override
  17. public void onBindViewHolder(MyViewHolder holder, int position) {
  18. //不使用
  19. }
  20. @Override
  21. public void onBindViewHolder(final MyViewHolder holder, int position, List payloads) {
  22. //payloads是从notifyItemChanged(int, Object)中,或从notifyItemRangeChanged(int, int, Object)中传进来的Object集合
  23. //如果payloads不为空并且viewHolder已经绑定了旧数据了,那么adapter会使用payloads参数进行布局刷新
  24. //如果payloads为空,adapter就会重新绑定数据,也就是刷新整个item
  25. PicUrls.BasicPicBean bean = mDatas.get(holder.getAdapterPosition());
  26. long time = System.currentTimeMillis() + bean.url.hashCode();
  27. String data = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()).format(new Date(time));
  28. if (payloads.isEmpty()) {//为空,即不是调用notifyItemChanged(position,payloads)后执行的,也即在初始化时执行的
  29. holder.tv.setText(data);
  30. holder.et.setText(bean.name);
  31. Glide.with(context).load(bean.url)
  32. .dontAnimate()
  33. //.diskCacheStrategy(DiskCacheStrategy.NONE).skipMemoryCache(true)
  34. .into(holder.iv);
  35. } else if (payloads.size() > 0 && payloads.get(0) instanceof Integer) {
  36. //不为空,即调用notifyItemChanged(position,payloads)后执行的,可以在这里获取payloads中的数据进行局部刷新
  37. int type = (int) payloads.get(0);// 刷新哪个部分 标志位
  38. switch (type) {
  39. case NOTIFY_TV:
  40. holder.tv.setText(data);//只刷新tv
  41. break;
  42. case NOTIFY_ET:
  43. holder.et.setText(bean.name);//只刷新et
  44. break;
  45. case NOTIFY_IV:
  46. Glide.with(context).load(bean.url).dontAnimate().into(holder.iv);//只刷新iv
  47. break;
  48. }
  49. }
  50. // 如果设置了回调,则设置点击事件
  51. holder.itemView.setOnClickListener(new OnClickListener() {
  52. @Override
  53. public void onClick(View v) {
  54. if (mOnItemClickLitener != null) mOnItemClickLitener.onItemClick(holder.itemView, holder.getAdapterPosition());
  55. }
  56. });
  57. holder.itemView.setOnLongClickListener(new OnLongClickListener() {
  58. @Override
  59. public boolean onLongClick(View v) {
  60. if (mOnItemClickLitener != null) mOnItemClickLitener.onItemLongClick(holder.itemView, holder.getAdapterPosition());
  61. return false;
  62. }
  63. });
  64. }
  65. @Override
  66. public int getItemCount() {
  67. return mDatas.size();
  68. }
  69. /**
  70. * 添加并更新数据,同时具有动画效果
  71. */
  72. public void addDataAt(int position, PicUrls.BasicPicBean data) {
  73. mDatas.add(position, data);
  74. notifyItemInserted(position);//更新数据集,注意如果用adapter.notifyDataSetChanged()将没有动画效果
  75. }
  76. /**
  77. * 移除并更新数据,同时具有动画效果
  78. */
  79. public void removeDataAt(int position) {
  80. mDatas.remove(position);
  81. notifyItemRemoved(position);
  82. }
  83. public void setOnItemClickLitener(MyOnItemClickLitener mOnItemClickLitener) {
  84. this.mOnItemClickLitener = mOnItemClickLitener;
  85. }
  86. class MyViewHolder extends RecyclerView.ViewHolder {
  87. TextView tv;
  88. ImageView iv;
  89. EditText et;
  90. public MyViewHolder(View view) {
  91. super(view);
  92. tv = (TextView) view.findViewById(R.id.tv_name);
  93. iv = (ImageView) view.findViewById(R.id.iv_head);
  94. et = (EditText) view.findViewById(R.id.et_input);
  95. }
  96. }
  97. }

布局

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="wrap_content"
  5. android:gravity="center_horizontal"
  6. android:orientation="vertical">
  7. <TextView
  8. android:id="@+id/tv_name"
  9. android:layout_width="wrap_content"
  10. android:layout_height="wrap_content"
  11. android:gravity="center"
  12. android:text="0.00"
  13. android:textColor="#00f"
  14. android:textSize="13sp"/>
  15. <ImageView
  16. android:id="@+id/iv_head"
  17. android:layout_width="match_parent"
  18. android:layout_height="200dp"
  19. android:scaleType="centerCrop"
  20. android:src="@mipmap/ic_launcher"/>
  21. <EditText
  22. android:id="@+id/et_input"
  23. android:layout_width="wrap_content"
  24. android:layout_height="wrap_content"
  25. android:gravity="center"
  26. android:hint="包青天"
  27. android:inputType="numberDecimal"
  28. android:labelFor="@id/et_input"
  29. android:maxLines="1"
  30. android:minWidth="50dp"
  31. android:textColor="#f00"
  32. android:textSize="10sp"/>
  33. </LinearLayout>

获取图片集合

  1. public class PicUrls {
  2. private static final String HOST0 = "http://img1.mm131.com/pic/";//网站【http://www.mm131.com/】
  3. private static final String HOST1 = "http://img.mmjpg.com/";//网站【http://www.mmjpg.com/】
  4. private static final String HOST2 = "http://pic.meituba.com/uploads/allimg/";//网站【http://www.meituba.com/】
  5. public static final UrlBean BIG_BEANS_0 = new UrlBean.Builder()//http://pic.meituba.com/uploads/allimg/2015/10/23/220.jpg
  6. .host(HOST2).urlHeader("2015/10/23/").picIndexFrom(220).picCount(100).picDes("100张动漫卡通壁纸").build();
  7. public static final UrlBean BIG_BEANS_1 = new UrlBean.Builder()//http://pic.meituba.com/uploads/allimg/2017/03/27/121_5600.jpg
  8. .host(HOST2).urlHeader("2017/03/27/121_").picIndexFrom(5600).picCount(100).picDes("100张搞笑内涵图片").build();
  9. public static final UrlBean BIG_BEANS_2 = new UrlBean.Builder()//http://pic.meituba.com/uploads/allimg/2015/10/23/360.jpg
  10. .host(HOST2).urlHeader("2015/10/23/").picIndexFrom(360).picCount(750).picDes("750张性感美女图").build();
  11. public static final UrlBean BIG_BEANS_3 = new UrlBean.Builder()//http://pic.meituba.com/uploads/allimg/2016/03/25/43_20335.jpg
  12. .host(HOST2).urlHeader("2016/03/25/43_").picIndexFrom(20335).picCount(1400).picDes("1400张动漫卡通壁纸").build();
  13. private static final UrlBean[] simpleBeans = {
  14. //http://img1.mm131.com/pic/996/1.jpg
  15. new UrlBean.Builder().host(HOST0).urlHeader("996/").picCount(10).picDes("北影校花余雨高清写真图片").build(),
  16. new UrlBean.Builder().host(HOST0).urlHeader("2958/").picCount(10).picDes("童颜嫩妹桃子黑丝大尺度诱惑").build(),
  17. new UrlBean.Builder().host(HOST0).urlHeader("2939/").picCount(10).picDes("清纯少女刘奕宁酥胸覆白色内衣").build(),
  18. new UrlBean.Builder().host(HOST0).urlHeader("2343/").picCount(10).picDes("萌妹销魂写真身材惹火让人欲罢不能").build(),
  19. new UrlBean.Builder().host(HOST0).urlHeader("2935/").picCount(10).picDes("性感女神杨晨晨透视睡衣大胆秀乳").build(),
  20. //http://img.mmjpg.com/2015/444/1.jpg
  21. new UrlBean.Builder().host(HOST1).urlHeader("2015/444/").picCount(10).picDes("模范学院美少女柳侑绮制服大片").build(),
  22. new UrlBean.Builder().host(HOST1).urlHeader("2015/74/").picCount(10).picDes("极品女神可儿私拍秀完美身材").build(),
  23. new UrlBean.Builder().host(HOST1).urlHeader("2017/990/").picCount(10).picDes("香艳妹子雪白的美胸绝对让你大饱眼福").build(),
  24. new UrlBean.Builder().host(HOST1).urlHeader("2017/962/").picCount(10).picDes("真诱人啊!女神雪白的美胸看着很有感觉").build(),
  25. new UrlBean.Builder().host(HOST1).urlHeader("2017/936/").picCount(10).picDes("身材娇美纯天然美女小叶子美胸艺术照").build(),
  26. //http://pic.meituba.com/uploads/allimg/2015/10/23/247.jpg
  27. new UrlBean.Builder().host(HOST2).urlHeader("2015/10/23/").picIndexFrom(247).picCount(10).picDes("呆萌可爱的哆啦A梦动漫").build(),
  28. new UrlBean.Builder().host(HOST2).urlHeader("2016/03/25/43_").picIndexFrom(20574).picCount(10).picDes("海贼王红发香克斯").build(),
  29. new UrlBean.Builder().host(HOST2).urlHeader("2016/03/25/44_").picIndexFrom(11275).picCount(10).picDes("英雄联盟游戏图片").build(),
  30. new UrlBean.Builder().host(HOST2).urlHeader("2016/07/30/43_").picIndexFrom(485).picCount(10).picDes("精选超萌小猫咪").build(),
  31. new UrlBean.Builder().host(HOST2).urlHeader("2016/09/08/43_").picIndexFrom(476).picCount(10).picDes("可爱快乐的女孩动漫").build(),
  32. };
  33. //******************************************************************************************
  34. /**
  35. * 10*15张各种各样的带有描述的图片
  36. */
  37. public static ArrayList<BasicPicBean> getPicList() {
  38. List<UrlBean> urlList = Arrays.asList(simpleBeans);
  39. ArrayList<BasicPicBean> picList = new ArrayList<>();
  40. for (UrlBean bean : urlList) {
  41. picList.addAll(getPicList(bean));
  42. }
  43. return picList;
  44. }
  45. /**
  46. * 每一个UrlBean都有超多图片,多的有几千张
  47. */
  48. public static ArrayList<BasicPicBean> getPicList(UrlBean bean) {
  49. ArrayList<BasicPicBean> picList = new ArrayList<>();
  50. for (int i = 0; i < bean.picCount; i++) {
  51. String picIndex = "" + (bean.picIndexFrom + i);
  52. for (int j = picIndex.length(); j < bean.minLength; j++) {
  53. if (picIndex.length() < bean.minLength) {
  54. picIndex = "0" + picIndex;
  55. } else break;
  56. }
  57. String picUrl = bean.host + bean.urlHeader + picIndex + bean.urlEnder;//例如.../1.jpg
  58. String picDes = bean.picDes + "-" + i;
  59. picList.add(new BasicPicBean(picUrl, picDes, i));
  60. }
  61. return picList;
  62. }
  63. //******************************************************************************************
  64. static class UrlBean {
  65. public String picDes;//图片描述
  66. public String host;//存放图片的主机地址
  67. public String urlHeader;
  68. public String urlEnder;//默认为= ".jpg"
  69. public int picCount;//此系列图片的数量。所有图片都是以数字命名的,比如1.jpg、2.jpg
  70. public int picIndexFrom;//此系列图片开始的序号位置,默认为1
  71. public int minLength;//如,当为1.jpg时实际为01.jpg或001.jpg
  72. private UrlBean(Builder builder) {
  73. picDes = builder.picDes;
  74. host = builder.host;
  75. urlHeader = builder.urlHeader;
  76. urlEnder = builder.urlEnder;
  77. picCount = builder.picCount;
  78. picIndexFrom = builder.picIndexFrom;
  79. minLength = builder.minLength;
  80. }
  81. static final class Builder {
  82. private String picDes = "包青天作品";
  83. private String host = "";
  84. private String urlHeader = "";
  85. private String urlEnder = ".jpg";//默认为".jpg"
  86. private int picCount = 1;
  87. private int picIndexFrom = 1;
  88. private int minLength = 0;
  89. public Builder() {
  90. }
  91. public Builder urlHeader(String val) {
  92. urlHeader = val;
  93. return this;
  94. }
  95. public Builder urlEnder(String val) {
  96. urlEnder = val;
  97. return this;
  98. }
  99. public Builder picCount(int val) {
  100. picCount = val;
  101. return this;
  102. }
  103. public Builder picIndexFrom(int val) {
  104. picIndexFrom = val;
  105. return this;
  106. }
  107. public Builder minLength(int val) {
  108. minLength = val;
  109. return this;
  110. }
  111. public Builder host(String val) {
  112. host = val;
  113. return this;
  114. }
  115. public Builder picDes(String val) {
  116. picDes = val;
  117. return this;
  118. }
  119. public UrlBean build() {
  120. return new UrlBean(this);
  121. }
  122. }
  123. }
  124. //******************************************************************************************
  125. public static class BasicPicBean {
  126. public String url;
  127. public String name;
  128. public int index;
  129. public BasicPicBean(String url, String name, int index) {
  130. this.url = url;
  131. this.name = name;
  132. this.index = index;
  133. }
  134. }
  135. }
2017-6-7




以上是关于RecyclerView 数据刷新的几种方式的主要内容,如果未能解决你的问题,请参考以下文章

关于recyclerView中ViewHolder中的几种不同方式获取position有什么区别

关于recyclerView中ViewHolder中的几种不同方式获取position有什么区别

关于recyclerView中ViewHolder中的几种不同方式获取position有什么区别

数据字典的缓存刷新与读取的几种方式

HTML5页面跳转的几种方法

jQuery Mobile页面跳转切换的几种方式