Fragment 从不接收来自 Shared ViewModel 的 LiveData 更新
Fragment Never Receives LiveData updates from Shared ViewModel
我的应用程序使用 MVVM 架构。我有一个由 Activity 及其子片段之一共享的 ViewModel。 ViewModel 包含一个我想从 Activity 更新并在片段中观察的简单字符串。
我的问题很简单:在 LiveData 更新后,我的片段中从未达到观察回调。为了测试,我尝试观察 MainActivity
中的数据,但效果很好。此外,观察我在其他 ViewModel 中声明的片段中的 LiveData 变量也能正常工作。奇怪的是,只有这个 ViewModel 的 LiveData 似乎对我的片段造成了问题。
我正在声明 ViewModel 并通过 Koin 将其注入我的 Activity 和 Fragment。我做错了什么,永远不会在我的片段中获取此 ViewModel 数据的更新?
ViewModel
class RFIDTagViewModel: ViewModel() {
private val _rfidTagUUID = MutableLiveData<String>()
val rfidTagUUID: LiveData<String> = _rfidTagUUID
fun tagUUIDScanned(tagUUID: String) {
_rfidTagUUID.postValue(tagUUID)
}
}
Activity
class MainActivity : AppCompatActivity(), Readers.RFIDReaderEventHandler,
RFIDSledEventHandler.TagScanInterface {
private val rfidViewModel: RFIDTagViewModel by viewModel()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
rfidViewModel.rfidTagUUID.observe(this, {
Timber.d("I'm ALWAYS reached")
})
}
override fun onResume() {
rfidViewModel.tagUUIDScanned(uuid) //TODO: data passed in here, never makes it to Fragment observer, only observed by Activity successfully
}
}
片段
class PickingItemFragment : Fragment() {
private val rfidViewModel: RFIDTagViewModel by viewModel()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
rfidViewModel.rfidTagUUID.observe(viewLifecycleOwner, { tagUUID ->
Timber.d("I'm NEVER reached")
})
}}
Koin DI 配置
val appModule = module {
viewModel { RFIDTagViewModel() }
}
您需要使用相同的视图模型,也就是 sharedViewModel,您正在使用相同视图模型的两个不同实例。
修复它。
在 activity 和片段上:
private val rfidViewModel: RFIDTagViewModel by activityViewModels()
https://developer.android.com/topic/libraries/architecture/viewmodel?hl=pt-br
在您的片段中,我看到您正在使用 viewModels()
。 viewModels()
这里会附加到Fragment,而不是Activity。
如果您想在 Fragment 和 Activity 之间共享 ViewModel,则在 Fragment 中使用 activityViewModels()
。现在,在 Fragment 中,您的 shareViewModel 将附加到包含您的 Fragment 的 Activity。
编辑如下:
PickingItemFragment.kt
class PickingItemFragment : Fragment() {
private val rfidViewModel: RFIDTagViewModel by activityViewModels()
}
我的应用程序使用 MVVM 架构。我有一个由 Activity 及其子片段之一共享的 ViewModel。 ViewModel 包含一个我想从 Activity 更新并在片段中观察的简单字符串。
我的问题很简单:在 LiveData 更新后,我的片段中从未达到观察回调。为了测试,我尝试观察 MainActivity
中的数据,但效果很好。此外,观察我在其他 ViewModel 中声明的片段中的 LiveData 变量也能正常工作。奇怪的是,只有这个 ViewModel 的 LiveData 似乎对我的片段造成了问题。
我正在声明 ViewModel 并通过 Koin 将其注入我的 Activity 和 Fragment。我做错了什么,永远不会在我的片段中获取此 ViewModel 数据的更新?
ViewModel
class RFIDTagViewModel: ViewModel() {
private val _rfidTagUUID = MutableLiveData<String>()
val rfidTagUUID: LiveData<String> = _rfidTagUUID
fun tagUUIDScanned(tagUUID: String) {
_rfidTagUUID.postValue(tagUUID)
}
}
Activity
class MainActivity : AppCompatActivity(), Readers.RFIDReaderEventHandler,
RFIDSledEventHandler.TagScanInterface {
private val rfidViewModel: RFIDTagViewModel by viewModel()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
rfidViewModel.rfidTagUUID.observe(this, {
Timber.d("I'm ALWAYS reached")
})
}
override fun onResume() {
rfidViewModel.tagUUIDScanned(uuid) //TODO: data passed in here, never makes it to Fragment observer, only observed by Activity successfully
}
}
片段
class PickingItemFragment : Fragment() {
private val rfidViewModel: RFIDTagViewModel by viewModel()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
rfidViewModel.rfidTagUUID.observe(viewLifecycleOwner, { tagUUID ->
Timber.d("I'm NEVER reached")
})
}}
Koin DI 配置
val appModule = module {
viewModel { RFIDTagViewModel() }
}
您需要使用相同的视图模型,也就是 sharedViewModel,您正在使用相同视图模型的两个不同实例。
修复它。
在 activity 和片段上:
private val rfidViewModel: RFIDTagViewModel by activityViewModels()
https://developer.android.com/topic/libraries/architecture/viewmodel?hl=pt-br
在您的片段中,我看到您正在使用 viewModels()
。 viewModels()
这里会附加到Fragment,而不是Activity。
如果您想在 Fragment 和 Activity 之间共享 ViewModel,则在 Fragment 中使用 activityViewModels()
。现在,在 Fragment 中,您的 shareViewModel 将附加到包含您的 Fragment 的 Activity。
编辑如下:
PickingItemFragment.kt
class PickingItemFragment : Fragment() {
private val rfidViewModel: RFIDTagViewModel by activityViewModels()
}