Can anytime AppDatabase in Android Room be null?
up vote
0
down vote
favorite
While adding Room Database, it is suggested to use Singleton Design Pattern
Note: You should follow the singleton design pattern when instantiating an AppDatabase object, as each RoomDatabase instance is fairly expensive, and you rarely need access to multiple instances.
So, adding Room Database, following Google example which is written in Java, in will be as below
private var INSTANCE: AppDatabase? = null
fun getInstance(context: Context): AppDatabase? {
if (INSTANCE == null){
synchronized(AppDatabase::class){
INSTANCE = Room.databaseBuilder(context.applicationContext,
AppDatabase::class.java, "app_database")
.build()
}
}
return INSTANCE
}
When I call getInstance, compiler suggests that getInstance can be null. So my question is there any case that getInstance be null and do I have to check if it's null. If not, then how should I instantiate AppDatabase so that getInstance return AppDatabase not AppDatabase? and it fits documentation recommendation?
kotlin singleton
add a comment |
up vote
0
down vote
favorite
While adding Room Database, it is suggested to use Singleton Design Pattern
Note: You should follow the singleton design pattern when instantiating an AppDatabase object, as each RoomDatabase instance is fairly expensive, and you rarely need access to multiple instances.
So, adding Room Database, following Google example which is written in Java, in will be as below
private var INSTANCE: AppDatabase? = null
fun getInstance(context: Context): AppDatabase? {
if (INSTANCE == null){
synchronized(AppDatabase::class){
INSTANCE = Room.databaseBuilder(context.applicationContext,
AppDatabase::class.java, "app_database")
.build()
}
}
return INSTANCE
}
When I call getInstance, compiler suggests that getInstance can be null. So my question is there any case that getInstance be null and do I have to check if it's null. If not, then how should I instantiate AppDatabase so that getInstance return AppDatabase not AppDatabase? and it fits documentation recommendation?
kotlin singleton
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
While adding Room Database, it is suggested to use Singleton Design Pattern
Note: You should follow the singleton design pattern when instantiating an AppDatabase object, as each RoomDatabase instance is fairly expensive, and you rarely need access to multiple instances.
So, adding Room Database, following Google example which is written in Java, in will be as below
private var INSTANCE: AppDatabase? = null
fun getInstance(context: Context): AppDatabase? {
if (INSTANCE == null){
synchronized(AppDatabase::class){
INSTANCE = Room.databaseBuilder(context.applicationContext,
AppDatabase::class.java, "app_database")
.build()
}
}
return INSTANCE
}
When I call getInstance, compiler suggests that getInstance can be null. So my question is there any case that getInstance be null and do I have to check if it's null. If not, then how should I instantiate AppDatabase so that getInstance return AppDatabase not AppDatabase? and it fits documentation recommendation?
kotlin singleton
While adding Room Database, it is suggested to use Singleton Design Pattern
Note: You should follow the singleton design pattern when instantiating an AppDatabase object, as each RoomDatabase instance is fairly expensive, and you rarely need access to multiple instances.
So, adding Room Database, following Google example which is written in Java, in will be as below
private var INSTANCE: AppDatabase? = null
fun getInstance(context: Context): AppDatabase? {
if (INSTANCE == null){
synchronized(AppDatabase::class){
INSTANCE = Room.databaseBuilder(context.applicationContext,
AppDatabase::class.java, "app_database")
.build()
}
}
return INSTANCE
}
When I call getInstance, compiler suggests that getInstance can be null. So my question is there any case that getInstance be null and do I have to check if it's null. If not, then how should I instantiate AppDatabase so that getInstance return AppDatabase not AppDatabase? and it fits documentation recommendation?
kotlin singleton
kotlin singleton
edited 12 hours ago
Jayson Minard
35.5k13103170
35.5k13103170
asked Nov 5 at 6:26
musooff
869
869
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
up vote
1
down vote
accepted
Use something like this to make sure it is not null
object DatabaseSource {
private lateinit var INSTANCE: AppDatabase
fun getInstance(context: Context): AppDatabase {
if (!::INSTANCE.isInitialized) {
synchronized(AppDatabase::class) {
if (!::INSTANCE.isInitialized) {
INSTANCE = Room.databaseBuilder(context.applicationContext,
AppDatabase::class.java,
"app_database").build()
}
}
}
return INSTANCE
}
}
Call it with:
val db = DatabaseSource.getInstance(context)
And this will never be null so you no longer have that issue.
I added double locking to be safer for thread safety on the getInstance() call.
But really you should be using dependency injection with singletons to avoid this passed in dependency of context and this manual creation/locking. You'll have to have the context available everywhere which is a bad pattern.
This also acts as an answer to your other post which is apparently a duplicate of this one.
That indeed was what I am looking for. But how would I pass thecontexthere? Since I am creating INSTANCE in mycompanion object, it's not a good practice to havecontextinside static fields. Looking google sample, I see that they usealsowhich works perfectly. What do you say?
– musooff
2 hours ago
Are you using dependency injection? because this seems like it should be injected as a singleton, and the context should be made available for injection as well.
– Jayson Minard
1 hour ago
1
The comment about not usinglateinitthere is not universally a valid comment. It is fine in any context where you KNOW the lifecycle gaurantees it will be instantiated before use. Here the only way to access it is by a method that guarantees it is valid. So you are fine. The other comment is not relevant without this context.
– Jayson Minard
1 hour ago
1
I saw your proposed edit of volatile, but since this is only modified under lock, and we are checking if assigned which is I believe a bit field that would not be partially set. You can add it if you want, but not sure it is really what you want and will just add more contention on accessing it.
– Jayson Minard
1 hour ago
1
Let's not add things we see in other posts without reason.
– Jayson Minard
1 hour ago
|
show 4 more comments
up vote
-1
down vote
In this code, you already check for the null situation of your AppDatabase instance:
if (INSTANCE == null){...}
Actually when you request an instance of your AppDatabase then this above part will check that is there any instance of that available or not. And if you don't have any instance it will create a new instance for you then.
This class is a Singleton class.
But before your first request to create an instance for AppDatabase it's null.
Hope this helped you.
Yeah indeedif (INSTANCE == null){...}checks if not null then creates. My question was can it be still benullwhile creating (insideif). If it doesn't, then there is no need to haveAppDatabase?as a return type ofgetInstanceWho my question was, if it's nevernullthen how can I instantiateAppDatabaseand havefun getInstance(context: Context) : AppDatabase{...}
– musooff
Nov 5 at 7:08
No, I mentioned that in my answer. When you try to get an instance of that you get an instance of that. But this class doesn't create an instance each time you want an instance for you and if there is an existing instance it will give it to you. otherwise, this class will create a new instance for you.
– Ehsan
Nov 5 at 7:13
Then how can I creategetInstancemethod withAppDatabasereturn type instead ofAppDatabse?
– musooff
Nov 5 at 7:15
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
Use something like this to make sure it is not null
object DatabaseSource {
private lateinit var INSTANCE: AppDatabase
fun getInstance(context: Context): AppDatabase {
if (!::INSTANCE.isInitialized) {
synchronized(AppDatabase::class) {
if (!::INSTANCE.isInitialized) {
INSTANCE = Room.databaseBuilder(context.applicationContext,
AppDatabase::class.java,
"app_database").build()
}
}
}
return INSTANCE
}
}
Call it with:
val db = DatabaseSource.getInstance(context)
And this will never be null so you no longer have that issue.
I added double locking to be safer for thread safety on the getInstance() call.
But really you should be using dependency injection with singletons to avoid this passed in dependency of context and this manual creation/locking. You'll have to have the context available everywhere which is a bad pattern.
This also acts as an answer to your other post which is apparently a duplicate of this one.
That indeed was what I am looking for. But how would I pass thecontexthere? Since I am creating INSTANCE in mycompanion object, it's not a good practice to havecontextinside static fields. Looking google sample, I see that they usealsowhich works perfectly. What do you say?
– musooff
2 hours ago
Are you using dependency injection? because this seems like it should be injected as a singleton, and the context should be made available for injection as well.
– Jayson Minard
1 hour ago
1
The comment about not usinglateinitthere is not universally a valid comment. It is fine in any context where you KNOW the lifecycle gaurantees it will be instantiated before use. Here the only way to access it is by a method that guarantees it is valid. So you are fine. The other comment is not relevant without this context.
– Jayson Minard
1 hour ago
1
I saw your proposed edit of volatile, but since this is only modified under lock, and we are checking if assigned which is I believe a bit field that would not be partially set. You can add it if you want, but not sure it is really what you want and will just add more contention on accessing it.
– Jayson Minard
1 hour ago
1
Let's not add things we see in other posts without reason.
– Jayson Minard
1 hour ago
|
show 4 more comments
up vote
1
down vote
accepted
Use something like this to make sure it is not null
object DatabaseSource {
private lateinit var INSTANCE: AppDatabase
fun getInstance(context: Context): AppDatabase {
if (!::INSTANCE.isInitialized) {
synchronized(AppDatabase::class) {
if (!::INSTANCE.isInitialized) {
INSTANCE = Room.databaseBuilder(context.applicationContext,
AppDatabase::class.java,
"app_database").build()
}
}
}
return INSTANCE
}
}
Call it with:
val db = DatabaseSource.getInstance(context)
And this will never be null so you no longer have that issue.
I added double locking to be safer for thread safety on the getInstance() call.
But really you should be using dependency injection with singletons to avoid this passed in dependency of context and this manual creation/locking. You'll have to have the context available everywhere which is a bad pattern.
This also acts as an answer to your other post which is apparently a duplicate of this one.
That indeed was what I am looking for. But how would I pass thecontexthere? Since I am creating INSTANCE in mycompanion object, it's not a good practice to havecontextinside static fields. Looking google sample, I see that they usealsowhich works perfectly. What do you say?
– musooff
2 hours ago
Are you using dependency injection? because this seems like it should be injected as a singleton, and the context should be made available for injection as well.
– Jayson Minard
1 hour ago
1
The comment about not usinglateinitthere is not universally a valid comment. It is fine in any context where you KNOW the lifecycle gaurantees it will be instantiated before use. Here the only way to access it is by a method that guarantees it is valid. So you are fine. The other comment is not relevant without this context.
– Jayson Minard
1 hour ago
1
I saw your proposed edit of volatile, but since this is only modified under lock, and we are checking if assigned which is I believe a bit field that would not be partially set. You can add it if you want, but not sure it is really what you want and will just add more contention on accessing it.
– Jayson Minard
1 hour ago
1
Let's not add things we see in other posts without reason.
– Jayson Minard
1 hour ago
|
show 4 more comments
up vote
1
down vote
accepted
up vote
1
down vote
accepted
Use something like this to make sure it is not null
object DatabaseSource {
private lateinit var INSTANCE: AppDatabase
fun getInstance(context: Context): AppDatabase {
if (!::INSTANCE.isInitialized) {
synchronized(AppDatabase::class) {
if (!::INSTANCE.isInitialized) {
INSTANCE = Room.databaseBuilder(context.applicationContext,
AppDatabase::class.java,
"app_database").build()
}
}
}
return INSTANCE
}
}
Call it with:
val db = DatabaseSource.getInstance(context)
And this will never be null so you no longer have that issue.
I added double locking to be safer for thread safety on the getInstance() call.
But really you should be using dependency injection with singletons to avoid this passed in dependency of context and this manual creation/locking. You'll have to have the context available everywhere which is a bad pattern.
This also acts as an answer to your other post which is apparently a duplicate of this one.
Use something like this to make sure it is not null
object DatabaseSource {
private lateinit var INSTANCE: AppDatabase
fun getInstance(context: Context): AppDatabase {
if (!::INSTANCE.isInitialized) {
synchronized(AppDatabase::class) {
if (!::INSTANCE.isInitialized) {
INSTANCE = Room.databaseBuilder(context.applicationContext,
AppDatabase::class.java,
"app_database").build()
}
}
}
return INSTANCE
}
}
Call it with:
val db = DatabaseSource.getInstance(context)
And this will never be null so you no longer have that issue.
I added double locking to be safer for thread safety on the getInstance() call.
But really you should be using dependency injection with singletons to avoid this passed in dependency of context and this manual creation/locking. You'll have to have the context available everywhere which is a bad pattern.
This also acts as an answer to your other post which is apparently a duplicate of this one.
edited 1 hour ago
answered 10 hours ago
Jayson Minard
35.5k13103170
35.5k13103170
That indeed was what I am looking for. But how would I pass thecontexthere? Since I am creating INSTANCE in mycompanion object, it's not a good practice to havecontextinside static fields. Looking google sample, I see that they usealsowhich works perfectly. What do you say?
– musooff
2 hours ago
Are you using dependency injection? because this seems like it should be injected as a singleton, and the context should be made available for injection as well.
– Jayson Minard
1 hour ago
1
The comment about not usinglateinitthere is not universally a valid comment. It is fine in any context where you KNOW the lifecycle gaurantees it will be instantiated before use. Here the only way to access it is by a method that guarantees it is valid. So you are fine. The other comment is not relevant without this context.
– Jayson Minard
1 hour ago
1
I saw your proposed edit of volatile, but since this is only modified under lock, and we are checking if assigned which is I believe a bit field that would not be partially set. You can add it if you want, but not sure it is really what you want and will just add more contention on accessing it.
– Jayson Minard
1 hour ago
1
Let's not add things we see in other posts without reason.
– Jayson Minard
1 hour ago
|
show 4 more comments
That indeed was what I am looking for. But how would I pass thecontexthere? Since I am creating INSTANCE in mycompanion object, it's not a good practice to havecontextinside static fields. Looking google sample, I see that they usealsowhich works perfectly. What do you say?
– musooff
2 hours ago
Are you using dependency injection? because this seems like it should be injected as a singleton, and the context should be made available for injection as well.
– Jayson Minard
1 hour ago
1
The comment about not usinglateinitthere is not universally a valid comment. It is fine in any context where you KNOW the lifecycle gaurantees it will be instantiated before use. Here the only way to access it is by a method that guarantees it is valid. So you are fine. The other comment is not relevant without this context.
– Jayson Minard
1 hour ago
1
I saw your proposed edit of volatile, but since this is only modified under lock, and we are checking if assigned which is I believe a bit field that would not be partially set. You can add it if you want, but not sure it is really what you want and will just add more contention on accessing it.
– Jayson Minard
1 hour ago
1
Let's not add things we see in other posts without reason.
– Jayson Minard
1 hour ago
That indeed was what I am looking for. But how would I pass the
context here? Since I am creating INSTANCE in my companion object, it's not a good practice to have context inside static fields. Looking google sample, I see that they use also which works perfectly. What do you say?– musooff
2 hours ago
That indeed was what I am looking for. But how would I pass the
context here? Since I am creating INSTANCE in my companion object, it's not a good practice to have context inside static fields. Looking google sample, I see that they use also which works perfectly. What do you say?– musooff
2 hours ago
Are you using dependency injection? because this seems like it should be injected as a singleton, and the context should be made available for injection as well.
– Jayson Minard
1 hour ago
Are you using dependency injection? because this seems like it should be injected as a singleton, and the context should be made available for injection as well.
– Jayson Minard
1 hour ago
1
1
The comment about not using
lateinit there is not universally a valid comment. It is fine in any context where you KNOW the lifecycle gaurantees it will be instantiated before use. Here the only way to access it is by a method that guarantees it is valid. So you are fine. The other comment is not relevant without this context.– Jayson Minard
1 hour ago
The comment about not using
lateinit there is not universally a valid comment. It is fine in any context where you KNOW the lifecycle gaurantees it will be instantiated before use. Here the only way to access it is by a method that guarantees it is valid. So you are fine. The other comment is not relevant without this context.– Jayson Minard
1 hour ago
1
1
I saw your proposed edit of volatile, but since this is only modified under lock, and we are checking if assigned which is I believe a bit field that would not be partially set. You can add it if you want, but not sure it is really what you want and will just add more contention on accessing it.
– Jayson Minard
1 hour ago
I saw your proposed edit of volatile, but since this is only modified under lock, and we are checking if assigned which is I believe a bit field that would not be partially set. You can add it if you want, but not sure it is really what you want and will just add more contention on accessing it.
– Jayson Minard
1 hour ago
1
1
Let's not add things we see in other posts without reason.
– Jayson Minard
1 hour ago
Let's not add things we see in other posts without reason.
– Jayson Minard
1 hour ago
|
show 4 more comments
up vote
-1
down vote
In this code, you already check for the null situation of your AppDatabase instance:
if (INSTANCE == null){...}
Actually when you request an instance of your AppDatabase then this above part will check that is there any instance of that available or not. And if you don't have any instance it will create a new instance for you then.
This class is a Singleton class.
But before your first request to create an instance for AppDatabase it's null.
Hope this helped you.
Yeah indeedif (INSTANCE == null){...}checks if not null then creates. My question was can it be still benullwhile creating (insideif). If it doesn't, then there is no need to haveAppDatabase?as a return type ofgetInstanceWho my question was, if it's nevernullthen how can I instantiateAppDatabaseand havefun getInstance(context: Context) : AppDatabase{...}
– musooff
Nov 5 at 7:08
No, I mentioned that in my answer. When you try to get an instance of that you get an instance of that. But this class doesn't create an instance each time you want an instance for you and if there is an existing instance it will give it to you. otherwise, this class will create a new instance for you.
– Ehsan
Nov 5 at 7:13
Then how can I creategetInstancemethod withAppDatabasereturn type instead ofAppDatabse?
– musooff
Nov 5 at 7:15
add a comment |
up vote
-1
down vote
In this code, you already check for the null situation of your AppDatabase instance:
if (INSTANCE == null){...}
Actually when you request an instance of your AppDatabase then this above part will check that is there any instance of that available or not. And if you don't have any instance it will create a new instance for you then.
This class is a Singleton class.
But before your first request to create an instance for AppDatabase it's null.
Hope this helped you.
Yeah indeedif (INSTANCE == null){...}checks if not null then creates. My question was can it be still benullwhile creating (insideif). If it doesn't, then there is no need to haveAppDatabase?as a return type ofgetInstanceWho my question was, if it's nevernullthen how can I instantiateAppDatabaseand havefun getInstance(context: Context) : AppDatabase{...}
– musooff
Nov 5 at 7:08
No, I mentioned that in my answer. When you try to get an instance of that you get an instance of that. But this class doesn't create an instance each time you want an instance for you and if there is an existing instance it will give it to you. otherwise, this class will create a new instance for you.
– Ehsan
Nov 5 at 7:13
Then how can I creategetInstancemethod withAppDatabasereturn type instead ofAppDatabse?
– musooff
Nov 5 at 7:15
add a comment |
up vote
-1
down vote
up vote
-1
down vote
In this code, you already check for the null situation of your AppDatabase instance:
if (INSTANCE == null){...}
Actually when you request an instance of your AppDatabase then this above part will check that is there any instance of that available or not. And if you don't have any instance it will create a new instance for you then.
This class is a Singleton class.
But before your first request to create an instance for AppDatabase it's null.
Hope this helped you.
In this code, you already check for the null situation of your AppDatabase instance:
if (INSTANCE == null){...}
Actually when you request an instance of your AppDatabase then this above part will check that is there any instance of that available or not. And if you don't have any instance it will create a new instance for you then.
This class is a Singleton class.
But before your first request to create an instance for AppDatabase it's null.
Hope this helped you.
answered Nov 5 at 7:00
Ehsan
399522
399522
Yeah indeedif (INSTANCE == null){...}checks if not null then creates. My question was can it be still benullwhile creating (insideif). If it doesn't, then there is no need to haveAppDatabase?as a return type ofgetInstanceWho my question was, if it's nevernullthen how can I instantiateAppDatabaseand havefun getInstance(context: Context) : AppDatabase{...}
– musooff
Nov 5 at 7:08
No, I mentioned that in my answer. When you try to get an instance of that you get an instance of that. But this class doesn't create an instance each time you want an instance for you and if there is an existing instance it will give it to you. otherwise, this class will create a new instance for you.
– Ehsan
Nov 5 at 7:13
Then how can I creategetInstancemethod withAppDatabasereturn type instead ofAppDatabse?
– musooff
Nov 5 at 7:15
add a comment |
Yeah indeedif (INSTANCE == null){...}checks if not null then creates. My question was can it be still benullwhile creating (insideif). If it doesn't, then there is no need to haveAppDatabase?as a return type ofgetInstanceWho my question was, if it's nevernullthen how can I instantiateAppDatabaseand havefun getInstance(context: Context) : AppDatabase{...}
– musooff
Nov 5 at 7:08
No, I mentioned that in my answer. When you try to get an instance of that you get an instance of that. But this class doesn't create an instance each time you want an instance for you and if there is an existing instance it will give it to you. otherwise, this class will create a new instance for you.
– Ehsan
Nov 5 at 7:13
Then how can I creategetInstancemethod withAppDatabasereturn type instead ofAppDatabse?
– musooff
Nov 5 at 7:15
Yeah indeed
if (INSTANCE == null){...} checks if not null then creates. My question was can it be still be null while creating (inside if). If it doesn't, then there is no need to have AppDatabase? as a return type of getInstance Who my question was, if it's never null then how can I instantiate AppDatabase and have fun getInstance(context: Context) : AppDatabase{...}– musooff
Nov 5 at 7:08
Yeah indeed
if (INSTANCE == null){...} checks if not null then creates. My question was can it be still be null while creating (inside if). If it doesn't, then there is no need to have AppDatabase? as a return type of getInstance Who my question was, if it's never null then how can I instantiate AppDatabase and have fun getInstance(context: Context) : AppDatabase{...}– musooff
Nov 5 at 7:08
No, I mentioned that in my answer. When you try to get an instance of that you get an instance of that. But this class doesn't create an instance each time you want an instance for you and if there is an existing instance it will give it to you. otherwise, this class will create a new instance for you.
– Ehsan
Nov 5 at 7:13
No, I mentioned that in my answer. When you try to get an instance of that you get an instance of that. But this class doesn't create an instance each time you want an instance for you and if there is an existing instance it will give it to you. otherwise, this class will create a new instance for you.
– Ehsan
Nov 5 at 7:13
Then how can I create
getInstance method with AppDatabase return type instead of AppDatabse?– musooff
Nov 5 at 7:15
Then how can I create
getInstance method with AppDatabase return type instead of AppDatabse?– musooff
Nov 5 at 7:15
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53149350%2fcan-anytime-appdatabase-in-android-room-be-null%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
