Jetpack - Room&Paging

Room官方文档

Room 持久性库在 SQLite 的基础上提供了一个抽象层,让用户能够在充分利用 SQLite 的强大功能的同时,获享更强健的数据库访问机制。

该库可帮助您在运行应用的设备上创建应用数据的缓存。此缓存充当应用的单一可信来源,使用户能够在应用中查看关键信息的一致副本,无论用户是否具有互联网连接。

Paging官方文档

分页库可帮助您一次加载和显示一小块数据。按需载入部分数据会减少网络带宽和系统资源的使用量

简单的使用

dependencies {
      def room_version = "2.2.0-rc01"
      implementation "androidx.room:room-runtime:$room_version"
      annotationProcessor "androidx.room:room-compiler:$room_version" 
      def paging_version = "2.1.0"
      implementation "androidx.paging:paging-runtime:$paging_version" 
 }
ROOM
  • Bean
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;

@Entity
public class Student {
	@PrimaryKey(autoGenerate = true)
	public int id;

	@ColumnInfo(name = "s_name") //数据库列名,不写就默认用字段名作为列名
	private String name;
	private int age;
	private int s_num;//新增字段 ,学号 ,新增字段后数据库版本升为2,并写版本迁移sql

	public Student(String name, int age, int s_num) {
		this.name = name;
		this.age = age;
		this.s_num = s_num;
	}

	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;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int getS_num() {
		return s_num;
	}

	public void setS_num(int s_num) {
		this.s_num = s_num;
	}
}
  • DAO
@Dao
public interface StudentDao {


	@Insert
	void insert(Student... students);

	@Update
	void updateStudent(Student... students);

	@Delete
	void deletec(Student student);

	@Query("DELETE from Student")
	void deleteAllStudent();

	@Query("SELECT * FROM Student where s_name =(:name)")
	Student queryStudentByName(String name);

	//paging需要用到这种模式
	@Query("SELECT * FROM Student order by id DESC")
	DataSource.Factory<Integer, Student> getAllStudent();

	@Query("SELECT * FROM Student order by id DESC")
	LiveData<List<Student>> getAllListStudent();

	@Query("SELECT * FROM Student order by id DESC")
	List<Student> queryAllListStudent();
}
  • Database
//数据库操作 ,这里可以多个Entity ,dao
/exportSchema 会生成一个json文件 记录sql语句的操作,需要在gradle配置文件路径
@Database(entities = {Student.class}, version = 2, exportSchema = false)
public abstract class MyDataBase extends RoomDatabase {

	private static MyDataBase instance;

	public static synchronized MyDataBase getInstance(Context context) {
		if (instance == null) {
			RoomDatabase.Builder<MyDataBase> builder = Room.databaseBuilder(context.getApplicationContext(), MyDataBase.class, "test");
			//builder.fallbackToDestructiveMigration();//使用这个配置 ,数据库升级会清除以前的数据,重新建表
			builder.addMigrations(MIGRATION_1_2, MIGRATION_2_3);//数据库升级
			instance = builder.build();
		}
		return instance;
	}

	//提供学生的dao
	public abstract StudentDao studentDao();

	//数据库版本升级 , 数据迁移范例
	static final Migration MIGRATION_1_2 = new Migration(1, 2) {
		@Override
		public void migrate(@NonNull SupportSQLiteDatabase database) {
			database.execSQL("ALTER TABLE STUDENT ADD COLUMN S_NUM INTEGER NOT NULL DEFAULT 1");
		}
	};
	static final Migration MIGRATION_2_3 = new Migration(2, 3) {
		@Override
		public void migrate(@NonNull SupportSQLiteDatabase database) {
			//database.execSQL("");
		}
	};
}

  • Repository
  • 对数据库的操作都在这个类 ,增删改查
  • 需要异步执行 ,room没有异步执行会抛异常(如需要在主线程执行,需要在database配置allowMainThreadQueries())
public class StudentRepository {

	private final StudentDao studentDao;
	private String TAG = "StudentRepository";


	private LiveData<List<Student>> allListStudent;

	public StudentRepository(Context context) {
		MyDataBase instance = MyDataBase.getInstance(context);
		studentDao = instance.studentDao();
		allListStudent = studentDao.getAllListStudent();
	}

	public LiveData<List<Student>> getAllListStudent() {
		return allListStudent;
	}

	public DataSource.Factory<Integer, Student> getAllStudent() {
		return studentDao.getAllStudent();
	}
	public void insert(Student... students) {
		Log.i(TAG, "insert: ");
		new AsyncTaskInsert(studentDao).execute(students);
	}

	public void delete() {
		new AsyncTaskDelete(studentDao).execute();
	}

	public void queryAll() {
		new AsyncTaskQuery(studentDao).execute();
	}

	public void queryByName(Student student) {
		new AsyncTaskQueryByName(studentDao).execute(student);
	}

	static class AsyncTaskInsert extends AsyncTask<Student, Void, Void> {
		private StudentDao studentDao;

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

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

	static class AsyncTaskDelete extends AsyncTask<Void, Void, Void> {

		private StudentDao studentDao;

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


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

	static class AsyncTaskQuery extends AsyncTask<Student, Void, Void> {

		private StudentDao studentDao;
		private String TAG = "AsyncTaskQuery";

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

		@Override
		protected Void doInBackground(Student... students) {
			List<Student> list = studentDao.queryAllListStudent();
			for (Student student : list) {
				String name = student.getName();
				int age = student.getAge();
				Log.i(TAG, "Student -- name : " + name + " age : " + age);
			}

			return null;
		}
	}

	static class AsyncTaskQueryByName extends AsyncTask<Student, Void, Void> {

		private StudentDao studentDao;
		private String TAG = "AsyncTaskQueryByName";

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

		@Override
		protected Void doInBackground(Student... students) {

			Student student = studentDao.queryStudentByName(students[0].getName());
			String name = student.getName();
			int age = student.getAge();
			Log.i(TAG, "Student -- name : " + name + " age : " + age);
			return null;
		}
	}
}

  • RoomViewModel
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.paging.DataSource;

public class RoomViewModel extends AndroidViewModel {

	private StudentRepository repository;
	private String TAG = "RoomViewModel";

	public RoomViewModel(@NonNull Application application) {
		super(application);
		repository = new StudentRepository(application.getApplicationContext());
	}

	public LiveData<List<Student>> getListStudent() {
		Log.i(TAG, "getListStudent: ");

		return repository.getAllListStudent();
	}

	private int size = 50;

	public void insert() {
		Student[] students = new Student[size];
		Student student;
		for (int i = 0; i < size; i++) {
			student = new Student("张 " + i, 20 + i, i);
			students[i] = student;
		}
		Log.i(TAG, "insert: ");
		repository.insert(students);
	}

	public void delete() {
		repository.delete();
	}

	public void queryAll() {
		repository.queryAll();
	}

	public void queryByName(Student student) {
		repository.queryByName(student);
	}

	public DataSource.Factory<Integer, Student> getAllStudent() {
		return repository.getAllStudent();
	}

}
Paging
  • PagedListAdapter

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

public class MyAdapter extends PagedListAdapter<Student, MyAdapter.MyViewHolder> {

	public MyAdapter() {
		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.getAge() == newItem.getAge();
			}
		});
	}

	@NonNull
	@Override
	public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
		LayoutInflater from = LayoutInflater.from(parent.getContext());
		View view = from.inflate(R.layout.student, parent, false);
		return new MyViewHolder(view);
	}

	@Override
	public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {

		Student item = getItem(position);
		if (item == null) {
			holder.textView.setText("加载中 ...");
		} else {
			holder.textView.setText(item.getName() + " ... " + item.getAge());
		}
	}

	static class MyViewHolder extends RecyclerView.ViewHolder {

		TextView textView;

		public MyViewHolder(@NonNull View itemView) {
			super(itemView);
			textView = itemView.findViewById(R.id.textView_student);
		}

	}
}
  • RecyclerView与Adapter绑定
XXXActivity{
    ...
    ...
    ...
myAdapter = new MyAdapter();
		roomBinding.rv.setLayoutManager(new LinearLayoutManager(this));
		roomBinding.rv.setAdapter(myAdapter);

		pagedListLiveData = new LivePagedListBuilder<>(roomViewModel.getAllStudent(), 2).build();
		pagedListLiveData.observe(this, new Observer<PagedList<Student>>() {
			@Override
			public void onChanged(PagedList<Student> students) {
				Log.i(TAG, "livedata onChanged: ");
				//提交数据,更新界面
				myAdapter.submitList(students);
				students.addWeakCallback(null, new PagedList.Callback() {
					@Override
					public void onChanged(int position, int count) {
						Log.i(TAG, "onChanged: position :  "+position+" count : "+count);
					}

					@Override
					public void onInserted(int position, int count) {

					}

					@Override
					public void onRemoved(int position, int count) {

					}
				});

			}
		});
  • XML
<?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <data>

        <variable
            name="data"
            type="com.demo.myjetpack.room_paging.RoomViewModel" />

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".room_paging.RoomActivity">

        <Button
            android:id="@+id/insert"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="56dp"
            android:onClick="@{()->data.insert()}"
            android:text="增"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/delete"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.974" />

        <Button
            android:id="@+id/delete"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{()->data.delete()}"
            android:text="删"
            app:layout_constraintEnd_toStartOf="@+id/query"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/insert"
            app:layout_constraintTop_toTopOf="@+id/insert" />

        <Button
            android:id="@+id/query"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{()->data.queryAll()}"
            android:text="查"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/delete"
            app:layout_constraintTop_toTopOf="@+id/delete" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toTopOf="@+id/delete"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值