Reputation: 14066
Here is my code
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)
}
}
This is from the google samples.. After I want to:
class BookmarkListFragment : FirstFragment() {
private var viewModel: BookmarkViewModel? = null
..
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProviders.of(activity!!).get(BookmarkViewModel::class.java)
...
And here is the problem:
java.lang.RuntimeException: Cannot create an instance of class com.lacas.db.room.BookmarkViewModel
Can I use this in a fragment?
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.lacas.asd/com.lacas.asd.ui.activities.testtabs.TestTab2Activity}: java.lang.RuntimeException: Cannot create an instance of class com.lacas.asd.db.room.BookmarkViewModel at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2924) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2985) at android.app.ActivityThread.-wrap14(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1635) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6692) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358) Caused by: java.lang.RuntimeException: Cannot create an instance of class com.lacas.asd.db.room.BookmarkViewModel at android.arch.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:207) at android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:134) at android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:102) at com.lacas.asd.ui.activities.testtabs.TestTab2Activity$viewModel$2.invoke(TestTab2Activity.kt:34) at com.lacas.asd.ui.activities.testtabs.TestTab2Activity$viewModel$2.invoke(TestTab2Activity.kt:29) at kotlin.UnsafeLazyImpl.getValue(Lazy.kt:154) at com.lacas.asd.ui.activities.testtabs.TestTab2Activity.getViewModel(TestTab2Activity.kt) at com.lacas.asd.ui.activities.testtabs.TestTab2Activity.onCreated(TestTab2Activity.kt:45) at com.lacas.asd.base.BasePermissionsActivity.onCreate(BasePermissionsActivity.kt:34) at android.app.Activity.performCreate(Activity.java:6912) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1126) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2877) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2985) at android.app.ActivityThread.-wrap14(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1635) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6692) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358) Caused by: java.lang.reflect.InvocationTargetException at java.lang.reflect.Constructor.newInstance0(Native Method) at java.lang.reflect.Constructor.newInstance(Constructor.java:430) at android.arch.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:199) at android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:134) at android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:102) at com.lacas.asd.ui.activities.testtabs.TestTab2Activity$viewModel$2.invoke(TestTab2Activity.kt:34) at com.lacas.asd.ui.activities.testtabs.TestTab2Activity$viewModel$2.invoke(TestTab2Activity.kt:29) at kotlin.UnsafeLazyImpl.getValue(Lazy.kt:154) at com.lacas.asd.ui.activities.testtabs.TestTab2Activity.getViewModel(TestTab2Activity.kt) at com.lacas.asd.ui.activities.testtabs.TestTab2Activity.onCreated(TestTab2Activity.kt:45) at com.lacas.asd.base.BasePermissionsActivity.onCreate(BasePermissionsActivity.kt:34) at android.app.Activity.performCreate(Activity.java:6912) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1126) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2877) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2985) at android.app.ActivityThread.-wrap14(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1635) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6692) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358) Caused by: java.lang.RuntimeException: cannot find implementation for com.lacas.asd.db.room.BookmarkDb. BookmarkDb_Impl does not exist at android.arch.persistence.room.Room.getGeneratedImplementation(Room.java:93) at android.arch.persistence.room.RoomDatabase$Builder.build(RoomDatabase.java:630) at com.lacas.asd.db.room.BookmarkDb$Companion.get(BookmarkDb.kt:29) at com.lacas.asd.db.room.BookmarkViewModel.(BookmarkViewModel.kt:14) at java.lang.reflect.Constructor.newInstance0(Native Method) at java.lang.reflect.Constructor.newInstance(Constructor.java:430) at android.arch.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:199) at android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:134) at android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:102) at com.lacas.asd.ui.activities.testtabs.TestTab2Activity$viewModel$2.invoke(TestTab2Activity.kt:34) at com.lacas.asd.ui.activities.testtabs.TestTab2Activity$viewModel$2.invoke(TestTab2Activity.kt:29) at kotlin.UnsafeLazyImpl.getValue(Lazy.kt:154) at com.lacas.asd.ui.activities.testtabs.TestTab2Activity.getViewModel(TestTab2Activity.kt) at com.lacas.asd.ui.activities.testtabs.TestTab2Activity.onCreated(TestTab2Activity.kt:45) at com.lacas.asd.base.BasePermissionsActivity.onCreate(BasePermissionsActivity.kt:34) at android.app.Activity.performCreate(Activity.java:6912) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1126) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2877) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2985) at android.app.ActivityThread.-wrap14(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1635) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6692) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)
Upvotes: 17
Views: 24728
Reputation: 753
What was needed in my case. In build.gradle(:app), in the plugins block:
id 'kotlin-kapt'
In the dependencies block:
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
In the class Fragment, where Fragment is your Fragment name:
private lateinit var viewModel : ViewModel
In OnViewCreated of your Fragment:
viewModel = ViewModelProvider(this, ViewModelFactory()).get(ViewModel::class.java)
where ViewModel and ViewModelFactory are your ViewModel and ViewModelFactory names respectively.
Also, if you passed some variable in your ViewModel and ViewModelFactory, like private val repository: Repository
or private val mydao:MyDao
, make sure to add them to viewModel declaration this way:
next to lateinit viewModel at the beginning of the Fragment class:
private val myRoomDatabase : MyRoomDatabase by lazy { MyRoomDatabase.getDatabase(requireContext()) }
then, still in OnViewCreated:
viewModel = ViewModelProvider(this, ViewModelFactory(myRoomDatabase.myDao())).get(ViewModel::class.java)
or, even better, use indexing instead of
.get
viewModel = ViewModelProvider(this, ItemListViewModelFactory(notesRoomDatabase.notesDao()))[ItemListViewModel::class.java]
Upvotes: 0
Reputation: 573
For anyone who found none of the above solutions worked:
Double-check if you allowed Room to execute in the main thread. In this case, the ViewModel is trying to construct in the main thread, while Room's builder rejects it.
Upvotes: 0
Reputation: 61
Fragment or Activity should need @AndroidEntryPoint for instance if you use Dagger/Hil
Upvotes: 1
Reputation: 11457
I fixed the same problem by doing this.
Added the 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)
}
}
}
To
@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)
}
}
}
Upvotes: 1
Reputation: 14066
As somebody said here:
Android room persistent: AppDatabase_Impl does not exist
the solution was:
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"
Upvotes: 14
Reputation: 1
In my case this implementation solved my problem
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
before I implemented this only
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
Upvotes: 0
Reputation: 7220
in, my case I was added private set
in DatabaseClass :|
I removed it.
private var INSTANCE: NoteDatabase? = null
private set
to :
private var INSTANCE: NoteDatabase? = null
this problem take my 2 hours :|||
Upvotes: 1
Reputation: 1752
In my case, I had forgotten to annotate my DatabaseClass class with
@Database(entities = [Book::class], version = 1)
abstract class BookRoomDatabase: RoomDatabase()
Upvotes: 0
Reputation: 469
These 3 things worked for me:
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"
Addingapply plugin: 'kotlin-kapt'
at the top of build.gradle(app) and cleaning the project
Re-installing the application
Upvotes: 1
Reputation: 1835
remove kapt "xxxx.xxx." if you still use that in you gradle.build since it'e been deprecated and add
apply plugin: 'kotlin-kapt'
at the end of your gradle.build for the app module. that fixed my problem in android studio 3.1
Upvotes: 4
Reputation: 4206
Change viewModel = ViewModelProviders.of(activity!!).get(BookmarkViewModel::class.java)
to viewModel = ViewModelProviders.of(this).get(BookmarkViewModel::class.java)
Furthermore don't instantiate the viewModel
to null
. Change it to a lateinit var
this way you don't have to instantiate immediately (but you are telling Kotlin that you will instantiate it before accessing it). You can do this like so: private lateinit var viewModel: BookMarkViewModel
EDIT The root of the problem was that the Room Dependencies
where either not on the same version or annotationProcessor
was used instead of kapt
(kapt
is required when using Kotlin)
Upvotes: 8