防止每次显示我的片段和列表时都创建它们



我第一次在我的应用程序中使用带有导航组件的数据绑定和片段。关于导航和加载我的列表,一切都很好。我的问题是:

当我在列表中单击其中一个项目时,我会导航到该项目的详细片段。但是当我返回到列表(onBack(时,片段和列表会被再次加载,它们会被重新创建

我想要实现的是不重新创建片段和列表。它们保持相同的状态,这样当我从详细信息返回时,我可以继续从我停止的点导航我的列表。

我的代码:

碎片

class ListFragment : Fragment() {
private lateinit var viewDataBinding: FragmentListBinding
private lateinit var adapter: ListAdapter
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
viewDataBinding = FragmentListBinding.inflate(inflater, container, false).apply {
viewmodel = ViewModelProviders.of(this@ListFragment).get(ListViewModel::class.java)
lifecycleOwner = viewLifecycleOwner
}
return viewDataBinding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupAdapter()
setupObservers()
}
private fun setupObservers() {
viewDataBinding.viewmodel?.listLive?.observe(viewLifecycleOwner, Observer {
adapter.updateList(it)
})
viewDataBinding.viewmodel?.toastMessage?.observe(viewLifecycleOwner, Observer {
activity?.longToast(it)
})
}
private fun setupAdapter() {
val viewModel = viewDataBinding.viewmodel
if (viewModel != null) {
adapter = ListAdapter(viewDataBinding.viewmodel!!)
val layoutManager = LinearLayoutManager(activity)
list_rv.layoutManager = layoutManager
list_rv.adapter = adapter
}
}
override fun onResume() {
super.onResume()
viewDataBinding.viewmodel?.fetchList()
}
}

碎片布局

<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<variable
name="viewmodel"
type="app.example.list.ListViewModel" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="@{safeUnbox(viewmodel.dataLoading) ? View.GONE : View.VISIBLE}" />

</RelativeLayout>

查看模型

class ListViewModel : BaseViewModel() {
val listLive = MutableLiveData<List<Item>>()
fun fetchList() {
dataLoading.value = true
ItemRepository.getInstance().getList() { isSuccess, response ->
dataLoading.value = false
if (isSuccess) {
listLive.value = response?.items
empty.value = false
} else {
empty.value = true
}
}
}
}

我正在列表和带有导航功能的项目之间导航

itemView.findNavController().navigate(R.id.action_listFragment_to_detailFragment)

您永远不应该在onResume()等生命周期方法中重新加载数据——这就是为什么每次返回片段时数据都会重新加载。

相反,您应该在ViewModel的init块中只调用fetchList()一次,这样可以确保它只运行一次:

class ListViewModel : BaseViewModel() {
val listLive = MutableLiveData<List<Item>>()
init {
fetchList()
}
fun fetchList() {
dataLoading.value = true
ItemRepository.getInstance().getList() { isSuccess, response ->
dataLoading.value = false
if (isSuccess) {
listLive.value = response?.items
empty.value = false
} else {
empty.value = true
}
}
}
}

目前尚不清楚您的getList()方法是如何工作的。现在的编写方式对于单个回调来说通常是正确的。如果getList()实际返回的值流在基础数据更改时继续传递回调,则必须确保在onCleared()中注销该回调(ViewModel被销毁时的回调(。

由于以下代码-,您每次都会重新创建回收列表

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupAdapter()     //you are setting adapter every time view is getting created
setupObservers()
}

当您使用导航体系结构进行导航时,每次导航到目的地时,前一个片段将被停止((,返回后将重新创建。因为到目前为止,导航组件没有的后台问题

但使用ViewModel的全部目的是不保存片段状态,而是让ViewModel保留数据。您正在使用视图模型,但不能每次都在回收视图上设置适配器。

当您从视图模型中获取列表时,只需通知回收视图列表即可。

最新更新