簡體   English   中英

Android [Kotlin] - 使用共享視圖模型將新項目插入到 MasterDetail-Flow 上的選定子列表中

[英]Android [Kotlin] - Inserting a new item into a selected Child-List on a MasterDetail-Flow using shared viewModel

我對 android 很陌生,我正在嘗試遵循推薦的應用程序架構。

該應用程序基本上由兩個使用房間數據庫的實體組成:培訓和練習。 它們具有多對多關系,按照 android 開發人員指南中的建議實現,並帶有一個額外的參考實體和一個 POJO:

@Entity(
    tableName = "training_exercise_ref",
    primaryKeys = ["trainingId", "exerciseId"])
data class TrainingExerciseCrossRef (
    var trainingId: Long,
    var exerciseId: Long
)

data class TrainingWithExercise (
    @Embedded val training: Training,

    @Nullable
    @Relation(
        parentColumn = "trainingId",
        entityColumn = "exerciseId",
        associateBy = Junction(TrainingExerciseCrossRef::class)
    )
    val exercises: List<Exercise>?

默認情況下,培訓不需要練習。

現在我想在第一個主視圖(recyclerview)中列出所有培訓,如果點擊培訓,我想在單獨的 Detail/Exercise-Recyclerview 中顯示相應的練習。 我通過兩個不同的片段完成了此操作,並且按照開發人員指南中的建議通過 ViewModel 共享數據:

class DashboardViewModel(application: Application) : AndroidViewModel(application) {

    private val trainingRepository: TrainingRepository

    val allTrainingWithExercises: LiveData<List<TrainingWithExercise>>
    val selectedTraining = MutableLiveData<TrainingWithExercise>()

    init {
        val trainingDao = TrainingRoomDatabase.getDatabase(application, viewModelScope).trainingDao()
        trainingRepository = TrainingRepository(trainingDao)

        allTrainingWithExercises = trainingRepository.allTrainingWithExerciseEntries
    }

    fun selectTraining(trainingWithExercise: TrainingWithExercise) {
        selectedTraining.value = trainingWithExercise
    }

    fun insertExerciseToTraining(trainingId: Long, exercise: Exercise) = viewModelScope.launch {
        val newExerciseId: Long = exerciseRepository.insert(exercise)
        trainingRepository.insertExerciseOfTraining(trainingId, newExerciseId)
    }

所以,當我點擊一個訓練時,我將選擇保存在 viewModel 中,試圖在片段中設置一個觀察者

dashboardViewModel.selectedTraining.observe(viewLifecycleOwner, Observer { exercises ->
            exercises?.let { adapter.setTraining(it) }
        })

並在詳細信息片段中顯示所選訓練和練習列表。 在細節片段中,我還希望能夠插入新的練習。

我的問題來了:
當我添加新練習時,我使用上面的“insertExerciseToTraining”函數,然后在存儲庫中插入練習和新的 trainingExerciseCrossRef。 但是在細節片段中,練習列表沒有更新。 只有當我回到訓練概覽並再次選擇訓練時。 這甚至是使用共享視圖模型的正確方法嗎?
作為快速修復,我只在 viewModel 中共享訓練 id 並再次從數據庫查詢 trainingWithExercise,觀察並顯示它。 然后,在插入新練習時,列表會正確更新。 但這似乎不是實現我的目標的最佳方式或使用 viewModels 的最佳方式。
有什么建議?

我想出了一個解決方法,但我不確定這是否是最佳實踐。 也許有更清潔的方法; 但它的工作。

所以基本上,如上所述,我正在選擇訓練,並將選擇的 id 保存到 viewModel 中。 然后我啟動詳細信息片段,並觀察完整的 allTrainingWithExercise-List/LiveData,然后使用先前保存的 ID 過濾該列表以進行訓練,並將其設置在視圖中。
因此,當我通過插入新練習來更新訓練的練習列表時,觀察到的 allTrainingsWithExercise 會得到更新,並且我正在通過保存的訓練 ID“重新選擇”訓練。

dashboardViewModel.allTrainingWithExercises.observe(viewLifecycleOwner, Observer { trainings ->
            trainings?.let { adapter.setTraining(it.filter { it.training.trainingId == dashboardViewModel.selectedTrainingId }[0]) }
        })

暫無
暫無

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

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