Android Room - Avoid Passing Context Into Singleton
Solution 1:
You can initialize your database and save an instance of it into your Application class something like this.
publicclassMyApplicationextendsApplication {
public AppDatabase database;
@OverridepublicvoidonCreate() {
super.onCreate();
database = AppDatabase.getInstance(this)
}
}
Late you can access your reference like
((MyApplication)activity).dabase
Hope this would help.
Solution 2:
You can instantiate the db then lock the instance.
Also, calling context.applicationContext
return the context of the single, global Application object of the current process. This Context's lifecycle is separate from the current context
, that is tied to the lifetime of the process rather than the current component.
/**
* The Room Database that contains the item table.
*/@Database(entities = arrayOf(Item::class), version = 1, exportSchema = false)
abstractclassItemDb : RoomDatabase() {
abstractfunitemDao(): ItemDao
companionobject {
privatevar INSTANCE: ItemDb? = nullprivateval lock = Any()
@JvmStaticfungetInstance(context: Context): ItemDb {
// When calling this instance concurrently from multiple threads we're in serious trouble:// So we use this method, 'synchronized' to lock the instance
synchronized(lock) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.applicationContext, ItemDb::class.java, "items.db").build()
}
return INSTANCE!!
}
}
}
}
Solution 3:
@Database(entities = {Category.class, News.class}, version = 1)
publicabstractclassAppDatabaseextendsRoomDatabase {
privatestatic final String DB_NAME = "database.db";
privatestatic AppDatabase instance;
publicabstract CategoryDao categoryDao();
publicabstract NewsDao newsDao();
privateAppDatabase () {}
// Use this to call on any placepublicstatic AppDatabase getInstance() {
return instance;
}
// Use once to Create and setup the objectpublicstatic AppDatabase setInstance(Context context) {
if (instance == null) {
synchronized (AppDatabase.class) {
if (instance == null) {
instance = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class, DB_NAME).build();
}
}
}
return instance;
}
}
// Second you need to set instance on Application Class which create and make your DB //Ready for Use Before anything performpublicclassMyApplicationextendsApplication {
@Override
publicvoidonCreate() {
super.onCreate();
AppDatabase.setInstance(this)
}
}
To Use
//Need to call
AppDatabase.getInstance().categoryDao();
Solution 4:
There is a lot of things to consider here. It totally depends on your use case - because you might have your app to touch the db only on single thread so you do not need any synchronization there at all.
However if you want some complementary solution (might also call it "overkill" in situations I mentioned above), please check https://github.com/android/architecture-components-samples which I paste here for reference only (discussion about this approach is here:
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/package com.example.android.observability.persistence
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import android.content.Context
/**
* The Room database that contains the Users table
*/@Database(entities = [User::class], version = 1)abstractclassUsersDatabase : RoomDatabase() {
abstractfunuserDao(): UserDao
companionobject {
@Volatileprivatevar INSTANCE: UsersDatabase? = nullfungetInstance(context: Context): UsersDatabase =
INSTANCE ?: synchronized(this) {
INSTANCE ?: buildDatabase(context).also { INSTANCE = it }
}
privatefunbuildDatabase(context: Context) =
Room.databaseBuilder(context.applicationContext,
UsersDatabase::class.java, "Sample.db")
.build()
}
}
In general - you might want to take a look at Kotlin double checking singleton and/or Java Double-Checked Locking with Singleton.
Solution 5:
You could use this function
publicclassDatabaseClient {
private Context mCtx;
privatestatic DatabaseClient mInstance;
//our app database objectprivatefinal AppDatabase appDatabase;
privateDatabaseClient(Context mCtx){
this.mCtx = mCtx;
//creating the app database with Room database builder//alldata is the name of the database
appDatabase = Room.databaseBuilder(mCtx, AppDatabase.class, "alldata").build();
}
publicstaticsynchronized DatabaseClient getInstance(Context mCtx){
if (mInstance == null) {
mInstance = newDatabaseClient(mCtx);
}
return mInstance;
}
public AppDatabase getAppDatabase(){ return appDatabase; }
}
And use this to call getInstance()
DatabaseClient.getInstance(MainActivity.this).getAppDatabase().memberDao();
AppDatabase class look like this:
@Database(entities = {Member.class} , version = 1, exportSchema = false)
publicabstractclassAppDatabaseextendsRoomDatabase {
publicabstract MemberDao memberDao();
}
Post a Comment for "Android Room - Avoid Passing Context Into Singleton"