首页 > 解决方案 > 为什么我在 ViewModel 中使用 LiveData 时数据不持久?

问题描述

我正在使用Navigation Component.

在底部A菜单的片段屏幕中,我可以recyclerview通过按钮动态添加项目。

如果我按下此屏幕上的按钮,它会移动到另一个可以选择数据的片段。

如果我在转换后的片段屏幕上选择数据,它会返回到前一个屏幕并recycler view item根据所选数据添加一个。

重复这个过程。

但是,即使我重复此过程,该项目也不会动态添加。

我使用向Listof添加项目,但由于调试,of不会从仅增加一个。LiveDataViewModelsize of the list typeLiveData

至少据我所知,数据应该被持久化,因为 usingviewmodel不受lifecycle.

但是我遇到的问题是,好像每次都因为换屏而被初始化并保存了。

为什么是这样?

视图模型

class WriteRoutineViewModel : ViewModel() {
    private var _items: MutableLiveData<ArrayList<RoutineModel>> = MutableLiveData(arrayListOf())
    val items: LiveData<ArrayList<RoutineModel>> = _items

    fun addRoutine(workout: String) {
        val item = RoutineModel(workout, "TEST")

        item.setSubItemList(detailItem)
        _items.value?.add(item)
        _items.value = _items.value
    }
}

分段

class WriteRoutineFragment : Fragment() {
    private var _binding : FragmentWriteRoutineBinding? = null
    private val binding get() = _binding!!
    private lateinit var adapter : RoutineAdapter
    private val args : WriteRoutineFragmentArgs by navArgs()
    private val vm : WriteRoutineViewModel by viewModels { WriteRoutineViewModelFactory() }

    override fun onCreateView(inflater: LayoutInflater,
                              container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        _binding = FragmentWriteRoutineBinding.inflate(inflater, container, false)

        adapter = RoutineAdapter(::addDetail, ::deleteDetail)
        binding.rv.adapter = this.adapter
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        args.workout?.let { workout ->
            vm.addRoutine(workout)
            Toast.makeText(context, workout, Toast.LENGTH_SHORT).show()
        }

        vm.items.observe(viewLifecycleOwner) { updatedItems ->
            adapter.setItems(updatedItems)
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

更新导航图

<fragment
        android:id="@+id/writeRoutine"
        android:name="com.example.lightweight.fragment.WriteRoutineFragment"
        android:label="fragment_write_routine"
        tools:layout="@layout/fragment_write_routine" >
        <action
            android:id="@+id/action_writeRoutineFragment_to_workoutListTabFragment"
            app:destination="@id/workoutListTabFragment" />
        <argument
            android:name="workout"
            app:argType="string"
            app:nullable="true"
            android:defaultValue="@null"/>
    </fragment>

标签: androidkotlinandroid-recyclerviewandroid-viewmodel

解决方案


视图模型应该具有视图模型的活动范围,以便能够在整个活动生命周期中存在。

视图模型必须像这样初始化,

private val model: SharedViewModel by activityViewModels()

这个确切的用例在Android Docs中有详细解释


推荐阅读