Android :Paging (分页)加载数据-简单应用

1.Paging介绍:

安卓Paging是一种分页加载数据的方法,它基于无限滚动模式而设计,可以帮助应用更高效地利用网络带宽和系统资源。Paging库可以加载和显示来自本地存储或网络中更大的数据集中的数据页面,适用于以列表的形式加载大量的数据。

Paging库具有以下功能:

1. 分页数据的内存中缓存,有助于确保应用在处理分页数据时高效使用系统资源。
2. 内置的请求去重功能,可确保应用高效利用网络带宽和系统资源。
3. 可配置的RecyclerView适配器,会在用户滚动到已加载数据的末尾时自动请求数据。
4. 对Kotlin协程和数据流以及LiveData和RxJava的一流支持。
5. 内置对错误处理功能的支持,包括刷新和重试功能。

总之,安卓Paging可以帮助开发者更有效地加载和管理大量数据,提高应用的性能和用户体验。

2.Paging使用:

官方文档:Paging  |  Jetpack  |  Android Developers

1.导入依赖:在build.gradle文件中加入

dependencies {
 
        //Room
        def room_version = "2.5.0"
        implementation "androidx.room:room-runtime:$room_version"
        annotationProcessor "androidx.room:room-compiler:$room_version"
        
       //Paging
      def paging_version = "3.2.1"
      implementation "androidx.paging:paging-runtime:$paging_version"

        
}

2.布局文件 activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.9" />

    <Button
        android:id="@+id/btnPopulate"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="生成数据"
        app:layout_constraintBottom_toBottomOf="@+id/btnClean"
        app:layout_constraintEnd_toStartOf="@+id/btnClean"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/btnClean" />

    <Button
        android:id="@+id/btnClean"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="清除数据"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/btnPopulate"
        app:layout_constraintTop_toTopOf="@+id/guideline2" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/guideline2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

3. 里面每一项的布局  item.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="100dp">

    <ImageView
        android:id="@+id/item_img"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/guideline3"
        app:layout_constraintEnd_toStartOf="@+id/guideline5"
        app:layout_constraintStart_toStartOf="@+id/guideline4"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/baseline_img" />

    <TextView
        android:id="@+id/item_tv"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:gravity="center"
        android:text="TextView"
        android:textSize="20sp"
        app:layout_constraintBottom_toTopOf="@+id/guideline3"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/item_img"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="1.0" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.1" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.3" />
</androidx.constraintlayout.widget.ConstraintLayout>

3.创建数据库

1.实体类 Student.java

package com.example.mypaging;

import androidx.room.Entity;
import androidx.room.PrimaryKey;

//实体类
@Entity
public class Student {
    //主键
    @PrimaryKey(autoGenerate = true)
    private int id;

    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

2.创建接口 StudentDao.java

package com.example.mypaging;

import androidx.paging.DataSource;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;

//接口 Dao  方法签名
@Dao
public interface StudentDao {

    //插入数据
    @Insert
    void insertStudents(Student... students);

    //删除数据
    @Query("delete from student")
    void deleteTBData();

    //查询
    @Query("select * from student order by id desc")
    DataSource.Factory<Integer, Student> getAllStudents();   //paging
//    LiveData<List<Student>> getAllStudents();


}

3.  创建抽象类继承RoomDatabase  StudentDataBase.java

package com.example.mypaging;

import android.content.Context;

import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;

@Database(entities = {Student.class}, version = 1, exportSchema = false)
public abstract class StudentDataBase extends RoomDatabase {
    private static StudentDataBase studentDataBase;

    public static StudentDataBase getInstance(Context context) {
        if (studentDataBase == null) {
            studentDataBase = Room.databaseBuilder(context, StudentDataBase.class, "studentDB").build();
        }
        return studentDataBase;
    }

    public abstract StudentDao studentDao();
}

4. AsyncTask 异步任务 删除 和 保存数据方法

InsertAsyncTask.java

package com.example.mypaging;

import android.os.AsyncTask;

/**
 * AsyncTask 在 API 级别 30 中此字段已弃用 , 请改用标准或 Kotlin 并发实用程序
 * 插入数据 异步任务
 * android.os.AsyncTask<Params、进度、结果>
 */
public class InsertAsyncTask extends AsyncTask<Student, Void, Void> {

    private StudentDao studentDao;

    public InsertAsyncTask(StudentDao studentDao) {
        this.studentDao = studentDao;
    }

    /**
     * 4个步骤
     * 执行异步任务时,任务会经历 4 个步骤:
     * <p>
     * onPreExecute(),在任务之前的 UI 线程上调用 被执行。此步骤通常用于设置任务,例如 在用户界面中显示进度条。
     * <p>
     * doInBackground(Params),在后台线程上调用 执行完毕后立即执行。
     * 此步骤用于 执行可能需要很长时间的后台计算。参数 的异步任务被传递到此步骤。
     * 计算结果必须 由此步骤返回,并将传递回最后一步。这一步 还可用于发布一个或多个单元 的进步。
     * 这些值在步骤中发布在 UI 线程上。onPreExecute()publishProgress(Progress)onProgressUpdate(Progress)
     * <p>
     * onProgressUpdate(Progress),在 UI 线程上调用 调用 。
     * 执行的时间是 定义。此方法用于在用户中显示任何形式的进度 接口,而后台计算仍在执行。
     * 例如 它可用于对进度条进行动画处理或在文本字段中显示日志。publishProgress(Progress)
     * <p>
     * onPostExecute(Result),在后台之后的 UI 线程上调用 计算完成。将后台计算的结果传递给主界面。
     */

    @Override
    protected Void doInBackground(Student... students) {
        studentDao.insertStudents(students);
        return null;
    }

}

DeleteTBAsyncTask.java

package com.example.mypaging;

import android.os.AsyncTask;


public class DeleteTBAsyncTask extends AsyncTask<Void, Void, Void> {
    private StudentDao studentDao;

    public DeleteTBAsyncTask(StudentDao studentDao) {
        this.studentDao = studentDao;
    }

    @Override
    protected Void doInBackground(Void... voids) {
        studentDao.deleteTBData();
        return null;
    }
}

4.创建适配器

1. MyViewHolder.java

package com.example.mypaging;

import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

// 列表中的每一项数据
public class MyViewHolder extends RecyclerView.ViewHolder {
     TextView textView;
     ImageView imageView;
    public MyViewHolder(@NonNull View itemView) {
        super(itemView);
        textView = itemView.findViewById(R.id.item_tv);
        imageView = itemView.findViewById(R.id.item_img);
    }
}

2. MyPageAdapter.java

package com.example.mypaging;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.paging.PagedListAdapter;
import androidx.recyclerview.widget.DiffUtil;

public class MyPageAdapter extends PagedListAdapter<Student, MyViewHolder> {

    public MyPageAdapter() {
        super(new DiffUtil.ItemCallback<Student>() {
            @Override
            public boolean areItemsTheSame(@NonNull Student oldItem, @NonNull Student newItem) {
                //比较id是否相等
                return oldItem.getId() == newItem.getId();
            }

            @Override
            public boolean areContentsTheSame(@NonNull Student oldItem, @NonNull Student newItem) {
                //比较内容是否相等
                return oldItem.getName().equals(oldItem.getName());
            }
        });
    }


    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        //获取视图对象
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
        return new MyViewHolder(view);
    }


    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        //获取数据
        Student student = getItem(position);
        if (student == null) {
            //容器中还没有数据时
            holder.textView.setText("正在加载...");
        } else {
            holder.textView.setText(student.getName());
        }

    }


}

5. MainActivity.java

package com.example.mypaging;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.paging.LivePagedListBuilder;
import androidx.paging.PagedList;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

public class MainActivity extends AppCompatActivity {

    private Button btnPopulate, btnClean;

    private StudentDataBase studentDataBase;
    private StudentDao studentDao;
    //往视图中添加数据 需要用适配器
    private RecyclerView recyclerView;
    private MyPageAdapter myPageAdapter;

    //数据获取
    LiveData<PagedList<Student>> allStudentsLivePaged;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btnPopulate = findViewById(R.id.btnPopulate);
        btnClean = findViewById(R.id.btnClean);
        recyclerView = findViewById(R.id.recyclerView);

        myPageAdapter = new MyPageAdapter();

        recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
        //分隔符
        recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
        //往视图中添加适配器
        recyclerView.setAdapter(myPageAdapter);

        studentDataBase = StudentDataBase.getInstance(this);
        studentDao = studentDataBase.studentDao();
        allStudentsLivePaged = new LivePagedListBuilder<>(studentDao.getAllStudents(), 3).build();
        //观察
        allStudentsLivePaged.observe(this, new Observer<PagedList<Student>>() {
            @Override
            public void onChanged(PagedList<Student> students) {
                //内容发生改变
                myPageAdapter.submitList(students);
                students.addWeakCallback(null, new PagedList.Callback() {
                    @Override
                    public void onChanged(int i, int i1) {
                        Log.e("TAG", "----观察--" + students);
                    }

                    @Override
                    public void onInserted(int i, int i1) {

                    }

                    @Override
                    public void onRemoved(int i, int i1) {

                    }
                });
            }
        });

        //按钮事件
        btnPopulate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Student[] students = new Student[100];
                for (int i = 0; i < 100; i++) {
                    Student student = new Student();
                    student.setName("学生"+i);
                    students[i] = student;
                }
                new InsertAsyncTask(studentDao).execute(students);
            }
        });

        //事件
        btnClean.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new DeleteTBAsyncTask(studentDao).execute();
            }
        });

    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/238608.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

VSCode配置记录

1. 修改代码背景颜色 1&#xff09;Shift Command P&#xff0c;搜索框输入&#xff1a;settings.json 2&#xff09;输入配置 {"workbench.colorCustomizations": {"editor.lineHighlightBackground": "#86e9e93d", # 修改鼠标所在行背景色…

自动化测试 —— Web自动化三大报错

Web自动化三大报错有哪些呢&#xff1f;接下来给大家讲讲。 Web自动化三大报错&#xff08;Exception&#xff09; 1. Exception1&#xff1a;no such element&#xff08;没有在页面上找到这个元素&#xff09; reason1&#xff1a;元素延迟加载了 solution&#xff1a; …

功率放大器有哪些功能和作用

功率放大器是一种电子设备&#xff0c;主要用于将输入的低功率信号放大为更大的功率信号。功率放大器的主要功能和作用包括&#xff1a; 信号放大&#xff1a;功率放大器可以将输入的低功率信号放大为更大的功率信号。这对于一些需要输出更大功率的应用来说非常重要&#xff0c…

外包干了3年,技术退步太明显了。。。。。

先说一下自己的情况&#xff0c;本科生生&#xff0c;18年通过校招进入武汉某软件公司&#xff0c;干了差不多3年的功能测试&#xff0c;今年国庆&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能…

腾讯云服务器购买:腾讯云服务器购买指南一步步全流程攻略

腾讯云服务器购买流程直接在官方秒杀活动上购买比较划算&#xff0c;在云服务器CVM或轻量应用服务器页面自定义购买价格比较贵&#xff0c;但是自定义购买云服务器CPU内存带宽配置选择范围广&#xff0c;活动上购买只能选择固定的活动机&#xff0c;选择范围窄&#xff0c;但是…

正点原子高速无线下载器下载bin文件

有时候需要帮忙调试&#xff0c;直接下载写好代码的bin文件比较快&#xff0c;所以找到这个方式&#xff0c;关于keil如何生成bin文件可以看上篇文章&#xff0c;其他IDE生成方式我就遇到再说了&#xff0c;可以自己在网上搜教程。 关于正点原子的高速无线下载器可以去下载官方…

vrep学习笔记8——将vrep中graph文件导出为csv.文件,并导入matlab中绘制曲线图

在机械臂仿真过程中&#xff0c;使用vrep中的graph图表功能绘制出的曲线不够清晰&#xff0c;如何将graph中的图表数据导出为csv文件&#xff0c;并使用matlab绘制出同样的曲线图呢&#xff1f; 1.将vrep中的graph导出为csv文件 首先选中graph如下 选择file-export-selected g…

报错:AttributeError: ‘DataFrame‘ object has no attribute ‘reshape‘

这个错误通常发生在你试图在 Pandas DataFrame 上直接使用 reshape 方法时。reshape 方法通常与 NumPy 数组相关联&#xff0c;而不是 Pandas DataFrame。 如果你正在使用 Pandas DataFrame 并希望重新塑造它&#xff0c;你应该使用 Pandas 的重塑函数&#xff0c;如 pivot、m…

06_W5500_DHCP

1.DHCP协议介绍&#xff1a; DHCP&#xff08;Dynamic Host Configuration Protocol&#xff09;是一种用于自动分配IP地址和其他网络配置信息的协议。它允许网络中的设备&#xff08;如计算机、手机、打印机等&#xff09;在连接到网络时自动获取IP地址、子网掩码、默认网关、…

geolife笔记:比较不同轨迹相似度方法

1 问题描述 在geolife 笔记&#xff1a;将所有轨迹放入一个DataFrame-CSDN博客中&#xff0c;已经将所有的轨迹放入一个DataFrame中了&#xff0c;我们现在需要比较&#xff0c;在不同的轨迹距离度量方法下&#xff0c;轨迹相似度的效果。 这里采用论文笔记&#xff1a;Deep R…

前沿技术|张磊:RR22 Blazing Fast PSI 实现介绍

“隐语”是开源的可信隐私计算框架&#xff0c;内置 MPC、TEE、同态等多种密态计算虚拟设备供灵活选择&#xff0c;提供丰富的联邦学习算法和差分隐私机制 开源项目 github.com/secretflow gitee.com/secretflow ​ 11月25日&#xff0c;「隐语开源社区 Meetup西安站」顺利举…

Pika:AIGC新秀,视频生成产业或迎来GPT时刻

今天分享的AIGC系列深度研究报告&#xff1a;《Pika&#xff1a;AIGC新秀&#xff0c;视频生成产业或迎来GPT时刻》。 &#xff08;报告出品方&#xff1a;中泰证券&#xff09; 报告共计&#xff1a;11页 Pika&#xff1a;专注Text to Video生成场景&#xff0c;支持3D和动漫…

从视频中提取图片,轻松制作专属视频封面

你是否曾经为如何制作一个吸引人的视频封面而烦恼&#xff1f;现在&#xff0c;我们将向你展示如何从视频中提取图片&#xff0c;并轻松制作专属的视频封面。无论你是视频编辑新手&#xff0c;还是经验丰富的专业人士&#xff0c;这个技巧都能够帮助你快速提升你的视频品质。 …

时间戳与QDateTime转换,以及QString转时间戳

1、主要有时间戳->QDateTime,QDateTime->QString 2、同时QString->QDateTime,QDateTime->时间戳 详情见代码&#xff1a; //QDateTime转时间戳qint64 time QDateTime::currentSecsSinceEpoch();double nowTime (double)time;qDebug()<<"nowTime1111…

【VTK】VTK中的光标样式

很高兴在雪易的CSDN遇见你 前言 本文分享VTK中的光标设置相关内容技术&#xff0c;希望对各位小伙伴有所帮助&#xff01; 感谢各位小伙伴的点赞关注&#xff0c;小易会继续努力分享&#xff0c;一起进步&#xff01; 你的点赞就是我的动力(&#xff3e;&#xff35;&#…

你知道如何画时间轴吗?

时间轴的英文是time axis。贯穿四维空间的一条线&#xff0c;是虚数轴&#xff0c;时间轴上一段距离表示时间 。&#xff08;源自“百度百科”&#xff09; 时间轴&#xff1a;通过互联网技术&#xff0c;依据时间顺序&#xff0c;把一方面或多方面的事件串联起来&#xff0c;…

12.11作业

1. 完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如果账号和密码不匹配&…

java面试题-mysql索引相关问题

远离八股文&#xff0c;面试大白话&#xff0c;通俗且易懂 看完后试着用自己的话复述出来。有问题请指出&#xff0c;有需要帮助理解的或者遇到的真实面试题不知道怎么总结的也请评论中写出来&#xff0c;大家一起解决。 java面试题汇总-目录-持续更新中 这一块本想着晚一点再整…

大型软件编程实际应用实例:个体诊所电子处方系统,使用配方模板功能输入症状就可开出处方软件操作教程

一、前言&#xff1a; 在开电子处方的时候&#xff0c;如果能够输入症状就可以一键导入配方&#xff0c;则在很大程度上可以节省很多时间。而且这个配方可以根据自己的经验自己设置&#xff0c;下面以 佳易王诊所电子处方软件为例说明。 二、具体一键导入配方详细操作教程 点击…

Linux本地部署Mosquitto MQTT协议消息服务端并实现远程访问【内网穿透】

文章目录 前言1. Linux 搭建 Mosquitto2. Linux 安装Cpolar3. 创建MQTT服务公网连接地址4. 客户端远程连接MQTT服务5. 代码调用MQTT服务6. 固定连接TCP公网地址7. 固定地址连接测试 前言 Mosquitto是一个开源的消息代理&#xff0c;它实现了MQTT协议版本3.1和3.1.1。它可以在不…