kotlin结合Room在实际项目中的运用
架构还是MVVM,DataBinding+ViewModel+LiveData的组合
效果:
1.首先添加Room依赖
添加kapt插件:
plugins {id 'com.android.application'id 'kotlin-android'id 'kotlin-kapt'
}
def room_version = "2.3.0"implementation "androidx.room:room-runtime:$room_version"implementation "androidx.room:room-ktx:$room_version"kapt "androidx.room:room-compiler:$room_version"
2.创建数据库相关类
entity:
package com.aruba.flowapplyapplication.database.entityimport androidx.room.Entity
import androidx.room.PrimaryKey/*** Created by aruba on 2021/9/20.*/
@Entity
data class UserInfo(@PrimaryKey val id: Int,var userName: String,var age: Int
)
Dao,之前我们需要使用异步任务操作Dao,kotlin则可以使用挂起函数,标识使用协程操作:
package com.aruba.flowapplyapplication.database.daoimport androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.aruba.flowapplyapplication.database.entity.UserInfo
import kotlinx.coroutines.flow.Flow/*** Created by aruba on 2021/9/20.*/
@Dao
interface UserInfoDao {//id重复的替换@Insert(onConflict = OnConflictStrategy.REPLACE)suspend fun insert(userInfo: UserInfo)//返回Flow,由于Flow需要使用collect,该函数为挂起函数,所以不需要加suspend了@Query("SELECT * FROM userinfo")fun getUserInfoList(): Flow<List<UserInfo>>
}
Database:
package com.aruba.flowapplyapplication.databaseimport android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import com.aruba.flowapplyapplication.database.dao.UserInfoDao
import com.aruba.flowapplyapplication.database.entity.UserInfoprivate const val DB_NAME: String = "my.db"/*** Created by aruba on 2021/9/20.*/
@Database(entities = [UserInfo::class], version = 1, exportSchema = true)
abstract class MyDatabase : RoomDatabase() {abstract fun getUserDao(): UserInfoDaocompanion object {private var instance: MyDatabase? = nullfun getInstance(): MyDatabase {checkNotNull(instance) { "init has not been called" }return instance as MyDatabase}fun init(context: Context) {synchronized(this) {instance ?: Room.databaseBuilder(context,MyDatabase::class.java, DB_NAME).build().let { instance = it }}}}
}
3.定义ViewModel
使用LiveData对三个EditText进行双向绑定
package com.aruba.flowapplyapplication.viewmodelimport android.view.View
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.aruba.flowapplyapplication.database.MyDatabase
import com.aruba.flowapplyapplication.database.dao.UserInfoDao
import com.aruba.flowapplyapplication.database.entity.UserInfo
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch
import androidx.databinding.ObservableField/*** Created by aruba on 2021/9/20.*/
class UserInfoViewModel : ViewModel() {val id = MutableLiveData<String>()val name = MutableLiveData<String>()val age = MutableLiveData<String>()private val userInfoDao: UserInfoDao by lazy {MyDatabase.getInstance().getUserDao()}fun insert(v: View) {if (id.value == null || name.value == null || age.value == null) {return}val userInfo = UserInfo(id.value!!.toInt(), name.value!!, age.value!!.toInt())viewModelScope.launch(Dispatchers.IO) {userInfoDao.insert(userInfo)}}fun getUserInfo(): Flow<List<UserInfo>> {return userInfoDao.getUserInfoList().flowOn(Dispatchers.IO)}}
4.定义RecyclerViewAdapter
package com.aruba.flowapplyapplication.adapterimport android.view.LayoutInflater
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.RecyclerView
import com.aruba.flowapplyapplication.R
import com.aruba.flowapplyapplication.database.entity.UserInfo
import com.aruba.flowapplyapplication.databinding.ItemUserinfoBinding/*** Created by aruba on 2021/9/20.*/
class UserInfoAdapter() : RecyclerView.Adapter<UserInfoAdapter.MyViewHolder>() {private var data = ArrayList<UserInfo>()class MyViewHolder(val binding: ItemUserinfoBinding) : RecyclerView.ViewHolder(binding.root)fun setData(data: List<UserInfo>) {this.data.clear()this.data.addAll(data)notifyDataSetChanged()}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {val binding: ItemUserinfoBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.context),R.layout.item_userinfo,parent, false)return MyViewHolder(binding)}override fun onBindViewHolder(holder: MyViewHolder, position: Int) {holder.binding.userInfo = data[position]}override fun getItemCount(): Int {return data.size}
}
5.Fragment中实例化ViewModel,以及进行数据绑定等操作
package com.aruba.flowapplyapplicationimport android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.aruba.flowapplyapplication.adapter.UserInfoAdapter
import com.aruba.flowapplyapplication.database.MyDatabase
import com.aruba.flowapplyapplication.databinding.FragmentRoomBinding
import com.aruba.flowapplyapplication.viewmodel.UserInfoViewModel
import kotlinx.coroutines.flow.collectclass RoomFragment : Fragment() {override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {//初始化数据库MyDatabase.init(requireContext())val inflate = DataBindingUtil.inflate<FragmentRoomBinding>(layoutInflater,R.layout.fragment_room,container,false)//实例化ViewModelval userInfoViewModel = ViewModelProvider(this,ViewModelProvider.AndroidViewModelFactory(requireActivity().application)).get(UserInfoViewModel::class.java)inflate.userInfoViewModel = userInfoViewModelinflate.recyclerview.adapter = UserInfoAdapter()inflate.recyclerview.layoutManager = LinearLayoutManager(context)inflate.lifecycleOwner = viewLifecycleOwner//开启协程对数据库的表进行监听lifecycleScope.launchWhenCreated {//每当UserInfo表发生变化,Flow都会把UserInfo列表发射出去,那么我们//在collect中就可以获取到userInfoViewModel.getUserInfo().collect {(inflate.recyclerview.adapter as UserInfoAdapter).setData(it)}}return inflate.root}}