有一个活动和一些片段。每个片段都可以访问 ViewModel。问题是在旋转设备并返回片段后,observable 会触发两次。这是视图模型:
class AppViewModel(private val mainRepository: MainRepository) : ViewModel() {
//поле которое обновляется
val userInfo: MutableLiveData<Any> by lazy {
MutableLiveData<Any>()
}
...
//метод который обновляет поле
fun getUserInfo() {
...
}
}
在 Fragment 中使用 ViewModel:
class PersonalPage : Fragment(R.layout.fragment_personal_page) {
lateinit var viewModel: AppViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
viewBinding = FragmentPersonalPageBinding.inflate(inflater, container, false)
viewBinding!!.lifecycleOwner = viewLifecycleOwner
val retrofitService = RetrofitService.getInstance(requireContext())
val mainRepository = MainRepository(retrofitService)
viewModel = ViewModelProvider(
requireActivity(),
AppVMFactory(mainRepository)
)[AppViewModel::class.java]
return viewBinding!!.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.userInfo.observe(viewLifecycleOwner) {
it?.let {
if (it is UserInfo) {
println("viewmodel fetch")
...
}
}
}
viewModel.getUserInfo()
}
....
}
处理活动中的屏幕旋转以返回片段:
supportFragmentManager.findFragmentByTag("personal_page")?.let {
transaction.replace(R.id.contentContainer, it,"personal_page").commit()
} ?: run {
transaction.replace(R.id.contentContainer, personalPage,"personal_page").commit()
}
试图在旋转时移除监听器:
viewModel.userInfo.removeObservers(viewLifecycleOwner)
没有那样工作。尝试通过完全分配 null 来杀死视图模型 - 没有用。尽管我在调试下查看并且我在堆栈上有一份片段副本,也就是说,没有重复。是否有可能在屏幕旋转后以某种方式删除变量的侦听器,或者是否有另一种方法来处理一般的方向变化?或者,您可以在旋转后删除片段,然后再次切换到它,而不用标签搜索片段,但我认为这是错误的。
这很简单:订阅者在订阅后立即收到最新数据,如果它们已经存在并且
LifeCicleOwner处于合适的状态。转动屏幕后
LiveData,它已经包含数据,订阅者立即收到,然后您再次拉取下载,订阅者收到更新(重新下载)的数据。如果数据一旦加载就不需要更新,那么就需要按条件调用加载,例如,检查是否保存:
但是由于
ViewModelStoreOwner您可以在更改片段时将活动作为细微差别传递,因此您需要了解应用程序逻辑和所需的行为。