无法创建 class com.example.retrotest.ui.AlbumsViewModel 的实例

Cannot create an instance of class com.example.retrotest.ui.AlbumsViewModel

当我尝试使用模拟器启动应用程序时出现错误。 尝试在第 40 行和第 41 行查找 AlbumListFragment 错误。我不明白我做错了什么。已多次执行此代码而没有错误。

我还在片段布局中使用 android:text="@{viewModel.response}"。我不认为数据绑定是问题所在。

有人看到我哪里做错了吗?

2022-04-03 18:25:22.687 4959-4959/com.example.mvvmretrofit E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.mvvmretrofit, PID: 4959
    java.lang.RuntimeException: Cannot create an instance of class com.example.retrotest.ui.AlbumsViewModel
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:230)
        at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:112)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:169)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:139)
        at com.example.retrotest.ui.AlbumListFragment$onCreateView$viewModel.invoke(AlbumListFragment.kt:41)
        at com.example.retrotest.ui.AlbumListFragment$onCreateView$viewModel.invoke(AlbumListFragment.kt:40)
        at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
        at com.example.retrotest.ui.AlbumListFragment.onCreateView$lambda-0(AlbumListFragment.kt:40)
        at com.example.retrotest.ui.AlbumListFragment.onCreateView(AlbumListFragment.kt:43)
        at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2995)
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:523)
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
        at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1374)
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2841)
        at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:2777)
        at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3020)
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:551)
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
        at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1374)
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2841)
        at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2784)
        at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:262)
        at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:478)
        at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246)
        at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1435)
        at android.app.Activity.performStart(Activity.java:8018)
        at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3475)
        at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
        at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
        at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
     Caused by: java.lang.NoSuchMethodException: com.example.retrotest.ui.AlbumsViewModel.<init> [class android.app.Application]
        at java.lang.Class.getConstructor0(Class.java:2332)
        at java.lang.Class.getConstructor(Class.java:1728)
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:228)
        at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:112) 
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:169) 
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:139) 
        at com.example.retrotest.ui.AlbumListFragment$onCreateView$viewModel.invoke(AlbumListFragment.kt:41) 
        at com.example.retrotest.ui.AlbumListFragment$onCreateView$viewModel.invoke(AlbumListFragment.kt:40) 
        at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74) 
        at com.example.retrotest.ui.AlbumListFragment.onCreateView$lambda-0(AlbumListFragment.kt:40) 
        at com.example.retrotest.ui.AlbumListFragment.onCreateView(AlbumListFragment.kt:43) 
        at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2995) 
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:523) 
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261) 
        at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113) 
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1374) 
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2841) 
        at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:2777) 
        at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3020) 
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:551) 
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261) 
        at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113) 
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1374) 
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2841) 
        at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2784) 
        at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:262) 
        at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:478) 
        at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246) 
        at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1435) 
        at android.app.Activity.performStart(Activity.java:8018) 
        at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3475) 
        at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221) 
        at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201) 
        at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:223) 
        at android.app.ActivityThread.main(ActivityThread.java:7656) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 
2022-04-03 18:25:23.849 4959-4975/com.example.mvvmretrofit W/System: A resource failed to call close. 

专辑列表片段:

class AlbumListFragment : Fragment() {

    private val viewModel: AlbumsViewModel by lazy {
        ViewModelProvider(this)[AlbumsViewModel::class.java]
    }
    /**
     * Inflates the layout with Data Binding, sets its lifecycle owner to the OverviewFragment
     * to enable Data Binding to observe LiveData, and sets up the RecyclerView with an adapter.
     */
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val binding = FragmentAlbumListBinding.inflate(inflater)

        binding.viewModel = viewModel

        // Allows Data Binding to Observe LiveData with the lifecycle of this Fragment
        binding.lifecycleOwner = this

        // Giving the binding access to the OverviewViewModel
        binding.viewModel = viewModel

        setHasOptionsMenu(true)
        return binding.root
    }

    /**
     * Inflates the overflow menu that contains filtering options.
     */
    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        inflater.inflate(R.menu.overflow_menu, menu)
        super.onCreateOptionsMenu(menu, inflater)
    }
}

AlbumsViewModel.kt:

class AlbumsViewModel(val application: MyApplication) : AndroidViewModel(application) {

    private val _response = MutableLiveData<String>()

    val response: LiveData<String>
        get() = _response

    /**
     * Call getMarsRealEstateProperties() on init so we can display status immediately.
     */
    init {
        getAlbumProperties()
    }

    /**
     * Sets the value of the status LiveData to the Mars API status.
     */
    private fun getAlbumProperties() {
        AlbumApi.retrofitService.getAllAlbums().enqueue(object: Callback<List<Album>> {

            override fun onResponse(call: Call<List<Album>>, response: Response<List<Album>>) {
                _response.value = "Success: ${response.body()?.size} Album properties retrieved"
            }

            override fun onFailure(call: Call<List<Album>>, t: Throwable) {
                _response.value = "Failure: " + t.message
            }

        })
        _response.value = "Set the Album API Response here!"
    }

}

真正的错误是下面列出的那个

Caused by: java.lang.NoSuchMethodException: com.example.retrotest.ui.AlbumsViewModel.<init> [class android.app.Application]

此错误是因为您的 ViewModel 有一个 non-standard 构造函数(使用您自定义的 MyApplication 而不是默认的 Application 参数)并且提供者工厂找不到它的构造函数正在寻找。

你需要改变

AlbumsViewModel(val application: MyApplication)

AlbumsViewModel(val application: Application)

让它发挥作用。

如果您在某个地方确实需要 MyApplication 的 ViewModel 实例,您总是可以通过从基础 class 强制转换它来获得它,如下所示:

val myapp = getApplication<MyApplication>()