简体   繁体   English

为什么为我的viewModel类实现ViewModelProvider.Factory很重要?

[英]Why it is important to implement a ViewModelProvider.Factory for my viewModel class?

I have built a fragment that basically contains a Recyclerviewer with a custom ViewModel for my Data type using data binding and LiveData (which is a piece of code that I frequently implement) but in this time a runtime exception error has occurred! 我已经构建了一个片段,该片段基本上包含一个Recyclerviewer以及一个使用数据绑定和LiveData(这是我经常实现的代码)的针对我的数据类型的自定义ViewModel,但是这一次发生了运行时异常错误!

/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.tdm_project, PID: 9460
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.tdm_project/com.example.tdm_project.MainActivity}: java.lang.RuntimeException: Cannot create an instance of class com.example.tdm_project.viewmodel.ArticleViewModel
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2734)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2799)
        at android.app.ActivityThread.-wrap12(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1537)
        at android.os.Handler.dispatchMessage(Handler.java:110)
        at android.os.Looper.loop(Looper.java:203)
        at android.app.ActivityThread.main(ActivityThread.java:6269)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)
     Caused by: java.lang.RuntimeException: Cannot create an instance of class com.example.tdm_project.viewmodel.ArticleViewModel
        at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:154)
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:211)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:135)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:103)
        at com.example.tdm_project.HomeFragment.onCreateView(HomeFragment.kt:75)
        at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2439)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1460)
        at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
        at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:802)
        at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
        at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
        at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
        at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
        at androidx.fragment.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3273)
        at androidx.fragment.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3229)
        at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:201)
        at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:620)
        at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:178)
        at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1248)
        at android.app.Activity.performStart(Activity.java:6683)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2697)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2799) 
        at android.app.ActivityThread.-wrap12(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1537) 
        at android.os.Handler.dispatchMessage(Handler.java:110) 
        at android.os.Looper.loop(Looper.java:203) 
        at android.app.ActivityThread.main(ActivityThread.java:6269) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924) 
     Caused by: java.lang.InstantiationException: java.lang.Class<com.example.tdm_project.viewmodel.ArticleViewModel> has no zero argument constructor
        at java.lang.Class.newInstance(Native Method)

After googling my problem, the only suggestion I found is to implement a ViewModelFactory even though am using a ViewModel class and not AndroidViewModel. 搜索了我的问题后,我发现的唯一建议是即使使用的是ViewModel类而不是AndroidViewModel,也要实现ViewModelFactory。

See This answer 看到这个答案

ArticleViewModel class ArticleViewModel类



class ArticleViewModel : ViewModel {

    //lists
    private var articleMList = MutableLiveData<ArrayList<ArticleViewModel>>()
    private var articleInnerList = ArrayList<ArticleViewModel>()

    constructor(
     article: Article
    ) : super() {
        //const with parameters
    }

    //to observe my list
    fun getArticles() : MutableLiveData<ArrayList<ArticleViewModel>>{

        articleMList.value = articleInnerList

        return articleMList
    }

    //retrieve data from backend
    fun getData() {
            //some code
        }
}

Fragment class 片段类


class HomeFragment : Fragment() {


    //viewmodel
    private lateinit var vmodel : ArticleViewModel



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

        //set the view
        rootView = inflater.inflate(R.layout.home_fragment, container, false)

         //a function to initialize my recyclerview
        intialiserHorizontally()

          //creating the instance of viewmodel
        vmodel = ViewModelProviders.of(activity!!).get(ArticleViewModel::class.java)

        vmodel.getArticles().observe(this, Observer {
             customHAdapter.swapData(it)
        })

//getting the data from my db
        vmodel.getData()




        return rootView
    }

My question is why it is necessary to implement a ViewModelProvider.Factory in this case? 我的问题是为什么在这种情况下必须实现ViewModelProvider.Factory?

On its own, the ViewModel system only knows how to use a zero-argument constructor on your ViewModel subclasses (or a single-parameter constructor for AndroidViewModel subclasses). ViewModel系统本身仅知道如何在ViewModel子类上使用零参数构造函数(对于AndroidViewModel子类则使用单参数构造函数)。 So, either: 因此,要么:

  • Have no constructors at all, or 根本没有构造函数,或者

  • Have an explicit zero-argument constructor (but consider getting rid of your other one, as nothing should use it), or 有一个显式的零参数构造函数(但是考虑摆脱其他变量,因为什么都不要使用它),或者

  • Implement a factory, so you can call your desired custom constructor 实现工厂,因此您可以调用所需的自定义构造函数

Generally, if you want to create an instance of the ViewModel by ViewModelProviders.of(activity).get(ArticleViewModel::class.java) then it expects zero-argument constructor of the ViewModel . 通常,如果要通过ViewModelProviders.of(activity).get(ArticleViewModel::class.java)创建ViewModel的实例,则它期望ViewModel零参数构造函数。 If you want to pass any dependency to the ViewModel constructor then you have to use a factory and then you can instantiate by ViewModelProviders.of(activity, factory).get(ArticleViewModel::class.java) . 如果要将任何依赖项传递给ViewModel构造函数,则必须使用工厂,然后可以通过ViewModelProviders.of(activity, factory).get(ArticleViewModel::class.java)进行实例化。

Suggestion: 建议:

  1. Use dagger for dependency injection (it will make your life easy :)) 使用匕首进行依赖项注入(它将使您的生活变得轻松:))
  2. Use list of data class private var articlesLiveData = MutableLiveData<List<Article>>() instead of list of ViewModels in your ViewModel. 使用数据类private var articlesLiveData = MutableLiveData<List<Article>>()而不是ViewModel中的ViewModels列表,而应使用private var articlesLiveData = MutableLiveData<List<Article>>()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 获取ViewModel ViewModelProvider.Factory和应用程序上下文 - Get ViewModel ViewModelProvider.Factory and Application Context ViewModelProvider.Factory 总是返回一个视图模型 - ViewModelProvider.Factory always return one viewmodel 匕首2 viewmodels和ViewModelProvider.Factory - dagger 2 viewmodels and ViewModelProvider.Factory 将ViewModelProvider.Factory的提供程序注入espresso测试 - Inject provider of ViewModelProvider.Factory into esspresso test 如何将 ViewModelProvider.Factory 注入片段 - How to inject ViewModelProvider.Factory into a fragment Dagger 2 ViewModelProvider.Factory绑定多次 - Dagger 2 ViewModelProvider.Factory bound multiple times ViewModelProvider.Factory 和 ViewModelProvider.NewInstanceFactory 有什么区别? - What are the differences between ViewModelProvider.Factory and ViewModelProvider.NewInstanceFactory? 为什么我们需要 ViewModelProvider.Factory 将视图 model 传递到屏幕? - Why do we need ViewModelProvider.Factory to pass view model to a screen? 为什么在ViewModelProvider.Factory实现中添加@Singleton批注会导致编译错误[Dagger / MissingBinding]? - Why adding @Singleton annotation to ViewModelProvider.Factory implementation causes a compile error [Dagger/MissingBinding]? 使用Android上的Dagger和Java,ViewModelProvider.Factory在片段上保持为空 - ViewModelProvider.Factory remains null on fragment using Dagger and Java on Android
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM