无法创建类 ViewModel kotlin 的实例

Posted

技术标签:

【中文标题】无法创建类 ViewModel kotlin 的实例【英文标题】:Cannot create an instance of class ViewModel kotlin 【发布时间】:2018-11-02 06:19:56 【问题描述】:

这是我的代码

class BookmarkViewModel(app: Application) : androidViewModel(app) 

    private val dao = BookmarkDb.get(app).bookmarkDao()

    companion object 
        private const val PAGE_SIZE = PagingConstants.PERPAGE

        /**
         * If placeholders are enabled, PagedList will report the full size but some items might
         * be null in onBind method (PagedListAdapter triggers a rebind when data is loaded).
         * <p>
         * If placeholders are disabled, onBind will never receive null but as more pages are
         * loaded, the scrollbars will jitter as new pages are loaded. You should probably disable
         * scrollbars if you disable placeholders.
         */
        private const val ENABLE_PLACEHOLDERS = true
    

        val allBookmarks = LivePagedListBuilder(dao.allBookmarkByDatetime(), PagedList.Config.Builder()
                    .setPageSize(PAGE_SIZE)
                    .setEnablePlaceholders(ENABLE_PLACEHOLDERS)
                    .build()).build()

    fun insert(title: String, description: String, datetime: String) = ioThread 
        dao.insert(Bookmark(id = 0, title = title, description = description, datetime = datetime))
    

    fun remove(bookmark: Bookmark) = ioThread 
        dao.delete(bookmark)
    

这是来自谷歌样本.. 在我想要之后:

class BookmarkListFragment : FirstFragment() 

private var viewModel: BookmarkViewModel? = null
..

    override fun onActivityCreated(savedInstanceState: Bundle?) 
        super.onActivityCreated(savedInstanceState)

        viewModel = ViewModelProviders.of(activity!!).get(BookmarkViewModel::class.java)
...

这就是问题所在:

java.lang.RuntimeException:无法创建 com.lacas.db.room.BookmarkViewModel 类的实例

我可以在片段中使用它吗?

java.lang.RuntimeException:无法启动活动 ComponentInfocom.lacas.asd/com.lacas.asd.ui.activities.testtabs.TestTab2Activity:java.lang.RuntimeException:无法创建 com 类的实例。 lacas.asd.db.room.BookmarkViewModel 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2924) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2985) 在 android.app.ActivityThread.-wrap14(ActivityThread.java) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1635) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:154) 在 android.app.ActivityThread.main(ActivityThread.java:6692) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358) 原因:java.lang.RuntimeException:无法创建类 com.lacas.asd.db.room.BookmarkViewModel 的实例 在 android.arch.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:207) 在 android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:134) 在 android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:102) 在 com.lacas.asd.ui.activities.testtabs.TestTab2Activity$viewModel$2.invoke(TestTab2Activity.kt:34) 在 com.lacas.asd.ui.activities.testtabs.TestTab2Activity$viewModel$2.invoke(TestTab2Activity.kt:29) 在 kotlin.UnsafeLazyImpl.getValue(Lazy.kt:154) 在 com.lacas.asd.ui.activities.testtabs.TestTab2Activity.getViewModel(TestTab2Activity.kt) 在 com.lacas.asd.ui.activities.testtabs.TestTab2Activity.onCreated(TestTab2Activity.kt:45) 在 com.lacas.asd.base.BasePermissionsActivity.onCreate(BasePermissionsActivity.kt:34) 在 android.app.Activity.performCreate(Activity.java:6912) 在 android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1126) 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2877) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2985) 在 android.app.ActivityThread.-wrap14(ActivityThread.java) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1635) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:154) 在 android.app.ActivityThread.main(ActivityThread.java:6692) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358) 引起:java.lang.reflect.InvocationTargetException 在 java.lang.reflect.Constructor.newInstance0(本机方法) 在 java.lang.reflect.Constructor.newInstance(Constructor.java:430) 在 android.arch.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:199) 在 android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:134) 在 android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:102) 在 com.lacas.asd.ui.activities.testtabs.TestTab2Activity$viewModel$2.invoke(TestTab2Activity.kt:34) 在 com.lacas.asd.ui.activities.testtabs.TestTab2Activity$viewModel$2.invoke(TestTab2Activity.kt:29) 在 kotlin.UnsafeLazyImpl.getValue(Lazy.kt:154) 在 com.lacas.asd.ui.activities.testtabs.TestTab2Activity.getViewModel(TestTab2Activity.kt) 在 com.lacas.asd.ui.activities.testtabs.TestTab2Activity.onCreated(TestTab2Activity.kt:45) 在 com.lacas.asd.base.BasePermissionsActivity.onCreate(BasePermissionsActivity.kt:34) 在 android.app.Activity.performCreate(Activity.java:6912) 在 android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1126) 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2877) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2985) 在 android.app.ActivityThread.-wrap14(ActivityThread.java) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1635) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:154) 在 android.app.ActivityThread.main(ActivityThread.java:6692) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358) 原因:java.lang.RuntimeException:找不到 com.lacas.asd.db.room.BookmarkDb 的实现。 BookmarkDb_Impl 不存在 在 android.arch.persistence.room.Room.getGeneratedImplementation(Room.java:93) 在 android.arch.persistence.room.RoomDatabase$Builder.build(RoomDatabase.java:630) 在 com.lacas.asd.db.room.BookmarkDb$Companion.get(BookmarkDb.kt:29) 在 com.lacas.asd.db.room.BookmarkViewModel.(BookmarkViewModel.kt:14) 在 java.lang.reflect.Constructor.newInstance0(本机方法) 在 java.lang.reflect.Constructor.newInstance(Constructor.java:430) 在 android.arch.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:199) 在 android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:134) 在 android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:102) 在 com.lacas.asd.ui.activities.testtabs.TestTab2Activity$viewModel$2.invoke(TestTab2Activity.kt:34) 在 com.lacas.asd.ui.activities.testtabs.TestTab2Activity$viewModel$2.invoke(TestTab2Activity.kt:29) 在 kotlin.UnsafeLazyImpl.getValue(Lazy.kt:154) 在 com.lacas.asd.ui.activities.testtabs.TestTab2Activity.getViewModel(TestTab2Activity.kt) 在 com.lacas.asd.ui.activities.testtabs.TestTab2Activity.onCreated(TestTab2Activity.kt:45) 在 com.lacas.asd.base.BasePermissionsActivity.onCreate(BasePermissionsActivity.kt:34) 在 android.app.Activity.performCreate(Activity.java:6912) 在 android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1126) 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2877) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2985) 在 android.app.ActivityThread.-wrap14(ActivityThread.java) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1635) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:154) 在 android.app.ActivityThread.main(ActivityThread.java:6692) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)

【问题讨论】:

java.lang.RuntimeException: cannot find implementation for com.lacas.asd.db.room.BookmarkDb. BookmarkDb_Impl 【参考方案1】:

这里有人说:

Android room persistent: AppDatabase_Impl does not exist

解决办法是:

implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"

implementation "androidx.room:room-runtime:$roomVersion"
kapt "androidx.room:room-compiler:$roomVersion"


implementation "androidx.paging:paging-runtime:$paging_version"
    

【讨论】:

在最新版本的 Android Studio 中,添加 kapt 会导致构建错误:“原因:应用程序:不推荐使用原始 kapt。”所以你需要将apply plugin: 'kotlin-kapt' 添加到你的build.gradle。【参考方案2】:

更改viewModel = ViewModelProviders.of(activity!!).get(BookmarkViewModel::class.java)

viewModel = ViewModelProviders.of(this).get(BookmarkViewModel::class.java)

此外,不要将viewModel 实例化为null。将其更改为 lateinit var 这样您就不必立即实例化(但您告诉 Kotlin 您在访问它之前实例化它)。你可以这样做:private lateinit var viewModel: BookMarkViewModel

EDIT 问题的根源在于Room Dependencies 不是在同一版本上或annotationProcessor 被使用而不是kapt(使用Kotlin 时需要kapt

【讨论】:

用 this 和 lateinit 试过,同样... 也试过: private val viewModel by lazy(LazyThreadSafetyMode.NONE) ViewModelProviders.of(this).get(CheeseViewModel::class.java) 但总是一样... 我正在使用选项卡和片段。我希望在最后一个片段/选项卡中有一个实例。可能吗?还是只是在活动? 因为您使用的是 Kotlin。在 Room 的依赖项中,您是否使用 kapt 而不是 annotationProcessor 并且所有 Room 依赖项都具有相同的版本?如果不更改,然后重试。如果它仍然不起作用,如果你能提供我你的数据库创建代码,我会非常高兴,因为错误可能就在某个地方。 是的 :) 很抱歉,很难弄清楚,但很高兴它现在可以工作了 :)! 在最新版本的 Android Studio 中,添加 kapt 会导致错误:“原因:应用程序:不推荐使用原始 kapt。”所以你需要将apply plugin: 'kotlin-kapt' 添加到你的build.gradle。【参考方案3】:

删除 kapt “xxxx.xxx”。如果您仍然在 gradle.build 中使用它,因为它已被弃用并添加

apply plugin: 'kotlin-kapt'

在应用模块的 gradle.build 末尾。 这解决了我在 android studio 3.1 中的问题

【讨论】:

【参考方案4】:

这三件事对我有用:

    在依赖项中添加/保留 annotationProcessor 和 Kapt

annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version" kapt "android.arch.lifecycle:compiler:$lifecycle_version"

annotationProcessor "android.arch.persistence.room:compiler:$room_version" kapt "android.arch.persistence.room:compiler:$room_version"

    在 build.gradle(app) 顶部添加apply plugin: 'kotlin-kapt' 并清理项目

    重新安装应用程序

【讨论】:

【参考方案5】:

在我的情况下,我在 DatabaseClass 中添加了private set:| 我删除了它。

  private var INSTANCE: NoteDatabase? = null
            private set

到:

private var INSTANCE: NoteDatabase? = null

这个问题花了我 2 个小时 :|||

【讨论】:

实例化viewmodel时,只需要超级构造函数中的application参数【参考方案6】:

就我而言,我忘记用

注释我的 DatabaseClass 类
@Database(entities = [Book::class], version = 1)
abstract class BookRoomDatabase: RoomDatabase() 

【讨论】:

【参考方案7】:

在我的例子中,这个实现解决了我的问题

implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"

在我实现这个之前 implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"

【讨论】:

【参考方案8】:

我通过这样做解决了同样的问题。

添加注释。

class AlertViewModel
@Inject
constructor(private val userRepository: AlertRepository) : ViewModel()
    val getList:LiveData<List<Alert>> get() =
        userRepository.getList.flowOn(Dispatchers.Main)
            .asLiveData(context = viewModelScope.coroutineContext)

    fun insert(user:Alert)
        viewModelScope.launch 
            userRepository.insert(user)
        
    

@HiltViewModel // Added this annotation
class AlertViewModel
@Inject
constructor(private val userRepository: AlertRepository) : ViewModel()
    val getList:LiveData<List<Alert>> get() =
        userRepository.getList.flowOn(Dispatchers.Main)
            .asLiveData(context = viewModelScope.coroutineContext)

    fun insert(user:Alert)
        viewModelScope.launch 
            userRepository.insert(user)
        
    

【讨论】:

【参考方案9】:

例如,如果您使用 Dagger/Hil,Fragment 或 Activity 应该需要 @AndroidEntryPoint

【讨论】:

以上是关于无法创建类 ViewModel kotlin 的实例的主要内容,如果未能解决你的问题,请参考以下文章

无法创建类 ViewModel 的实例

Koin快速入门——Android ViewModel

无法从 ViewModelProvider 创建 ViewModel

Kotlin:数组字符串模板

Android MVI 模式的简单实现(基于kotlin FLow 和 ViewModel)

ViewModel 中的 Kotlin Dagger 字段注入引发 Dagger/Binding 异常