【问题标题】:Android ViewModel has no zero argument constructor when calling .observe() on a sharedViewModel在 sharedViewModel 上调用 .observe() 时,Android ViewModel 没有零参数构造函数
【发布时间】:2021-03-03 17:37:21
【问题描述】:

我有以下课程:

视图模型

class MealPlanViewModel @AssistedInject constructor(private val mealPlanRepository: MealPlanRepository, @Assisted private val canteenId: String) : ViewModel() {


    // AssistedInject code for using ViewModel injection with runtime parameters
    @AssistedInject.Factory
    interface AssistedFactory {
        fun create (canteenId: String): MealPlanViewModel
    }

    companion object {
        fun provideFactory(assistedFactory: AssistedFactory, canteenId: String): ViewModelProvider.Factory = object : ViewModelProvider.Factory {
            override fun <T : ViewModel?> create(modelClass: Class<T>): T {
                return assistedFactory.create(canteenId) as T
            }
        }
    }
}

父片段:

class MealPlanFragment : Fragment() {

    val canteenId = "mensa"

    @Inject
    lateinit var viewModelAssistedFactory: MealPlanViewModel.AssistedFactory

    private val viewModel: MealPlanViewModel by viewModels {
        MealPlanViewModel.provideFactory(viewModelAssistedFactory, canteenId)
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val binding = FragmentMealPlanBinding.inflate(inflater, container, false)
        val tabLayout = binding.tabLayout
        val viewPager = binding.viewPager

        viewPager.adapter = MealPlanPagerAdapter(childFragmentManager, lifecycle)

        return binding.root
    }

}

以及通过viewpager附加到父片段的子片段

@AndroidEntryPoint
class DayFragment : Fragment() {

private val viewModel: MealPlanViewModel by viewModels(

        ownerProducer = {requireParentFragment()}

    )

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

        val binding = FragmentDayBinding.inflate(inflater, container, false)

        viewModel.getMealPlanByDay(...).observe(viewLifecycleOwner, Observer {

             ...

        })

        return binding.root
    }



    companion object {

        @JvmStatic
        fun newInstance(position: Int) =
            DayFragment().apply {
                arguments = Bundle().apply {
                    putInt(POSITION, position)
                }
            }

    }

}

呼唤

viewModel.getMealPlanByDay(...).observe(viewLifecycleOwner, Observer {

})

导致以下错误: 无法创建 MealPlanViewModel 类的实例 没有零参数构造函数

但是如果我不使用 AssistedInject 在父片段中创建 ViewModel 并像下面这样实例化它,我不会在子片段中得到“没有零参数构造函数”。

val bundle: Bundle = ...
val mealPlanRepository = ...

val mealPlanViewModelFactory = MealPlanViewModelFactory(mealPlanRepository, canteenId, this, bundle)
val viewModel = ViewModelProvider(this, mealPlanViewModelFactory).get(MealPlanViewModel::class.java)

关于为什么会这样以及如何在仍然使用 AssistedInject 的同时解决这个问题的任何想法?

【问题讨论】:

    标签: android dependency-injection viewmodel assisted-inject


    【解决方案1】:

    通过this question,Kotlin 属性委托 AssistedInject by viewModels() 懒惰地实例化视图模型。因此,如果您在扩展子 Fragment 之前未在父 Fragment onCreateView() 或更早的时间引用视图模型,则不会及时创建视图模型以供子 Fragment 在其 onCreateView() 中访问。使用ViewModelProvider 会在创建父片段后立即实例化视图模型。

    感谢您的提问,我遇到了同样的问题,并以与您相同的方式解决了。

    【讨论】:

      猜你喜欢
      • 2017-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-11
      • 2020-09-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多