Android Jetpack:Room的简单搭建

第一部分:准备

① Data class

  1. @Entity(tableName = "friends") 建立一张表,表名叫friends
  2. 设置主键@PrimaryKey @ColumnInfo(name = "id"),将注释后面的属性设置成一个Column,并且指定这个属性是主键
  3. @ColumnInfo该注释后面的属性将成为表中的一个Column属性
  4. 如果类中有属性不想存入数据库,也就是这个friends表的,就用注释@Ignore var XXXX
@Entity(tableName = "friends")
data class Friend (
    @PrimaryKey @ColumnInfo(name = "id") val friendId: String
){
    
    
    @ColumnInfo(name = "avator_url") var friendAvatorUrl = ""

    @ColumnInfo(name = "name") var friendName = ""
}

② Dao

  1. Dao是一个接口, 实现Query
  2. 使用注释@Dao
  3. @Insert(onConflict = OnConflictStrategy.REPLACE)冲突策略
@Dao
interface FriendDao {
    
    
    @Query("SELECT * FROM friends ORDER BY name")
    fun getFriends():LiveData<List<Friend>>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertFriend(friend: Friend): Long
	
	@Update
	fun update(friend: Friend)

    @Delete
    suspend fun deletedFriend(friend: Friend)
}

④ Repository

  1. ViewModel通过Repository获取数据,ViewModel将会用到的方法:addFriend(friend: Friend)deleteFriend(friend: Friend)
  2. Repository通过Dao获取数据库的数据(必须要有Dao)
  3. Repository使用单例模式
class FriendRepository private constructor(
    private val friendDao: FriendDao
){
    
    
	//向表中添加一个friend
    suspend fun addFriend(friend: Friend) = friendDao.insertFriend(friend)
	//向表中删除一个friend
    suspend fun deleteFriend(friend: Friend) = friendDao.deletedFriend(friend)
	//获取表中的所有friend并返回 LiveData<List<Friend>>
    fun getFriends() = friendDao.getFriends()

    companion object{
    
    
        @Volatile private var instance: FriendRepository? = null

        fun getInstance(friendDao: FriendDao) =
            instance ?: synchronized(this){
    
    
                instance ?: FriendRepository(friendDao).also {
    
     instance = it }
        }
    }
}

④ RoomDatabase

  1. 使用注释表明构成数据库的表等…这里只有一个Friend,还有的话往里添加
@Database(entities = arrayOf(Friend::class), version = 1, exportSchema = false)
  1. Room需要有获取Dao的抽象方法, 创建Repository的时候才能从RoomDatabase里面通过friendDao()获取
	//获取 Dao
    abstract fun friendDao(): FriendDao
  1. 创建数据库需要传入Context,并且使用Room.databaseBuilder(context: Context, XxxRoomDatabase::class.java, "Xxx_database"),后面两个参数分别是你的RoomDatabase的类名,还有数据库的名字
  2. 想让数据库一开始就存有数据的话就覆写RoomDatabaseCallback,在协程中向数据库里放数据,放完后build()一下
  3. Debug的时候注意Callback里面的onCreate()onOpen()方法,onCreate()就只会在创建的时候回调一次,直到你删库跑路又回来重新创建。onOpen(),就是每次打开app都会回调
@Database(entities = arrayOf(Agenda::class, Friend::class, Plan::class),
            version = 1,
            exportSchema = false)
abstract class AppRoomDatabase : RoomDatabase() {
    
    

    abstract fun friendDao(): FriendDao
    
    companion object{
    
    
        @Volatile
        private var INSTANCE: AppRoomDatabase? = null

        fun getInstance(
            context: Context): AppRoomDatabase{
    
    
            return INSTANCE ?: synchronized(this){
    
    
                INSTANCE ?: buildDatabase(context).also {
    
     INSTANCE = it }
            }
        }
        
    private fun buildDatabase(context: Context):AppRoomDatabase{
    
    
        return Room.databaseBuilder(context, AppRoomDatabase::class.java, "app_database")
        //让数据库一开始就有数据,覆写Callback()里的onCreate()或者onOpen()
            .addCallback(object : RoomDatabase.Callback(){
    
    
                override fun onCreate(db: SupportSQLiteDatabase) {
    
    
                    super.onCreate(db)
                   //这里要操作数据库,不能在主线程中操作,我这里用的 Worker
                    /*val request = OneTimeWorkRequestBuilder<PrepopulateWorker>().build()
                    WorkManager.getInstance(context).enqueue(request)
                    */
                }
				override fun onOpen(db: SupportSQLiteDatabase) {
    
    
                    super.onOpen(db)
                   //这里要操作数据库,不能在主线程中操作,我这里用的 Worker
                    /*val request = OneTimeWorkRequestBuilder<PrepopulateWorker>().build()
                    WorkManager.getInstance(context).enqueue(request)
                    */
                }
                
            }).build()
        }
    }
}

⑥ ViewModel

  1. 需要有Repository的引用,因为要获取数据
  2. 主要就存数据嘛,这里就只有一个List<Friend>
  3. 有通过Repository访问数据库的方法,比如这里是insert(friend: Friend), 同样的不能在主线程访问,ViewModel里面当然在viewModelScope里面访问
class FriendListViewModel(
    private val friendListRepository: FriendRepository
): ViewModel(){
    
    

    var friends: LiveData<List<Friend>> = friendListRepository.getFriends()

    fun insert(friend: Friend) = viewModelScope.launch {
    
    
        friendListRepository.addFriend(friend)
    }
}

⑦ ViewModelFactory

  1. 通过他来创建ViewModel
  2. 具体我也不太懂了这个
class FriendListViewModelFactory(
    private val repository: FriendRepository
): ViewModelProvider.NewInstanceFactory() {
    
    
    @Suppress
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
    
    
        return FriendListViewModel(repository) as T
    }
}

小结

ViewModel -> Repository -> Dao -> RoomDatabase

第二部分:使用

需要在Activity或者Fragment中创建ViewModel,在这里,创建ViewModel我选择通过ViewModelFactory。思路 是这样的: 创建ViewModelViewModel需要获取数据需要通过RepositoryViewModel中需要有Repository的引用,而Repository要获取数据库数据需要通过Dao接口,Repository又需要Dao的引用,要获取Dao,那么需要有RoomDatabase来提供DaoRepository。所以,逆向就能构建出可以和数据库联系起来的ViewModel

① 获取Repository

  1. 获取AppRoomDatabase的实例,它的FriendDao()方法返回FriendDao,传入FriendRepository(friendDao : FriendDao),获得一个FriendRepository实例
private  fun getFriendRepository(context: Context) : FriendRepository{
    
    
        return FriendRepository.getInstance(
            AppRoomDatabase.getInstance(context).friendDao()
        )
    }

② 获取ViewModelFactory

  1. 将上一步获得的Repository传入ViewModelFactory()
fun provideFriendListViewModelFactory(context: Context): FriendListViewModelFactory{
    
    
		//调用上面的那个方法
        var repository = getFriendRepository(context)
        return FriendListViewModelFactory(repository)
    }

将上面两个方法写在了实用类里面,参照的SunFlower

object InjectorUtils {
    
    
    private  fun getFriendRepository(context: Context) : FriendRepository{
    
    
        return FriendRepository.getInstance(
            AppRoomDatabase.getInstance(context).friendDao()
        )
    }

    fun provideFriendListViewModelFactory(context: Context): FriendListViewModelFactory{
    
    
        var repository = getFriendRepository(context)
        return FriendListViewModelFactory(repository)
    }
}

③ 在Activity或者Fragment中创建ViewModel

直接调用InjectorUtilsprovideFriendListViewModelFactory(context: Context),获取了Factory之后直接create就可以了

class FriendFragment : Fragment() {
    
    

    private lateinit var friendListViewModel: FriendListViewModel

   	override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
    
    
    
    	//重点在这里,其他不重要
        friendListViewModel = InjectorUtils
            .provideFriendListViewModelFactory(requireContext())
            .create(FriendListViewModel::class.java)
            
        return FragmentFriendBinding.inflate(inflater, container,
            false).root
    }
}

猜你喜欢

转载自blog.csdn.net/qq_43709922/article/details/104139041