架构图如上所示:Dao层操作数据库,dataBase 实例 需要基础 RoomDataBase 执行一下 数据库的一下操作,viewModel 层 提供dataBase

使用viewmodel层提供的database 去修改操作视图,Adapter 加载结合:AsyncListDiffer

开发步骤:

1.按照Google developer开发文档将Room 接入到项目中:https://developer.android.com/training/data-storage/room

主要组件

Room 包含三个主要组件:

数据库类,用于保存数据库并作为应用持久性数据底层连接的主要访问点。数据实体,用于表示应用的数据库中的表。数据访问对象 (DAO),提供您的应用可用于查询、更新、插入和删除数据库中的数据的方法。

数据库类为应用提供与该数据库关联的 DAO 的实例。反过来,应用可以使用 DAO 从数据库中检索数据,作为关联的数据实体对象的实例。此外,应用还可以使用定义的数据实体更新相应表中的行,或者创建新行供插入。

 

plugins {

id 'com.android.application'

id 'org.jetbrains.kotlin.android'

id 'kotlin-kapt'

}

implementation("androidx.room:room-runtime:2.4.3")

annotationProcessor("androidx.room:room-compiler:2.4.3")

kapt("androidx.room:room-compiler:2.4.3")

2.定义数据实体

@Entity

data class User(

@PrimaryKey

var uid: Int,

@ColumnInfo(name = "first_name")

var firstName: String?,

@ColumnInfo(name = "last_name")

var lastName: String?

) {

override fun equals(any: Any?): Boolean {

if (any == null) {

return false

}

val other: User = any as User

return ((uid == other.uid && (firstName == other.firstName) && (lastName == other.lastName)))

}

}

3.数据访问对象Dao:

@Dao

interface UserDao {

@Query("SELECT * FROM user")

fun getAll(): LiveData>?

@Query("SELECT * FROM user")

fun getAll2(): MutableList?

@Query("SELECT * FROM user WHERE uid IN (:userIds)")

fun loadAllByIds(userIds: IntArray): List

@Query("SELECT * FROM user WHERE first_name LIKE :first AND " + "last_name LIKE :last LIMIT 1")

fun findByName(first: String, last: String): User

@Insert(onConflict = OnConflictStrategy.REPLACE)

fun insertOneUser(users: User)

@Insert(onConflict = OnConflictStrategy.REPLACE)

fun insertUserList(list: List)

@Delete

fun delete(user: User)

@Query("SELECT * FROM user ORDER BY last_name ASC")

fun usersByLastName(): LiveData>?

}

注意数据访问对象Dao在插入的时候注意添加下:onConflict = OnConflictStrategy.REPLACE 意思是插入或者更新:insert or update

4.定义数据库:

 AppDatabase 定义数据库配置,并作为应用对持久性数据的主要访问点。数据库类必须满足以下条件:

该类必须带有 @Database 注解,该注解包含列出所有与数据库关联的数据实体的 entities 数组。该类必须是一个抽象类,用于扩展 RoomDatabase。对于与数据库关联的每个 DAO 类,数据库类必须定义一个具有零参数的抽象方法,并返回 DAO 类的实例。

@Database(entities = [User::class], version = 1, exportSchema = false)

abstract class AppDatabase : RoomDatabase() {

abstract fun userDao(): UserDao

companion object {

@Volatile

private var INSTANCE: AppDatabase? = null

fun getInstance(): AppDatabase {

synchronized(this) {

var instance = INSTANCE

if (instance == null) {

instance = Room.databaseBuilder(MyApplication.instance(), AppDatabase::class.java, "my-database-name")

.allowMainThreadQueries()

.build()

INSTANCE = instance

}

return instance

}

}

}

}

这里定义了一个AppDatabase单例,可以在全局中时候 AppDatabase实例

5.定义:ViewModel

class MyViewModel : ViewModel() {

fun getUsersList(): LiveData>? {

return AppDatabase.getInstance().userDao().getAll()

}

}

6.Activity中添加 viewModel的:observe:

viewModel.getUsersList()?.observe(this) {

//获取到db 的数据后,开始显示到View上

}

7.创建Adapter ,这里的Adapter 结合了:AsyncListDiffer:https://developer.android.com/reference/androidx/recyclerview/widget/AsyncListDiffer

public class UserAdapter extends RecyclerView.Adapter {

private final AsyncListDiffer mDiffer = new AsyncListDiffer(this, DIFF_CALLBACK);

@Override

public int getItemCount() {

int size = mDiffer.getCurrentList().size();

return size;

}

public void submitList(List list) {

mDiffer.submitList(list);

}

@NonNull

@Override

public UserViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {

return new UserViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_user_adapter, viewGroup, false));

}

@Override

public void onBindViewHolder(UserViewHolder holder, int position) {

User user = mDiffer.getCurrentList().get(position);

holder.bindView(user, position);

}

public class UserViewHolder extends RecyclerView.ViewHolder {

TextView mIdView;

TextView mFirstNameView;

TextView mLastNameView;

public UserViewHolder(@NonNull View itemView) {

super(itemView);

mIdView = itemView.findViewById(R.id.tv_id);

mFirstNameView = itemView.findViewById(R.id.tv_first_name);

mLastNameView = itemView.findViewById(R.id.tv_last_name);

}

public void bindView(User user, int position) {

mIdView.setText("Id:" + user.getUid());

mFirstNameView.setText(user.getFirstName());

mLastNameView.setText(user.getLastName());

}

}

public static final DiffUtil.ItemCallback DIFF_CALLBACK = new DiffUtil.ItemCallback() {

@Override

public boolean areItemsTheSame(

@NonNull User oldUser, @NonNull User newUser) {

// User properties may have changed if reloaded from the DB, but ID is fixed

return oldUser.getUid() == newUser.getUid();

}

@Override

public boolean areContentsTheSame(@NonNull User oldUser, @NonNull User newUser) {

// NOTE: if you use equals, your object must properly override Object#equals()

// Incorrectly returning false here will result in too many animations.

return oldUser.equals(newUser);

}

};

}

8.接下来就要实现数据的增删改查,同步显示在View上了:

插入数据:insert 

mBinding.btnAddView.setOnClickListener {

mCoroutineScope.launch {

val localUserList = AppDatabase.getInstance().userDao().getAll2()

val count = localUserList?.size ?: 0

val targetCount = count + 1

val user = User(targetCount, "FirstName:" + targetCount, "LastName:" + targetCount)

AppDatabase.getInstance().userDao().insertOneUser(user)

}

}

更新数据:update

mBinding.btnEditView.setOnClickListener {

mCoroutineScope.launch {

val localUserList = AppDatabase.getInstance().userDao().getAll2()

if (localUserList?.isNullOrEmpty() == true) {

return@launch

}

localUserList?.forEach {

it.firstName = it.firstName + "A"

it.lastName = it.lastName + "B"

}

localUserList?.let {

AppDatabase.getInstance().userDao().insertUserList(it)

}

}

}

删除数据:delete:

mBinding.btnDeleteView.setOnClickListener {

mCoroutineScope.launch {

val localUserList = AppDatabase.getInstance().userDao().getAll2()

localUserList?.let {

val user = it?.get(it.size - 1)

if (user != null) {

AppDatabase.getInstance().userDao().delete(user)

}

}

}

}

到目前为止就已经实现了:数据库的增删改查,同步显示到View 上:这样Room,ViewModel, AsyncListDiffer 结合在了一起

Demo地址:GitHub - JasonZhangHG/DiffUtilDemo: Room DB + ViewModel + AsyncListDiffer

推荐阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: