0

我有以下课程:

视图模型

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 {

})

导致以下错误:Cannot create an instance of class MealPlanViewModel has no zero argument constructor

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

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

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

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

4

1 回答 1

0

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

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

于 2021-08-26T03:07:18.230 回答