Reset/clear 视图模型或实时数据
Reset/clear viewmodel or livedata
我正在遵循 Google 建议的 one-single-activity 应用程序模式,所以如果我想在 Fragments
之间共享数据] 我必须分享一个 ViewModel
其所有者必须是父 Activity
。 所以,问题变成了因为我只想在两个片段之间共享数据,而与其他片段无关。
假设我有 MainFragment
、CreateItemFragment
和 ScanDetailFragment
。因此,从第一个导航到 CreateItemFragment,每当我按下按钮时,我导航到 ScanDetailFragment 以扫描条形码,因此,通过 ViewModel 中的 LiveData
对象,我可以将扫描的值返回到ScandDetailFragment 完成后的 CreateItemFragment。当我决定取消项目的创建时,问题就出现了:我回到“MainFragment”,因为 ViewModel 的所有者是 Activity 的生命周期,一旦我再次进入 CreateItemFragment,之前扫描的值为还在。
有重置 ViewModel 的想法吗?
在这种情况下,您可以使用回调在片段之间共享数据。或者,如果您使用 DB/Sharedpreference/Content 提供程序,那么您不必担心共享数据,每个页面都会从商店中获取自己的数据 (DB/SharedPreference/Contentprovider)。
如果本指南对您有帮助,您也可以尝试https://medium.com/@lucasnrb/advanced-viewmodels-part-iii-share-a-viewmodel-between-fragments-59c014a3646
每次从MainFragment
进入CreateItemFragment
时都可以清除LiveData
值。
或者您可以通过 onBackPressed()
方法中的 CreateItemFragment
清除它。
当你取消项目的创建时,在观察者代码中将 livedata 值设置为 null.then if(updatedvalue!=null) 使用更新的实时数据编写你的代码 value.in 这样你就可以避免最后更新值。
but, aren't Viewmodels also aimed to share data between different views?
没有。每个视图模型应该负责一个视图。 “共享视图模型”模式适用于您有一个大视图(即 activity)的情况,该视图具有多个需要共享数据/状态的子视图(即片段),例如 the master / detail example in the documentation。当您需要在子视图之间进行实时更新时,这对这些情况很方便。
在您的情况下,您在片段之间导航,因此应该通过转换传递数据。这意味着 passing arguments along when starting new fragments and registering for results when they complete their task.
那么你的每个片段都是孤立的、独立的、更容易测试的,你不会最终得到一个做所有事情™的上帝视图模型,并在你试图跳过时变成一团糟篮球占它可能处于的每个状态。
目前(2022 年),viewmodel.getViewModelStore.clear();
或 onCleared();
方法已弃用。
因此,如果您想清除 ViewModel 持有的数据或清除 LiveData 的值,您只需使用 1 行代码,如下所示:
mainViewModel.getLiveData().getValue().clear();
- getLiveData() 是我在 MainViewModel 中的方法 class 到 return
liveData
变量
- getValue() 是 LiveData 提供的默认方法 (MutableLiveData: setValue(), postValue())
如果您需要在用户按下 Fragment 中的后退按钮时清除数据,您可以像下面的代码一样将其放在 onViewCreated 方法 - LifecycleFragment 的方法中。
private void handleOnBackPressed() {
requireActivity().getOnBackPressedDispatcher().addCallback(new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
Objects.requireNonNull(mainViewModel.getLiveData().getValue()).clear();
requireActivity().finish();
}
});
}
我在 Git 上的项目如果您想参考代码(它仍在更新): https://github.com/Nghien-Nghien/PokeAPI-Java/blob/master/app/src/main/java/com/example/pokemonapi/fragment/MainFragment.java
我正在遵循 Google 建议的 one-single-activity 应用程序模式,所以如果我想在 Fragments
之间共享数据] 我必须分享一个 ViewModel
其所有者必须是父 Activity
。 所以,问题变成了因为我只想在两个片段之间共享数据,而与其他片段无关。
假设我有 MainFragment
、CreateItemFragment
和 ScanDetailFragment
。因此,从第一个导航到 CreateItemFragment,每当我按下按钮时,我导航到 ScanDetailFragment 以扫描条形码,因此,通过 ViewModel 中的 LiveData
对象,我可以将扫描的值返回到ScandDetailFragment 完成后的 CreateItemFragment。当我决定取消项目的创建时,问题就出现了:我回到“MainFragment”,因为 ViewModel 的所有者是 Activity 的生命周期,一旦我再次进入 CreateItemFragment,之前扫描的值为还在。
有重置 ViewModel 的想法吗?
在这种情况下,您可以使用回调在片段之间共享数据。或者,如果您使用 DB/Sharedpreference/Content 提供程序,那么您不必担心共享数据,每个页面都会从商店中获取自己的数据 (DB/SharedPreference/Contentprovider)。
如果本指南对您有帮助,您也可以尝试https://medium.com/@lucasnrb/advanced-viewmodels-part-iii-share-a-viewmodel-between-fragments-59c014a3646
每次从MainFragment
进入CreateItemFragment
时都可以清除LiveData
值。
或者您可以通过 onBackPressed()
方法中的 CreateItemFragment
清除它。
当你取消项目的创建时,在观察者代码中将 livedata 值设置为 null.then if(updatedvalue!=null) 使用更新的实时数据编写你的代码 value.in 这样你就可以避免最后更新值。
but, aren't Viewmodels also aimed to share data between different views?
没有。每个视图模型应该负责一个视图。 “共享视图模型”模式适用于您有一个大视图(即 activity)的情况,该视图具有多个需要共享数据/状态的子视图(即片段),例如 the master / detail example in the documentation。当您需要在子视图之间进行实时更新时,这对这些情况很方便。
在您的情况下,您在片段之间导航,因此应该通过转换传递数据。这意味着 passing arguments along when starting new fragments and registering for results when they complete their task.
那么你的每个片段都是孤立的、独立的、更容易测试的,你不会最终得到一个做所有事情™的上帝视图模型,并在你试图跳过时变成一团糟篮球占它可能处于的每个状态。
目前(2022 年),viewmodel.getViewModelStore.clear();
或 onCleared();
方法已弃用。
因此,如果您想清除 ViewModel 持有的数据或清除 LiveData 的值,您只需使用 1 行代码,如下所示:
mainViewModel.getLiveData().getValue().clear();
- getLiveData() 是我在 MainViewModel 中的方法 class 到 return
liveData
变量 - getValue() 是 LiveData 提供的默认方法 (MutableLiveData: setValue(), postValue())
如果您需要在用户按下 Fragment 中的后退按钮时清除数据,您可以像下面的代码一样将其放在 onViewCreated 方法 - LifecycleFragment 的方法中。
private void handleOnBackPressed() {
requireActivity().getOnBackPressedDispatcher().addCallback(new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
Objects.requireNonNull(mainViewModel.getLiveData().getValue()).clear();
requireActivity().finish();
}
});
}
我在 Git 上的项目如果您想参考代码(它仍在更新): https://github.com/Nghien-Nghien/PokeAPI-Java/blob/master/app/src/main/java/com/example/pokemonapi/fragment/MainFragment.java