gpt4 book ai didi

android - 当从另一个 Fragment/ViewModel 执行插入时,从 Room 返回的 Kotlin Flow 不会更新

转载 作者:行者123 更新时间:2023-12-03 22:29:02 30 4
gpt4 key购买 nike

我有一个 Room 数据库,它返回一个对象流。当我将新项目插入数据库时​​,Flow 的收集功能仅在从相同的 Fragment/ViewModel 执行插入时触发。
我录制了一个快速视频来展示这个问题:https://www.youtube.com/watch?v=7HJkJ7M1WLg
这是我对相关文件的代码设置:
成就道.kt:

@Dao
interface AchievementDao {

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(achievement: Achievement)

@Query("SELECT * FROM achievement")
fun getAllAchievements(): Flow<List<Achievement>>
}
AppDB.kt:
@Database(entities = [Achievement::class], version = 1, exportSchema = false)
abstract class AppDB : RoomDatabase() {

abstract fun achievementDao(): AchievementDao
}
成就库.kt :
class AchievementRepository @Inject constructor(appDB: AppDB) {

private val achievementDao = appDB.achievementDao()

suspend fun insert(achievement: Achievement) {
withContext(Dispatchers.IO) {
achievementDao.insert(achievement)
}
}

fun getAllAchievements() = achievementDao.getAllAchievements()
}
HomeFragment.kt:
@AndroidEntryPoint
class HomeFragment : Fragment() {

private val viewModel: HomeViewModel by viewModels()

private lateinit var homeText: TextView

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_home, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
bindViews()
subscribeObservers()
}

private fun bindViews() {
homeText = requireView().findViewById(R.id.txt_home)
requireView().findViewById<ExtendedFloatingActionButton>(R.id.fab_add_achievement).setOnClickListener {
AddAchievementBottomSheet().show(parentFragmentManager, "AddAchievementDialog")
}
requireView().findViewById<ExtendedFloatingActionButton>(R.id.fab_add_achievement_same_fragment).setOnClickListener {
viewModel.add()
}
}

private fun subscribeObservers() {
viewModel.count.observe(viewLifecycleOwner, { count ->
if(count != null) {
homeText.text = count.toString()
} else {
homeText.text = resources.getString(R.string.app_name)
}
})
}
}
HomeViewModel.kt:
class HomeViewModel @ViewModelInject constructor(private val achievementRepository: AchievementRepository) :
ViewModel() {

private val _count = MutableLiveData<Int>(null)
val count = _count as LiveData<Int>

init {
viewModelScope.launch {
achievementRepository.getAllAchievements()
.collect { values ->
// FIXME this is only called when inserting from the same Fragment
_count.postValue(values.count())
}
}
}

fun add() {
viewModelScope.launch {
achievementRepository.insert(Achievement(0, 0, "Test"))
}
}
}
AddAchievementBottomSheet.kt:
@AndroidEntryPoint
class AddAchievementBottomSheet : BottomSheetDialogFragment() {

private val viewModel: AddAchievementViewModel by viewModels()
private lateinit var addButton: MaterialButton

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.dialog_add_achievement, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
addButton = requireView().findViewById(R.id.btn_add_achievement)
addButton.setOnClickListener {
viewModel.add(::close)
}
}

private fun close() {
dismiss()
}
}
AddAchievementBottomSheetViewModel.kt:
class AddAchievementViewModel @ViewModelInject constructor(private val achievementRepository: AchievementRepository) :
ViewModel() {

fun add(closeCallback: () -> Any) {
viewModelScope.launch {
achievementRepository.insert(Achievement(0, 0, "Test"))
closeCallback()
}
}
}
build.gradle(应用程序):
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
}

android {
compileSdkVersion 30

defaultConfig {
applicationId "com.marcdonald.achievementtracker"
minSdkVersion 23
targetSdkVersion 30
versionCode 1
versionName "1.0.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}

dependencies {
// Kotlin
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.0'
implementation 'androidx.core:core-ktx:1.3.2'

// Android
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation "androidx.activity:activity-ktx:1.1.0"
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'

// Navigation
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.1'

// Testing
testImplementation 'junit:junit:4.13.1'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

// Dagger Hilt
implementation 'com.google.dagger:hilt-android:2.29.1-alpha'
implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha02'
kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha02'
kapt 'com.google.dagger:hilt-android-compiler:2.29.1-alpha'

// Timber for logging
implementation 'com.jakewharton.timber:timber:4.7.1'

// Room
implementation 'androidx.room:room-runtime:2.2.5'
implementation 'androidx.room:room-ktx:2.2.5'
kapt 'androidx.room:room-compiler:2.2.5'
androidTestImplementation 'androidx.room:room-testing:2.2.5'
}
build.gradle(项目):
buildscript {
ext.kotlin_version = "1.4.10"
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.2.0-alpha16'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0'
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.29.1-alpha'
}
}

allprojects {
repositories {
google()
jcenter()
maven { url 'https://jitpack.io' }
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}
我不确定是否应该归咎于我对 Kotlin Flow 的理解,或者我的设置是否在某些方面不正确,但我希望能在这个问题上提供一些帮助。

最佳答案

确保使用相同的 RoomDatabase 实例。在您提供 AppDB 的地方添加一个 @Singleton 可能会成功。

关于android - 当从另一个 Fragment/ViewModel 执行插入时,从 Room 返回的 Kotlin Flow 不会更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64866053/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com