Paging
def paging_version = "3.0.1"
implementation "androidx.paging:paging-runtime:$paging_version"
// alternatively - without Android dependencies for tests
testImplementation "androidx.paging:paging-common:$paging_version"
// optional - RxJava2 support
implementation "androidx.paging:paging-rxjava2:$paging_version"
// optional - RxJava3 support
implementation "androidx.paging:paging-rxjava3:$paging_version"
// optional - Guava ListenableFuture support
implementation "androidx.paging:paging-guava:$paging_version"
// optional - Jetpack Compose integration
implementation "androidx.paging:paging-compose:1.0.0-alpha12"
def room_version = "2.3.0"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
// optional - RxJava2 support for Room
implementation "androidx.room:room-rxjava2:$room_version"
// optional - RxJava3 support for Room
implementation "androidx.room:room-rxjava3:$room_version"
// optional - Guava support for Room, including Optional and ListenableFuture
implementation "androidx.room:room-guava:$room_version"
// optional - Test helpers
testImplementation "androidx.room:room-testing:$room_version"
// optional - Paging 3 Integration
implementation "androidx.room:room-paging:2.4.0-alpha04"
<?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="wrap_content">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:text="TextView"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<?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.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="0dp"
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.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/btn_load"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="加载"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/btn_clear"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline2" />
<Button
android:id="@+id/btn_clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="清空"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/btn_load"
app:layout_constraintTop_toTopOf="@+id/guideline2" />
</androidx.constraintlayout.widget.ConstraintLayout>
package com.example.paging;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
@Entity(tableName = "student_table")
public class Student {
@PrimaryKey(autoGenerate = true)
private int id;
@ColumnInfo(name = "student_number")
private int studentNumber;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getStudentNumber() {
return studentNumber;
}
public void setStudentNumber(int studentNumber) {
this.studentNumber = studentNumber;
}
}
package com.example.paging;
import androidx.paging.DataSource;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
@Dao
public interface StudentDao {
@Insert
void insertStudents(Student... students);
@Query("DELETE FROM student_table")
void deleteAllStudents();
@Query("SELECT * FROM student_table ORDER BY id")
DataSource.Factory<Integer, Student> getAllStudents();
}
package com.example.paging;
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 synchronized StudentDatabase getStudentDatabase(Context context) {
if (studentDatabase == null){
studentDatabase = Room.databaseBuilder(context, StudentDatabase.class, "student_database").build();
}
return studentDatabase;
}
abstract StudentDao getStudentDao();
}
package com.example.paging;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.paging.PagedListAdapter;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.RecyclerView;
public class MyPagedAdapter extends PagedListAdapter<Student, MyPagedAdapter.MyViewHolder> {
protected MyPagedAdapter() {
super(new DiffUtil.ItemCallback<Student>() {
@Override
public boolean areItemsTheSame(@NonNull Student oldItem, @NonNull Student newItem) {
return oldItem.getId() == newItem.getId();
}
@Override
public boolean areContentsTheSame(@NonNull Student oldItem, @NonNull Student newItem) {
return oldItem.getStudentNumber() == newItem.getStudentNumber();
}
});
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View view = layoutInflater.inflate(R.layout.cell, 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("loading");
} else {
holder.textView.setText(String.valueOf(student.getStudentNumber()));
}
}
static class MyViewHolder extends RecyclerView.ViewHolder {
TextView textView;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.tv);
}
}
}
package com.example.paging;
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;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private Button btn_load, btn_clear;
private StudentDatabase studentDatabase;
private StudentDao studentDao;
private MyPagedAdapter myPagedAdapter;
private LiveData<PagedList<Student>> allStudentsLivePaged;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.rv);
btn_load = findViewById(R.id.btn_load);
btn_clear = findViewById(R.id.btn_clear);
myPagedAdapter = new MyPagedAdapter();
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
recyclerView.setAdapter(myPagedAdapter);
studentDatabase = StudentDatabase.getStudentDatabase(this);
studentDao = studentDatabase.getStudentDao();
// 参数2改小就能看到loading
allStudentsLivePaged = new LivePagedListBuilder<>(studentDao.getAllStudents(), 20).build();
allStudentsLivePaged.observe(this, new Observer<PagedList<Student>>() {
@Override
public void onChanged(PagedList<Student> students) {
myPagedAdapter.submitList(students);
students.addWeakCallback(null, new PagedList.Callback() {
@Override
public void onChanged(int i, int i1) {
Log.d("wmj", "onChanged: " + students);
}
@Override
public void onInserted(int i, int i1) {
}
@Override
public void onRemoved(int i, int i1) {
}
});
}
});
btn_load.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Student[] students = new Student[1000];
for (int i = 0; i < 1000; i++) {
Student student = new Student();
student.setStudentNumber(i);
students[i] = student;
}
new InsertStudents(studentDao).execute(students);
}
});
btn_clear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new ClearStudents(studentDao).execute();
}
});
}
static class InsertStudents extends AsyncTask<Student, Void, Void>{
StudentDao studentDao;
public InsertStudents(StudentDao studentDao) {
this.studentDao = studentDao;
}
@Override
protected Void doInBackground(Student... students) {
studentDao.insertStudents(students);
return null;
}
}
static class ClearStudents extends AsyncTask<Void, Void, Void>{
StudentDao studentDao;
public ClearStudents(StudentDao studentDao) {
this.studentDao = studentDao;
}
@Override
protected Void doInBackground(Void... voids) {
studentDao.deleteAllStudents();
return null;
}
}
}