首页 > 解决方案 > 如何在 startDestination 片段上加载 viewModel

问题描述

我正在尝试制作一个应用程序,该应用程序在加载应用程序时显示的第一个片段上显示数据列表。

我正在使用导航组件,并在 MainActivity 中实例化视图模型

事件视图模型.kt

...
    val events: MutableLiveData<Resource<List<Event>>> = MutableLiveData()

    init {
        getEvents()
    }

    private fun getEvents() = viewModelScope.launch {
        events.postValue(Resource.Loading())
        val response = eventRepository.getEvents(load())
        events.postValue(handleGetEvents(response))
    }
...

ActivityMain.kt

...
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Bind binding to xml
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // Setup viewModel dependency injection
        val eventRepository = EventRepository(EventDatabase(this))
        val eventViewModelProviderFactory = EventViewModelProviderFactory(eventRepository)
        viewModel = ViewModelProvider(this, eventViewModelProviderFactory).get(EventViewModel::class.java)


        // Setup nav
        bottomBar = binding.bottomNavigationView
        navController = findNavController( R.id.fragment)
        bottomBar.setupWithNavController(navController)
    }
 ...

显示的 FirstFragment 正在从 onViewCreated 内的 Main 活动加载 viewModel,如下所示:

片段优先.kt

...
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewModel = (activity as MainActivity).viewModel
        navController = Navigation.findNavController(view);

        viewModel.events.observe(viewLifecycleOwner, Observer { response ->
            when(response) {
                is Resource.Success -> {
                    response.data?.let {
                        initRecyclerView(it)
                        initViewPager(it)
                    }
                }
                is Resource.Error -> {
                    response.message?.let {
                        println("Error occured: $it")
                    }
                }
            }

        })
    }
...

然后我得到这个错误

Caused by: kotlin.UninitializedPropertyAccessException: lateinit property viewModel has not been initialized

我知道原因是视图模型需要时间来实例化,因为它正在调用 Internet 并接收 LiveData 的数据,因为我通过将另一个 Fragment 作为 StartDestination 对其进行了测试,其中包含一个导航到 FragmentFirst 的按钮,然后它工作得很好。

我想我可以用观察者模式包装整个 viewModel 并使片段在 viewModel 的实例化上观察。但我认为 viewModel 应该已经有一些功能或不需要我这样做的东西。

所以我的问题是::: 是否可以将视图模型观察者作为应用程序中加载的第一个片段,如果可以,我该怎么做?

先感谢您。

标签: androidkotlinmvvmviewmodel

解决方案


推荐阅读