Working with DatabaseHelper while recreating activity on Android - android

I have an activity that uses AsyncTask to download and save some data to the database. To open a database we need to pass Context param to the SQLiteOpenHelper's onCreate method, which means that database somehow needs context.
And I'm just curious, what would happen when device turns and activity goes through destroy and create cycle? Is it ok to open database in activity's constructor rather than in activity's onCreate() method?
The problem is that I use DB from another thread and I want to know what exactly would happen when activity is being destroyed and recreated

One solution would be to use the ApplicationContext instead of the ActivityContext. You only need a static method that requests the ApplicationContext from the Application constructor.
If you use some kind of singleton to access the context, you won't have any problems with concurrency.
See example here: http://androidcookbook.com/Recipe.seam?recipeId=1218
Another approach would be to use the LoaderManager which keeps track of your opened database connections.
See here: http://developer.android.com/reference/android/app/LoaderManager.html
(There is a complete example too)
The LoaderManager is available in the compatibility package for down to Android 1.5
Michael

Incase you want to do some db operations in background. you should use "Sevices".
Services can do long running operations on background.
here is the link : http://developer.android.com/guide/topics/fundamentals/services.html

Related

preserving Singleton DB data on rotation Without using ContentProvider (Android)

How do you preserve singleton database data in an activity after a screen rotation without using Content Provider or loaders?
This was an interview question I got stumped on.
ContentProvider with cursor loader was my first thought, but they said they didn't want that. Then I thought of saving the cursor returned from the singleton DB's query method, but I couldn't "put" a cursor in the out bundle in OnSavedInstance, so I have no idea.
I also asked them "isn't using a singleton database discouraged?" to which they said "yes, but this is just for interview purposes."
Maybe this can help someone in the future who encounters this question.
"In an activity" sounds like I'm not allowed to pass all the stuff to the application class (which will not be destroyed on screen rotation). But just in case this is an option:
You write your own class which extends from Application. The official documentation tells you how to do it but states that you basically don't need to. Having said that, this Stack Overflow post is a collection of possible exceptions from the rule.
In the Activity, you access it like this:
MyApplication app = (MyApplication)getApplication();
But personally I'd keep data for one Activity not in the Application class but inside a retained Fragment. They survive configuration changes but keep in mind that they are not part of the back stack. So if you have a savedInstanceState != null, the retained Fragment may nevertheless have been recreated in its initial state e.g. if the app has been paused for a while.
The guide on Handling Configuration Changes shows how to use retained Fragments
You can use fragments and use Fragment#setRetainInstance(true) for that. And all the data should be saved across configuration changes. Note that a retained fragment is not visual its placed along your Activity or Fragment This might help you: https://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html

How synchronized on activity work, given activity is recreated on orientation change

I have an activity, in the onCreate function I have created a Thread which reads from XML file and populates the Database and also populates member dataStructures.
I have created synchronized methods to carry out DB population and DataStructure population.
Since the lock is on activity[synchronized methods], will it cause any issue when activity is recreated because of orientation change or any config change?
Is it correct to use synchronized methods here? or should I use synchronized blocks?
How do I handle or take care so that DB is not corrupted?
How do I ensure only one instance of DataBaseHelper is present even over activity recreations?
If you want to do what I think you want to do then I suggest to do the following:
Create a thread(HandlerThread named DbAsyncThread or whatever) that handles all the methods for all the db methods.
Method should use synchronized blocks. Synchronized methods I use when there is a public static method. It always depends on what you want to achieve.
Incorrect states of db you can handle via exceptions. If there is an exception you throw it or pass it to the ui so that the users or you are notified.
Use callbacks. If there is a problem notify via callback about the problem. If there is no context involved there should not be any problem.

Using Static Application Context

I was having an issue with a handler returning during a screen rotation, meaning that the Activity had not been created yet and causing an error.
I solved this via this post: Static way to get 'Context' on Android?
Which sets up an application level static context to use. I wanted to know how safe this is to use and if there are any instances where I shouldn't use this, as I don't entirely understand it.
Thanks,
Kevin.
No, this is a horrible way to solve it. It means you're using the Application context instead of your Activity context, which is generally wrong and can cause memory leaks. The correct way to do this is to either check for this condition before ding anything that can cause this error, or to catch any exception caused and eat it.
Really the best way to solve this is just to turn off activity recreation on rotation which is and always has been a stupid idiotic idea by Google.
How safe is doing so?
Keeping an instance of the Application context as a singleton is completely safe, understanding as safe that you will not receive a NPE by accessing this instance. The application object is itself a singleton and there is only one per application. Even when the app is killed by the system, the Application object's onCreate() is the first call, so you will always obtain a reference to the Application context.
Can I use it for everything?
Of course, NO. The application context is a suitable context for resource management, like accessing to string values, getting the database instace and such. But it is not a good target for the Android View framework, which requires an Activity context. So, you can use it always when there is not a view related to its use. LayoutInflater, for example, will produce an error if you pass to it an Application context.
I recommend to use the Activity context always when you can, but there is some cases where passing the activity context is not an option, for example if you are creating a database instance when the application is being started.
What about the activity recreation on rotation?
Every Android developer will tell you it is a complete hell to manage this scenario, and it is better for you to lock your activity in vertical or do avoid the recreation of the activity. Beside there is not consistent way to do it across all brands and devices, there are many posts from Google Engineers advocating against doing it because it may produce serious memory leaks and layout problems. Here you have more information.
If you use application context you cannot do certain things like inflating a layout- if you pass the application Context into the LayoutInflater you will get an Exception.
Try to use a Loader instead. The result will not be pushed to the views until the Views are ready.

best way to share the same database among all activities

I am using a database that I need to access in all activities. So I created a class MyDBAdapter with all the methods open, create, getData etc...
To access the DB I see two different ways:
a. In each activity do I now write: MyDBAdapter db = new MyDBAdapter();
which means a new DBAdapter would be created in each activity. Each would open the same DB and have to close it. This also means that the same DB might be opened by several activities - is that OK? Or do I manually ensure that the DB is closed everytime I switch activities?
or
b. create only one instance of the DBAdapter in the first activity and pass it everytime to the next activity using putExtra("Task", x);
Then the DB gets only opened and closed once in the very first activity.
Which one is a better approach?
Thanks very much.
I prefer content provider to share data among activities.
Even though its mainly aimed to share among applications, It can be used inside our single app.
If we use content provider, there is no worries of closing and locking of db.
Content providers implement a common interface for querying the provider and returning results — as well as for adding, altering, and deleting data.
It's an interface that clients use indirectly, most generally through ContentResolver objects. You get a ContentResolver by calling getContentResolver()
Check this Simple Content Provider for db operations
Generally you have to close the database, right after you finish working with it (manually call db.close()). This mean that if you use your database in multiple activities, you have to close it every time after you have done using it. That said, it's up to you if you will make calls MyDBAdapter db = new MyDBAdapter(); in every activity or you will make a static reference to it. After all, if you have some local variable MyDBAdapter db in some code block, it will be garbage collected at some point.
Also generally speaking, you don't want your database operations in your Activities, because this way they will be executed on the UI Thread, blocking it, until they finish their db operation. You might want to use AsyncTask for your db operations which will create a separate Thread for db operations (and handle it for you). Here's a great tutorial on using AsyncTasks.

Sending an Activity to a non-Android class

I'm pretty much a noob when it comes to Android development. I have an Activity that has a method that pretty much just sets the text of a TextView to whatever text is provided as an argument. I have a second class, which is a Runnable, and I want to be able to give it the Activity (or obtain the Activity somehow), so it can call said method when it needs to.
This Runnable will eventually connect with a server, so it can update the application with information from the server. I've done client/server Java stuff before, so that's not the issue. I just need to figure out how to communicate between this Runnable and the Activity.
Originally, I was going to just pass the Activity itself in, but I read that it would create problems if I did. Instead, I was supposed to pass in an ApplicationContext via getApplicationContext(). I did that, but now I don't know what to do with the ApplicationContext. I tried casting it to the my Activity class, but the program just crashes.
How do I accomplish what I'm aiming at?
There are a few specific ways in Android to handle threading like AsyncTasks etc., you should read up on how to do 'painless' threading here. If it's just a one-off task where you connect to the server, get the value, set it in the TextView and then finish, I think an AsyncTask would be your best option. Continuing background processes are more suited to being services.
you can pass your activity to the constructor of your second Class like this :
public SecondClass(YourActivity _yourActivity){
this.activity = _yourActivity;
//do stuff
}
and in your Activity , you can instanciate your class like this :
SecondClass instance = new SecondClass(this);
NOTE : in your SecondClass , if you want to change the UI of your application , you can use the method runOnUiThread(Runnable);

Categories

Resources