簡體   English   中英

Android - ViewModel、LiveData、Room 和 Retrofit 以及協程放在 kotlin 中

[英]Android - ViewModel, LiveData, Room and Retrofit and coroutines put together in kotlin

我正在學習 Android,我堅持讓所有這些組件協同工作。 我說的是 ViewModel、LiveData、Room、Retrofit 和協程。

所以,我想要實現的是:

當應用程序啟動時,我想檢查用戶是否登錄。 如果沒有登錄,我什么都不做,如果他登錄了,我在主要活動中記錄他的名字。 用戶可以通過另一個 api 調用進行身份驗證。 然后,當用戶更新時,主要活動應將更改反映給用戶。 我在此處部分關注了谷歌代碼實驗室https://developer.android.com/jetpack/guide ,但它不完整,我迷失了其中。

以下是代碼塊:

UserDao.kt

使用 Room DAO 進行數據庫查詢

@Dao
interface UserDao {

    @Query("SELECT * FROM user WHERE id = :userId")
    fun get(userId: Long): LiveData<UserEntity?>

    @Insert(onConflict = REPLACE)
    suspend fun insert(userEntity: UserEntity)

    @Query("SELECT COUNT(*) FROM user WHERE last_update >= :timeout")
    suspend fun hasUser(timeout: Long): Boolean
}

用戶服務.kt

這是一個簡單的 api 調用,使用 Retrofit

interface UserService {

    @GET("users/current-user")
    suspend fun getUser(): Response<User>
}

用戶庫.kt

主要活動應調用 get on load 並刷新用戶(調用 api 並檢索用戶 ID),將用戶 ID 保存在 savedStateHandler 中,然后從剛剛保存的數據庫中檢索用戶。 但是在第一次啟動時,savedStateHandler 是空的。 當我從 api 獲取用戶時,我將其存儲在數據庫中,但是傳遞給userDao.get(userId)userId變量仍然是 null,因此沒有從數據庫加載任何內容。 我應該在何時何地保存 savedStateHandler 中的用戶 ID? 我在存儲庫中沒有引用它。 此外,當應用程序啟動時,不會觸發調用。 我怎樣才能從活動中解雇它? 不確定在可變實時數據變量中的何處設置用戶以觸發活動中的觀察者。

suspend fun insert(userEntity: UserEntity) {
    userDao.insert(userEntity)
}

suspend fun get(userId: Long): LiveData<UserEntity?> {
    refreshUser()
    return userDao.get(userId)
}

private suspend fun refreshUser() = withContext(Dispatchers.IO) {
    launch {
        // Check if user data was fetched recently.
        val userExists = userDao.hasUser(FRESH_TIMEOUT)

        if (!userExists) {
            // Refreshes the data.
            val response = userService.getUser()
            try {
                if (response.isSuccessful) {
                    Log.i("user", "Success ${response.code()} - ${response.message()}")
                    // Updates the database. The LiveData object automatically
                    // refreshes, so we don't need to do anything else here.
                    val body: User? = response.body()
                    val user = UserEntity(
                        body!!.id,
                        body.email,
                        body.name.firstName,
                        body.name.lastName,
                        body.telephone,
                        body.dateOfBirth,
                        System.currentTimeMillis() / 1000
                    )
                    userDao.insert(user)
                } else {
                    Log.w(
                        "user",
                        "Not successful ${response.code()} - ${response.message()}"
                    )
                }
            } catch (e: HttpException) {
                Log.e("user", "Exception ${response.code()} - ${response.message()}")
            }
        }
    }
}

UserViewModel.kt

class UserViewModel @ViewModelInject constructor(
      private val repository: UserRepository,
      @Assisted private val savedStateHandle: SavedStateHandle) : ViewModel() {

    fun insert(userEntity: UserEntity) = viewModelScope.launch {
        repository.insert(userEntity)
    }

    private val userId: Long? = savedStateHandle["uid"]

    val user: LiveData<UserEntity?>
        get() = liveData { repository.get(userId) }
}

主活動.kt

    viewModel.user.observe(this) { user ->
        Log.i("USER IS LOGGED", user.toString())
        Toast.makeText(this, "HELLO ${user?.email}!!", Toast.LENGTH_SHORT).show()
    }
private val userId: Long? = savedStateHandle["uid"] val user: LiveData<UserEntity?> get() = liveData { repository.get(userId) }

應該

private val userId: MutableLiveData<Long> = savedStateHandle.getLiveData("uid")

val user: LiveData<UserEntity?>
    get() = userId.switchMap { userId -> liveData { repository.get(userId) } }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM