Adrian 好心地向我提供了他的项目样本。这个答案是基于示例项目的调试结果。
导致您遇到的问题的问题实际上位于您的 MainActivity 类中。您在活动的onCreate 方法中实例化AddReminderFragment,并在按下FAB 时显示此片段的实例。
一切似乎都很好,除了 - 你总是呈现AddReminderFragment的同一个实例。这意味着当你第一次展示这个片段时,你会得到全新的AddReminderViewModel,它是使用by viewModels() 延迟加载的。
最初,我认为延迟加载 by viewModels() 导致了这个问题,因为它使用片段本身作为视图模型存储并且它缓存创建的视图模型以防您以后想要重用它.事实并非如此。
如何解决这个问题?
切勿存储对 Activity 和 Fragment 的引用或尽可能避免使用,并在有任何引用时小心。它可能会导致内存泄漏。
简要描述我所做的:
- 从
MainActivity 中删除了private lateinit var modal: AddReminderFragment 变量;
- 从
MainActivity 中删除了ITimePipupCallback;
- 从
TimePopupFragment 中删除了onAttach(context: Context);
- 在
TimePopupFragment 中实现了fun setCallback(callback: ITimePipupCallback): TimePopupFragment;
- 在显示来自
AddReminderFragment 的TimePopupFragment 实例之前,传入回调ITimePipupCallback 实例。好像它是对AlertDialog 按钮单击的回调;
- 从
AddReminderFragment 中删除了 onTimePicked 和 onDayPicked 方法,因为它们不再需要。
更新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
}
...
}
您可以安全地从AddReminderFragment 中删除override fun onDismiss(dialog: DialogInterface)。