I'm learning how to implement Room from Android jetpack into my android studio app but a message saying "not enough information to infer type variable T" keeps showing up when I try to use Room.databaseBuilder
this is my code:
// if there is no instance, we create a new one
synchronized(this){
val instance = Room.databaseBuilder(
context.applicationContext,
UserDatabase::class.java,
"user_database"
).build()
INSTANCE = instance
return instance
}
I can add the surrounding function or the whole file if that helps. Thanks in advance!
I'm not sure but this is the problem i faced as well and i solved it by downgrading 'implementation 'androidx.core:core-ktx:1.6.0' to 'implementation 'androidx.core:core-ktx:1.5.0' in the build.gradle file
If you have for example:-
#Database(entities = [Objects::class], version = 1)
abstract class MyDatabase: RoomDatabase() {
abstract fun getAllDao(): AllDAO
companion object {
var INSTANCE: MyDatabase? = null
fun getInstance(context: Context): MyDatabase {
synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
UserDatabase::class.java,
"user_database"
).build()
INSTANCE = instance
return instance
}
}
}
}
The you get the not enough information to infer type variable T e.g. :-
Changing to use the same class then all is fine, e.g.
#Database(entities = [Objects::class], version = 1)
abstract class UserDatabase: RoomDatabase() { //<<<<<<<<<< CHANGED
abstract fun getAllDao(): AllDAO
companion object {
var INSTANCE: UserDatabase? = null //<<<<<<<<<< CHANGED
fun getInstance(context: Context): UserDatabase { //<<<<<<<<<< CHANGED
if (INSTANCE == null) {
synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
UserDatabase::class.java, //<<<<<<<<<< AS WAS/ MATCHES
"user_database"
)
.allowMainThreadQueries() /*<<<<<<<<<< ADDED FOR convenience brevity */
.build()
INSTANCE = instance
return instance
}
}
return INSTANCE!!
}
}
}
Note run on the main thread to just demonstrate that the above runs (see following example run)
As a test/proof consider :-
class MainActivity : AppCompatActivity() {
lateinit var db1: UserDatabase
lateinit var dao1: AllDAO
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
db1 = UserDatabase.getInstance(this) //<<<<<<<<<< GET INSTANCE
dao1 = db1.getAllDao()
dao1.getObjects(listOf("nothing to get as no data has been added, just forcing open/create of database")) //<<<<<<<<< as per text USE/OPEN/CREATE Database(first use, once created database is opened as it persists)
// existing app used ....
The result (ignore TheDatabase as existing code was used for the answer) :-
Related
I stuck at this problem
class InventoryApplication : Application() {
val database: ItemDatabase by lazy { ItemDatabase.getDatabase(this) }
}
Error class
Code image
I had the same issue, i was able to resolve it by going to the ItemRoomDatabase.kt file, change the INSTANCE variable in the companion object, to return a non-null type ItemRoomDatabase? and the getDataBase() function to return a type ItemRoomDatabase, rather than a RoomDatabase return type as requested in the codelab example.
Your final code in the ItemRoomDatabase.kt file should look something like this:
#Database(entities = [Item::class], version = 1, exportSchema = false)
abstract class ItemRoomDatabase : RoomDatabase() {
abstract fun itemDao(): ItemDao
companion object {
#Volatile
private var INSTANCE: ItemRoomDatabase? = null
fun getDatabase(context: Context): ItemRoomDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
ItemRoomDatabase::class.java,
"item_database"
)
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
instance
}
}
}
}
Hi everyone today I try to use the room database but I can't because of #Violate annotation, not fount.
even I can't build my own database with databaseBuilder , I got Unresolved reference: java error
for PersonDatabase::class.java
#Database(entities = [person::class],version = 1,exportSchema = false)
abstract class PersonDatabase:RoomDatabase() {
abstract fun personDao():PersonDao
companion object {
private var INSTANCE: PersonDatabase? = null
fun getDatabase(context: Context): PersonDatabase {
// if the INSTANCE is not null, then return it,
// if it is, then create the database
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
PersonDatabase::class.java,
"word_database"
).build()
INSTANCE = instance
// return instance
instance
}
}
}
jetbrains.kotlin:kotlin-stdlib-jdk7 not added automatically in a project I just add this libray to gradle and then fix my problem.
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.32"
I'm new to kotlin and room, after following an official android guide i ended up by setting my entities, my DAO and my Database,
the issue is i can't understand on how can i use the function from dao in my fragment...
So my Database looks like this:
#Database(entities = [Articolo::class], version = 1, exportSchema = false)
abstract class ArticoliDatabase: RoomDatabase() {
abstract val articoliDao: ArticoliDAO
companion object {
#Volatile
private var INSTANCE: ArticoliDatabase? = null
fun getInstance(context: Context): ArticoliDatabase {
synchronized(this) {
var instance = INSTANCE
if (instance == null) {
instance = Room.databaseBuilder(
context.applicationContext,
ArticoliDatabase::class.java,
"pdt_database"
)
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
}
return instance
}
}
}
}
Then in my fragment i've done the following:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
...
db = ArticoliDatabase.getInstance(requireContext())
}
And in the same fragment in my click function i'm doing the following to insert
db.articoliDao.insert(Articolo(barcode, qta))
But the app even doesn't build correctly by saying that
ArticoliDatabase_Impl does not exist
So what is the right way to initialize and use the room database with kotlin?
I just need to simply insert and show the data from the db in a listview that's it..
The problem is in the build.gradle file. Can you please check if your import of room library looks like:
annotationProcessor "androidx.room:room-compiler:$room"
Since you are using kotlin, you must use kapt for annotation processor dependencies
This is how your room dependencies should look like
implementation "androidx.room:room-runtime:$room"
implementation "androidx.room:room-ktx:$room"
kapt "androidx.room:room-compiler:$room"
Create Database class AppDatabase and Dao Interface
AppDatabase
#Database(
entities = [User::class, Quote::class],
version = 1
)
abstract class AppDatabase : RoomDatabase() {
abstract fun getUserDao(): UserDao
abstract fun getQuoteDao(): QuoteDao
companion object {
#Volatile
private var instance: AppDatabase? = null
private val LOCK = Any()
operator fun invoke(context: Context) = instance ?: synchronized(LOCK) {
instance ?: buildDatabase(context).also {
instance = it
}
}
private fun buildDatabase(context: Context) =
Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"MyDatabase.db"
).build()
}
}
Dao Interface Here
#Dao
interface UserDao{
#Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun upsert(user: User) : Long
#Query("SELECT * FROM user WHERE uid = $CURRENT_USER_ID")
fun getuser() : LiveData<User>
}
Now in your fragment or activity you can insert and get user data by just craeting an object of dabase class as given below
private val db: AppDatabase
db=AppDatabase(context)
fun saveUser(user: User) = db.getUserDao().upsert(user)
fun getUser() = db.getUserDao().getuser()
I am writing an android application following the Android Architectural Components design.
This is the database class:
#Database(entities = [Authentication::class],version = 1, exportSchema = false)
abstract class AuthDB: RoomDatabase(){
abstract val authenticationDao :AuthenticationAccessObject
companion object{
#Volatile
private var INSTANCE: AuthDB? = null
fun getInstance(context: Context): AuthDB {
synchronized(this){
var instance = INSTANCE
if(instance == null){
instance = Room.databaseBuilder(
context.applicationContext,
AuthDB::class.java,
"authentication_database"
)
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
}
return instance
}
}
}
}
This is the Repository class:
class Repository2() {
private val database: AuthDB = AuthDB.getInstance(context = getContext())
private val daoA = database.authenticationDao
//Function to register a new user to system
fun insertAuth(userData: Any){
if (userData is Authentication){
daoA.insertAuth(userData)
} else {
throw IllegalArgumentException()
}
}
My target is that when I write the ViewModel, I want to create instance of Repository2 and call functions for example as follows:
var repo = Repository2()
repo.insertAuth(authenticationObject)
I am having problem giving context to getInstance in the Repository. The context should be such that when I instantiate the repository, it should automatically get the application context and instantiate the AuthDB database.
Until now,
I have tried to create Application class that extends Application and tried to get application context from there as suggested in another stackoverflow solution
Instantiated database with following code and failed:
private val database: AuthDB = AuthDB.getInstance(context = getContext())
Instantiated database with following code and failed:
private val database: AuthDB = AuthDB.getInstance(Application.getApplicationContext())
I have been trying for about two days now and nothing is working, I believe I am missing a major concept here. I hope someone can nudge me in the right direction?
Kind regards,
Salik
try this solution
EDIT:-
use this way to your RoomDatabase
#Database(
entities = [CompaniesModel::class, CompaniesHomeModel::class, UserPoint::class, Image::class, Offer::class, Rewords::class, BranchModel::class, PointsModel::class, RedeemModel::class, MainData::class, SubData::class],
version = 15)
abstract class DataBase : RoomDatabase() {
abstract fun homeDao(): HomeDao
abstract fun menuDao(): MenuDao
abstract fun companiesDao(): CompaniesListDao
abstract fun branchesDao(): BranchesDao
companion object {
#Volatile
private var databaseInstance: DataBase? = null
fun getDatabaseInstance(mContext: Context): DataBase =
databaseInstance ?: synchronized(this) {
databaseInstance ?: buildDatabaseInstance(mContext).also {
databaseInstance = it
}
}
private fun buildDatabaseInstance(mContext: Context) =
Room.databaseBuilder(mContext, DataBase::class.java, "crm")
.fallbackToDestructiveMigration()
.allowMainThreadQueries()
.build()
}
}
and for the getContext(), use Application() class like this:
class App : Application() {
override fun onCreate() {
super.onCreate()
instance = this
}
companion object {
lateinit var instance: App
}
}
and pass it like this
private val database: AuthDB = AuthDB.getInstance(app.instance)
I'm trying to use Room. I get this error (in runtime):
java.lang.RuntimeException: cannot find implementation for
com.easythings.booky.database.BookyDatabase. BookyDatabase_Impl does
not exist
My BookyDatabase class:
#Database(entities = [Book::class, Chapter::class], version = 1)
abstract class BookyDatabase : RoomDatabase() {
abstract val bookDao: BookDao
abstract val chapterDao: ChapterDao
companion object {
#Volatile
private var _databaseInstance: BookyDatabase? = null
fun getDatabase(context: Context): BookyDatabase {
if (_databaseInstance == null)
synchronized(BookyDatabase::class.java) {
if (_databaseInstance == null)
_databaseInstance = Room.databaseBuilder(
context.applicationContext,
BookyDatabase::class.java,
"booky_database"
)
.fallbackToDestructiveMigration()
.build()
}
return _databaseInstance!!
}
}
}
I don't understand what is wrong.
The BookyDatabase_Impl most likely isn't being generated ...
a) because you lack the annotations.
b) because you lack an annotation processor.
see Database or Defining data using Room entities.