无法使用ViewModelFactory实例化我的ViewModel

I can't bind a ViewModel to my Fragment (using lateinit) because I'm doing something wrong in the way I'm creating the ViewModel in my Activity. What am I doing wrong?

原因:java.lang.RuntimeException:无法创建com.example.foo.FooViewModel类的实例

这是活动:

class FooActivity : AppCompatActivity() {

    private lateinit var viewModel: FooViewModel

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_foo)

        val id = intent.getLongExtra(FOO_ID, 1L)

        val viewModelFactory = FooViewModelFactory(
            id,
            FooDatabase.getInstance(application).fooDao,
            application)
        viewModel = ViewModelProviders.of(
            this, viewModelFactory).get(FooViewModel::class.java)    
    }
}

当Fragment尝试绑定viewModel时实例化viewModel时发生异常,请参见下面的代码注释行:

class BlankFragment : Fragment() {

    private val viewModel: FooViewModel by activityViewModels()

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

        super.onCreateView(inflater, container, savedInstanceState)
        val binding = FragmentBlankBinding.inflate(inflater)
        binding.setLifecycleOwner(this)

        // EXCEPTION OCCURS HERE
        binding.viewModel = viewModel

        return binding.root
    }
}

这是ViewModel和ViewModelFactory类的代码:

class FooViewModelFactory (
    private val id: Long,
    private val fooDao: FooDao,
    private val application: Application) : ViewModelProvider.Factory {

    @Suppress("unchecked_cast")
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(FooViewModel::class.java)) {
             return FooViewModel(
                  id,
                  fooDao,
                  application
             ) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

class FooViewModel(id: Long, fooDao : FooDao, app: Application ): AndroidViewModel(app) {

    private val _foo = MutableLiveData<Foo>()
    val foo: LiveData<Foo>
        get() = _foo

    // infrastructure needed to get the Foo from the database
    private val _database = fooDao
    private val _fooid = id
    private var viewModelJob = Job()
    // database queries in the IO thread to avoid locking up the UI
    private val ioScope = CoroutineScope(viewModelJob + Dispatchers.IO)

    init {
        // commenting this out and doing nothing doesn't affect exception in question.
        GlobalScope.launch{ getFoo()}
    }

    private fun getFoo() = ... // code to fetch Foo from database

}

编辑:堆栈跟踪。

2020-05-22 22:10:05.018 8599-8599/com.example.foo E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.foo, PID: 8599
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.foo/com.example.foo.FooActivity}: android.view.InflateException: Binary XML file line #19: Binary XML file line #19: Error inflating class fragment
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3037)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3172)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1906)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6863)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
     Caused by: android.view.InflateException: Binary XML file line #19: Binary XML file line #19: Error inflating class fragment
     Caused by: android.view.InflateException: Binary XML file line #19: Error inflating class fragment
     Caused by: java.lang.RuntimeException: Cannot create an instance of class com.example.foo.FooViewModel
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:269)
        at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:106)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:185)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
        at androidx.lifecycle.ViewModelLazy.getValue(ViewModelProvider.kt:54)
        at androidx.lifecycle.ViewModelLazy.getValue(ViewModelProvider.kt:41)
        at com.example.foo.BlankFragment.getViewModel(Unknown Source:2)
        at com.example.foo.BlankFragment.onCreateView(BlankFragment.kt:27)
        at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2698)
        at androidx.fragment.app.FragmentStateManager.ensureInflatedView(FragmentStateManager.java:218)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1183)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
        at androidx.fragment.app.FragmentLayoutInflaterFactory.onCreateView(FragmentLayoutInflaterFactory.java:109)
        at androidx.fragment.app.FragmentController.onCreateView(FragmentController.java:135)
        at androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:356)
        at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:335)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:780)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
        at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:469)
        at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:140)
        at com.example.foo.FooActivity.onCreate(FooActivity.kt:29)
        at android.app.Activity.performCreate(Activity.java:7149)
        at android.app.Activity.performCreate(Activity.java:7140)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1288)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3017)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3172)
2020-05-22 22:10:05.019 8599-8599/com.example.foo E/AndroidRuntime:     at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1906)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6863)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
     Caused by: java.lang.NoSuchMethodException: <init> [class android.app.Application]
        at java.lang.Class.getConstructor0(Class.java:2327)
        at java.lang.Class.getConstructor(Class.java:1725)
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:267)
            ... 40 more