首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【Android】RecyclerView循环视图(2)——动态加载数据

【Android】RecyclerView循环视图(2)——动态加载数据

作者头像
三三是该溜子
发布2025-08-23 08:22:20
发布2025-08-23 08:22:20
8000
代码可运行
举报
文章被收录于专栏:该溜子的专栏该溜子的专栏
运行总次数:0
代码可运行

一:在适配器中设置item布局数据

1:ViewHolder中找控件

提问:我们都是设置的相同的数据,怎么样为每一个item设置不同的数据

第一反应去view中查找控件,但是我们已经把view交给ViewHolder管理了,所以应该去ViewHolder中查找

不在这里

2:设置数据

提问:控件找到了,在哪设置数据?

注意:这里的ivPicture,tvTitle是在构造方法中;把它们设置为MyViewHolder中的成员变量,便于onBindViewHolder方法中使用

3:设置数据优化版本

这件设置数据的事情还能变得更加简单一点

(1)Adapter泛型源码

带着泛型,是继承自ViewHolder的类型

如果声明为泛型,那么我们下面重写的方法中的返回类型也会被约束

也不用做强制转换了,直接使用holder即可

(2)效果如下

二:在Adapter中添加动态数据

夺命连环第三问:数据生效了,数据是固定的,怎么样把数据写活呢?

在一个列表中可能会有数十上百条数据,优先方案使用一个容器来保存这些图片,主题,标题

1:创建Article类

生成get和set方法,注意带三个参数的构造方法

代码语言:javascript
代码运行次数:0
运行
复制
package com.xlong.myapplication.recyclerview;

public class Article {
    private String title;//标题
    private String desc;//描述
    private String author;//作者
    private long publish;//发布时间
    private int picture;//图片资源

    public Article(String title, String author, int picture) {
        this.title = title;
        this.author = author;
        this.picture = picture;
    }

    public int getPicture() {
        return picture;
    }

    public void setPicture(int picture) {
        this.picture = picture;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public long getPublish() {
        return publish;
    }

    public void setPublish(long publish) {
        this.publish = publish;
    }
}

2:创建容器

构造方法

代码语言:javascript
代码运行次数:0
运行
复制
    public ArticleAdapter(){
        articles = createData();
        Log.i(TAG, "ArticleAdapter: articles.size = " + articles.size());
    }

不要在构造方法中无脑添加新闻文章数据,这里创建一个createData方法

3:createData方法

代码语言:javascript
代码运行次数:0
运行
复制
    /**
     * 自己造一点数据给RecyclerView
     *
     * @return 返回一个存放20条数据的新闻列表
     */
    private ArrayList<Article> createData() {
        ArrayList<Article> articles = new ArrayList<>();
        articles.add(new Article("辽宁清原抽水蓄能电站最后一台定子吊装完成",
                "人民网-图片频道,供稿:人民资讯", R.drawable.ic_article_1));
        articles.add(new Article("通行时间再缩短!广湛高铁佛山站建设正式启动",
                "人民网-广东频道,供稿:人民资讯", R.drawable.ic_article_2));
        articles.add(new Article("19岁杭州帅小伙第一名,还有人抓到一只甲鱼!今早3000多人在钱塘江边,太欢乐了",
                "杭州网", R.drawable.ic_article_3));
        articles.add(new Article("今日起“两江小渡”航线恢复正常运营",
                "上游新闻", R.drawable.ic_article_4));
        articles.add(new Article("中国太保小排球夏令营在漳州火热启航",
                "国际时事讲解", R.drawable.ic_article_5));
        articles.add(new Article("奋力推动民族地区高质量发展和现代化建设迈出新步伐",
                "当代先锋网", R.drawable.ic_article_6));
        articles.add(new Article("相信青春的力量|写在我省2024年万名大学生志愿服务西部计划出征之际",
                "人民网-图片频道,供稿:人民资讯", R.drawable.ic_article_7));
        articles.add(new Article("量身定制“海外订单” 贵州汽车制造开拓国际市场",
                "当代先锋网", R.drawable.ic_article_8));
        articles.add(new Article("势不可挡……在这里,乡村振兴的新引擎正发出强劲动力",
                "鲁网", R.drawable.ic_article_9));
        articles.add(new Article("菏泽职业学院召开2024届毕业生第二轮就业核查工作部署会",
                "大众报业·齐鲁壹点", R.drawable.ic_article_10));
        articles.add(new Article("菏泽职业学院学前教育系(育中教育学院)斩获省级大赛一等奖",
                "西安快线", R.drawable.ic_article_11));
        articles.add(new Article("菏泽职业学院一类教学大赛,二等奖+2!",
                "大众报业·齐鲁壹点", R.drawable.ic_article_12));
        articles.add(new Article("中央气象台停止对“格美”编号 湖南辽宁吉林等地仍有强降雨",
                "国际时事讲解", R.drawable.ic_article_13));
        articles.add(new Article("习水仙源镇:清凉山水引客来 消夏避暑人气足",
                "多彩贵州网", R.drawable.ic_article_14));
        articles.add(new Article("习水县寨坝镇:清凉避暑地 康养第二乡",
                "多彩贵州网", R.drawable.ic_article_15));
        articles.add(new Article("赤水市元厚镇:新品荔枝出山记",
                "人民网-图片频道,供稿:人民资讯", R.drawable.ic_article_16));
        articles.add(new Article("习水三岔河镇小小错车道 畅通出行暖民心",
                "湖南日报", R.drawable.ic_article_17));
        articles.add(new Article("习水土城镇社会实践活动丰富学生假期生活",
                "上海咨询", R.drawable.ic_article_18));
        articles.add(new Article("赤水建强“小站点”释放乡村振兴新动能",
                "福建新闻网,供稿:人民资讯", R.drawable.ic_article_19));
        articles.add(new Article("习水同民镇:火龙果喜丰收 果农笑开颜",
                "上游新闻,供稿:人民资讯", R.drawable.ic_article_20));

        return articles;
    }

类成员变量articles和createData方法内的局部变量articles指向的是同一个内存地址

三:动态数据和布局做关联

1:position

当前触发onBindVIewHolder方法的位置

打印个日志观察一下position——每一条item都有位置0,1,2,3,4

每次item被绘制的时候都会触发一次onBindViewHolder方法,并且位置也会随之变化,而我们的ArrayList的index索引也是从0开始,所以我们可以利用索引这一点作为桥梁,让holder取到ArrayList中的数据

代码语言:javascript
代码运行次数:0
运行
复制
     /**
     *  有一条item就调用一次这个方法
     *  数据如何与item布局做关联
     */
    @Override
    public void onBindViewHolder(@NonNull ArticleAdapter.MyViewHolder holder, int position) {
        Log.i(TAG, "onBindViewHolder: position" + position);
//        MyViewHolder myViewHolder = (MyViewHolder)holder;

//        holder.ivPicture.setImageResource(R.drawable.icon_wechat);
//        holder.tvTitlet.setText("我是在Java中指定的title标题!!!");
//        holder.tvAuthor.setText("我是作者");

        Article article = articles.get(position);
        holder.ivPicture.setImageResource(article.getPicture());
        holder.tvTitlet.setText(article.getTitle());
        holder.tvAuthor.setText(article.getAuthor());
    }

2:getItemCount

知道这个方法的作用是返回 RecyclerView 中的 item 总数

如果显示的条数多余我们有的数据呢?就会越界

优雅写法

代码语言:javascript
代码运行次数:0
运行
复制
    /**
     * @return  告诉RecyclerView显示多少条数据
     */
    @Override
    public int getItemCount() {
//        if (articles != null){
//            return articles.size();
//        }else {
//            return 0;
//        }
        return articles == null ? articles.size() : 0;
    }

总结:核心执行流程

代码语言:javascript
代码运行次数:0
运行
复制
ArticleListActivity.onCreate()  
→ 加载布局 → 获取RecyclerView  
→ 设置LinearLayoutManager  
→ new ArticleAdapter(设置适配器,初始化数据)
->ArticleAdapter类构造方法中创建数据  
→ RecyclerView与Adapter绑定  
  → getItemCount() → 返回数据总数(20) 适配器就会选择显示20条数据 
  → onCreateViewHolder() → 创建列表项视图和ViewHolder(按需创建,如5次)  
  → onBindViewHolder() → 为每个位置绑定数据(执行20次)  
→ 列表显示,滚动时复用ViewHolder并重新绑定数据  

四:模拟数据滞后加载场景

实际上很多场景下,RecycleView不是说一创建好,这些数据就存在了,而是经过了一段时间,我们的recycleView才会被创建好

这里我们使用一个点击按钮,当点击按钮后,我们才把这些数据进行展示,模拟数据滞后性

1:加载数据

在点击按钮后,调用createData方法创建数据

代码语言:javascript
代码运行次数:0
运行
复制
<Button
        android:id="@+id/btn_load"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="加载数据"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
代码语言:javascript
代码运行次数:0
运行
复制
		//点击加载数据按钮,加载数据;目的:模拟数据的延迟效果
        findViewById(R.id.btn_load).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ArrayList<Article> articles = createData();
                adapter.setArticles(articles);
            }
        });

在ArticleAdapter中创建set方法

代码语言:javascript
代码运行次数:0
运行
复制
public void setArticles(ArrayList<Article> articles) {
        this.articles = articles;
        //告诉adapter,关联的数据源有变化,请重新根据数据做出调整
        notifyDataSetChanged();
        Log.i(TAG, "setArticles: article.size = " + articles.size());
    }
(1)notifyDataSetChanged

问题引入:现在点击按钮是没有反应的,没有数据的

分析:我们仅仅是改变了这个容器中的数据,但是Adapter适配器本身不知道容器中数据更新了,size不为0了,所以需要调用notifyDataSetChanged();提醒RecyclerView.Adapter刷新一下信息(像极了村里才通网)

总结:数据需要更新的场景下,一般都会用到notifyDataSetChanged这个方法

2:修改数据

列表的某一个部分发生了变化,也可以用notify,这里我们同样用模拟的方法演示

代码语言:javascript
代码运行次数:0
运行
复制
    <Button
        android:id="@+id/btn_modify"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="修改部分"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
代码语言:javascript
代码运行次数:0
运行
复制
        findViewById(R.id.btn_modify).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ArrayList<Article> articles = adapter.getArticles();
                Article article = articles.get(1);
                article.setTitle("我修改了第二条数据的标题");
//                adapter.notifyDataSetChanged();//不必全部刷新
                adapter.notifyItemChanged(1);
            }
        });

在ArticleAdapter中创建get方法

代码语言:javascript
代码运行次数:0
运行
复制
public ArrayList<Article> getArticles() {
        return articles;
}
(1)notifyItemChanged

对单条数据进行刷新而非全部,这里节约了资源和提高了性能

Adapter中也提供了很多其他的刷新方法,了解即可

3:删除数据

代码语言:javascript
代码运行次数:0
运行
复制
    <Button
        android:id="@+id/btn_remove"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="删除"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent" />
代码语言:javascript
代码运行次数:0
运行
复制
		findViewById(R.id.btn_remove).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ArrayList<Article> articles = adapter.getArticles();
                Log.i(TAG, "onClick: 初始article size = " + articles.size());
                articles.remove(2);
                adapter.notifyItemRemoved(2);

                ArrayList<Article> articles1 = adapter.getArticles();
                Log.i(TAG, "onClick: 删除后article size = " + articles1.size());
            }
        });
(1)数据源ArrayList和Adapter同步删除

问题来了:删除一个item后,数据源的size大小依旧是20;第一次删除是有效果的,全局列表刷新,第二次就没效果了

分析:因为数据源本身还是20条数据,没有发生变化。他就会重新的根据数据源来匹配怎么显示

解决方案:对某个列表做移除或者插入数据时候,要先对数据源做一次操作;这样才能保证数据的一致性

其实就是先对ArrayList(数据源)做一次移除操作,再对Adapter做一次移除操作

总结:对RecyclerView的数据做增删查改操作的时候,记住同时也要处理数据源

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-08-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一:在适配器中设置item布局数据
    • 1:ViewHolder中找控件
    • 2:设置数据
    • 3:设置数据优化版本
      • (1)Adapter泛型源码
      • (2)效果如下
  • 二:在Adapter中添加动态数据
    • 1:创建Article类
    • 2:创建容器
    • 3:createData方法
  • 三:动态数据和布局做关联
    • 1:position
    • 2:getItemCount
    • 总结:核心执行流程
  • 四:模拟数据滞后加载场景
    • 1:加载数据
      • (1)notifyDataSetChanged
    • 2:修改数据
      • (1)notifyItemChanged
    • 3:删除数据
      • (1)数据源ArrayList和Adapter同步删除
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档