kotlin結(jié)合Room在實(shí)際項(xiàng)目中的運(yùn)用
架構(gòu)還是MVVM,DataBinding+ViewModel+LiveData的組合
效果:
1.首先添加Room依賴(lài)
添加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.創(chuàng)建數(shù)據(jù)庫(kù)相關(guān)類(lèi)
entity:
package com.aruba.flowapplyapplication.database.entity
import 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炫乓,之前我們需要使用異步任務(wù)操作Dao刚夺,kotlin則可以使用掛起函數(shù),標(biāo)識(shí)使用協(xié)程操作:
package com.aruba.flowapplyapplication.database.dao
import 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重復(fù)的替換
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(userInfo: UserInfo)
//返回Flow末捣,由于Flow需要使用collect侠姑,該函數(shù)為掛起函數(shù),所以不需要加suspend了
@Query("SELECT * FROM userinfo")
fun getUserInfoList(): Flow<List<UserInfo>>
}
Database:
package com.aruba.flowapplyapplication.database
import 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.UserInfo
private 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(): UserInfoDao
companion object {
private var instance: MyDatabase? = null
fun 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對(duì)三個(gè)EditText進(jìn)行雙向綁定
package com.aruba.flowapplyapplication.viewmodel
import 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.adapter
import 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中實(shí)例化ViewModel箩做,以及進(jìn)行數(shù)據(jù)綁定等操作
package com.aruba.flowapplyapplication
import 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.collect
class RoomFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
//初始化數(shù)據(jù)庫(kù)
MyDatabase.init(requireContext())
val inflate = DataBindingUtil.inflate<FragmentRoomBinding>(
layoutInflater,
R.layout.fragment_room,
container,
false
)
//實(shí)例化ViewModel
val userInfoViewModel = ViewModelProvider(
this,
ViewModelProvider.AndroidViewModelFactory(requireActivity().application)
).get(UserInfoViewModel::class.java)
inflate.userInfoViewModel = userInfoViewModel
inflate.recyclerview.adapter = UserInfoAdapter()
inflate.recyclerview.layoutManager = LinearLayoutManager(context)
inflate.lifecycleOwner = viewLifecycleOwner
//開(kāi)啟協(xié)程對(duì)數(shù)據(jù)庫(kù)的表進(jìn)行監(jiān)聽(tīng)
lifecycleScope.launchWhenCreated {
//每當(dāng)UserInfo表發(fā)生變化莽红,F(xiàn)low都會(huì)把UserInfo列表發(fā)射出去,那么我們
//在collect中就可以獲取到
userInfoViewModel.getUserInfo().collect {
(inflate.recyclerview.adapter as UserInfoAdapter).setData(it)
}
}
return inflate.root
}
}