如何解决Android:清除DialogFragment ViewModel 如何解决该问题?
我正在创建一个扩展BottomSheetDialogFragment
的对话框。在此对话框中,我有一个ViewModel来保存片段的状态(它内部有一些输入)。 ViewModel的某些属性是LiveData
。我注意到,在关闭对话框(调用dismiss()
或在对话框外部点击)并重新打开它时,LiveData
属性的值会保持不变。
因此,作为解决方案,我想重写onDismiss()
事件以手动清除ViewModel中的数据:
override fun onDismiss(dialog: DialogInterface) {
// Clear the viewmodel
viewModel.clear()
viewModelStore.clear()
super.onDismiss(dialog)
// Unsubscribe from observer
viewModel.getContact().removeObservers(viewLifecycleOwner)
}
viewModel.clear()
是我的ViewModel中的一个函数,用于将内部数据重置为默认值。
显然,这还是不够的,因为即使在解雇之前在ViewModel中重置了数据之后,在重新打开对话框时,ViewModel仍保留了它在调用clear()
由于不是LiveData
的属性会重置,因此我相信有一种重置LiveData
值的特定方法,但是我不知道该怎么做。谁能帮我吗?预先感谢!
解决方法
阿德里安(Adrian)向我提供了他的项目的样本。该答案基于调试示例项目的结果。
导致您遇到问题的问题实际上位于您的[{'time': '2020-08-21T00:00:00.000Z','click': 3},...]
类中。您可以在活动的MainActivity
方法中实例化AddReminderFragment
,并在按下FAB时显示此片段的实例。
一切似乎都不错,除了-您总是展示相同的onCreate
实例。这意味着,当您首次显示此片段时,您会获得全新的AddReminderFragment
,该文件是使用AddReminderViewModel
延迟加载的。
最初,我认为延迟加载by viewModels()
导致了此问题,因为它使用片段本身作为视图模型存储,并且它缓存创建的视图模型,以防您想重复使用以后再说。情况并非如此。
如何解决该问题?
切勿存储对活动和片段的引用,或尽其所能避免,如有任何注意,请多加注意。它可能会导致内存泄漏。
简述我做了什么:
- 从
by viewModels()
中删除了private lateinit var modal: AddReminderFragment
变量; - 从
MainActivity
中删除了ITimePipupCallback
; - 从
MainActivity
中删除了onAttach(context: Context)
; - 在
TimePopupFragment
中实现了fun setCallback(callback: ITimePipupCallback): TimePopupFragment
; - 在显示通过回调
TimePopupFragment
实例传递的TimePopupFragment
的{{1}}实例之前。好像是对AddReminderFragment
的按钮单击的回调; - 从
ITimePipupCallback
中删除了AlertDialog
和onTimePicked
方法,因为它们不再需要。
更新了onDayPicked
:
AddReminderFragment
对MainActivity
的更新:
class MainActivity : AppCompatActivity() {
companion object {
const val AddReminderModalTag = "add_reminder_modal"
}
private lateinit var binding: MainActivityBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = MainActivityBinding.inflate(layoutInflater)
binding.showModalHandler = this
setContentView(binding.root)
}
fun showAddReminderModal(view: View) {
AddReminderFragment.newInstance().show(supportFragmentManager,AddReminderModalTag)
}
}
对AddReminderFragment
的更新:
class AddReminderFragment : BottomSheetDialogFragment() {
...
override fun onCreateView(
inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?
): View? {
...
//Bind the add time button
binding.addTimeButton.setOnClickListener {
TimePopupFragment
.newInstance(viewModel.getReminderType().value!!)
.setCallback(object : ITimePipupCallback {
override fun onTimePicked(hour: Int,minute: Int) {
viewModel.addTimeToRemind(hour,minute)
}
override fun onDayPicked(day: Int) {
viewModel.addTimeToRemind(day)
}
})
.show(
parentFragmentManager,TIME_PICKER_TAG
)
}
...
return binding.root
}
...
}
您可以从TimePopupFragment
中安全删除class TimePopupFragment : DialogFragment() {
...
private lateinit var callback: ITimePipupCallback
// Removed `onAttach` method
fun setCallback(callback: ITimePipupCallback): TimePopupFragment {
this.callback = callback
return this
}
...
}
。
确保您正在使用片段的视图模型。您不应通过将值发布到实时数据postValue(T value)
中来清除视图模型,因为这是不必要的。
使用以下视图模型,
class MyViewModel : ViewModel() {
private val users: MutableLiveData<List<User>> by lazy {
MutableLiveData().also {
loadUsers()
}
}
fun getUsers(): LiveData<List<User>> {
return users
}
private fun loadUsers() {
// Do an asynchronous operation to fetch users.
}
}
在DialogFragment中,通过以下方式初始化视图模型
ViewModelProviders.of(<FRAGMENTT>).get(MyViewModel.class);
如果您使用的是ktx,则通过以下方式初始化视图模型
// Get a reference to the ViewModel scoped to this Fragment
val viewModel by viewModels<MyViewModel>()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。