hey there so i'm having a small design issue where I have a flow of data coming from my RoomDb but when I first open the app the RoomDd does not instantiate till I open the activity where I am using it so this causes me to get a null data object followed by an object with the data. I just wanted to know if there was a way for me to open up my RoomDb as soon as I open my Application
I am using Dagger Hilt for Injection
output of data on opening activity
please do let me know if there is anymore info I can provide about this problem
thanks!
I recommand you to follow this codelab from the documentation, which shows how to use Room properly.
You will initialize your ViewModel class inside the activities where you want to access your data,
private ViewModel mViewModel;
give it a value inside the onCreate() method of your activity
mViewModel = new ViewModelProvider(this).get(ViewModel.class);
and the ViewModel will call the getDatabase() method below inside its constructor
static RoomDatabase getDatabase(final Context context) {
if (INSTANCE == null) {
synchronized (RoomDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
RoomDatabase.class, "database")
// Prepopulate from a .db file
.createFromAsset("database/database.db")
// Or from code --> check this step from the codelab
// https://developer.android.com/codelabs/android-room-with-a-view#12
// .addCallback(sRoomDatabaseCallback)
.build();
}
}
}
return INSTANCE;
}
Related
It is thread safe to use single instance of database by all activities of my Applications. And if i do so, when should i close the database connection.
Please recommend the right method to use SqliteOpenHelper .
I've been using an approach I found in an online course and haven't had a slightest issue with it. Just put a synchronized keyword for your database instance so that multiple threads could manage it at the same time. This is what I am using:
synchronized static AppDatabase getInstance(Context context) {
if (instance == null) {
instance = new AppDatabase(context.getApplicationContext());
}
return (instance);
}
I use Room to save my data :
#Database(entities = {Colis.class}, version = 1)
public abstract class ChloeDatabase extends RoomDatabase {
public abstract ColisDao colisDao();
private static volatile ChloeDatabase INSTANCE;
public static ChloeDatabase getDatabase(final Context context) {
if (INSTANCE == null) {
synchronized (ChloeDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
ChloeDatabase.class, "my_database")
// Wipes and rebuilds instead of migrating if no Migration object.
// Migration is not part of this codelab.
.fallbackToDestructiveMigration()
.build();
}
}
}
return INSTANCE;
}
}
But what I really want is to save data in sdcard in sqlite format (so that I can export my_database.sqlite file in /sdcard/Android/data/my_package/my_database.sqlite, whether it's on a emulator or a real device).
I searched for a whole day on Internet without finding the solution.
Could anyone help me with this issure ?
You can extract your database, after you have connected your emulator or physical device like this:
Go to DeviceFileExplorer
data
data
find you app name
databases
and than find your database. It is the file with the larger size . Than drop it to your phone storage. After that if you want to check your data in your computer, you can perform queries in Sqlite syntax with this little toy here .
I created a class that uses 1 SOUNDPOOL to play musical notes. The problem is that there are a lot of notes and thus loading takes too long. I'd like to know if it was possible to use a single instance of the class in several activities to avoid having to recreate my music player each time.
have you heard of Singleton Design Pattern? Have a look at Wikipedia. Following this design pattern will ensure you have ever created only one instance of the class and all other classes will reuse this only instance.
Use Singletone design pattern
public class ClassicSingleton {
private static ClassicSingleton instance = null;
protected ClassicSingleton() {
// Exists only to defeat instantiation.
}
public static ClassicSingleton getInstance() {
if(instance == null) {
instance = new ClassicSingleton();
}
return instance;
}
}
As the other said, use Singleton. In fact, Android provides a Singleton object already, which is the Application. You may want to use that.
Is there a way to change what database an SQLiteOpenHelper object uses without having to force every class that uses the helper to replace their instance of the class?
The reason why I'm changing the database is because I have some live data and some offline data in two separate databases with identical table structures. I update the offline data and then swap them, allowing me to lock the offline database on big inserts.
You must use the singleton pattern to acces to your database with only one instance
it's look like
public class SingletonDemo {
private static SingletonDemo instance = null;
private SingletonDemo() { // do what you want here}
public static SingletonDemo getInstance() {
if (instance == null) {
synchronized (SingletonDemo.class) {
if (instance == null) {
instance = new SingletonDemo();
}
}
}
return instance;
}
...
// Add all the class function you need here
}
This is thread safe and can be use every where you need.
I'm dealing with fragments.
I have an Activity and different fragments.
Each fragment need the access to a Class(call it X) that allow it to access a database, but, because I have a lot of fragments, I don't want to create a different instance of the Class X in every fragment as I think it will require lots of memory.
So how can I do?
I wrote something like this (with a getter), but it doesn't work!
public class MyActivity {
private ClassX classx;
.....
public ClassX getClassX() {
return classx;
}
.....
}
But than, how can I call it from the fragment?
From the fragment call your activity's method
((MyActivity ) getActivity()).getClassX() ;
This is a little bit more of a Java question and android.
If you looking at accessing the database, look at creating a database singleton.
So something like:
public class Database {
// This starts off null
private static Database mInstance;
/**
* Singleton method, will return the same object each time.
*/
public static final Database getInstance() {
// First time this method is called by Database.getInstance() from anywhere
// in your App. It will create this Object once.
if(mInstance == null) mInstance = new Database();
// Returns the created object from a statically assigned field so its never
// destroyed until you do it manually.
return mInstance;
}
//Private constructor to stop you from creating this object by accident
private Database(){
//Init db object
}
}
So then from your fragments and activities you can then place the following field in your class's (Better use use a base activity and fragment to save you repeating code).
public abstract class BaseFragment extends Fragment {
protected final Database mDatabase = Database.getInstance();
}
Then your concrete fragments can extend your BaseFragment e.g. SearchListFragment extends BaseFragment
Hope this helps.
Worth reading about singletons and database
Regards,
Chris
Define an interface called Callbacks (or something else if you want). In it, have a public method called getClassX(). Then make your Activity implement the Callbacks interface.
In your Fragments, in onAttach, store a reference to a Callbacks object (i.e. your activity via something like:
if(activity instanceof Callbacks)
mCallbacks = (Callbacks)activity;
This will guarantee that the Fragments are able to call the function. (in case you want to reuse the fragments later in another app)
Then in your Activity, in onCreate(), create an instance of ClassX. In your getClassX() method, just return a reference to it.
When you want a reference to it from your Fragments, call mCallbacks.getClassX() and you should be sorted.
You can use a static object in your activity, and use it from the fragment, or call the getActivity() method in your fragment to access the whole activity objects/methods