Suppose that my application has many processes.
I try to run some init code (Actually store the application context in a static variable) in Application onCreate(). But I find that in some process, onCreate() is not run before other code in the same process and hence can not access the cached Context.
Where should I put the init code (store the application context) so that it must be ran before any code in the same process?
Based on the discussion we had in chat, you have a problem because you are trying to get the application's Context during static initialization of some helper class. I suggested the following:
If your helper class is only used by Android components
then by the time an Android component calls your class
the Application.onCreate() will have been called
and you can get the context from there.
You just need to wait until you get an actual call from an Android component to go and get the Context.
Don't try to do it as soon as the helper class is instantiated. Only do it when you need it.
Related
What exactly is the purpose of Application class.
what are the benefits of extending it to a custom subclass
Why use it ?
Can global variables be stored in any other class achieve same goal as Application ?
Nice question !
Your application is a context that is always running while your activities and services are running.
It is also the first context to be created and the last to be destroyed.
Thus, it surrounds the life cycle of your app.
You can use the application class as a way to share data or components (for dependency injection for instance). For instance if you want to share a singleton between activities, you can create the instance in the application class and provide a getter, then all other contexts can get the singleton via
((cast to your class)getApplicationContext()).getFoo();
There may be some use cases where you need to do stuff before even your first activity is launched, then do it in the onCreate method of the application class.
On the other hand, you should never relie on the onDestroy method of the Application class, as it is not always called. There is no contract for that on Android.
But this is rare and, usually, you don't need to override the application class though. Dependency injection can be achieved in other ways by RoboGuice or Dagger for instance.
Two things makes this Class very useful:
Application class is instantiated before any other Activity.
It holds the Application Context
Context brings a host of resources for us: we can figure out some device properties, load some resources, initiate a SQLite database etc, etc.
All of this happens before any Activity loads, and all of this is globally available to the Activities.
Simple example of what I mean:
public class App extends Application{
private static Resources sResources;
//--I want to load strings resources from anywhere--
public static String loadStringResource(int resID) {
return sResources.getString(resID);
}
#Override
public void onCreate() {
super.onCreate();
sResources = getResources();
//---I want to load all preferences when my app starts---
PreferenceManager.setDefaultValues(this,R.xml.prefs,false);
}
}
Extending the Application class allows you to integrate into the application's lifecycle.
This is also useful to store global application-level information (though it's usually good to keep your activities 'independent')
The Application class is aware of the Application Context and is loaded when your app is loaded so it holds the proper callbacks for the application lifecycle before your activity starts. You most likely would not want to extend this class.
From the API docs:
There is normally no need to subclass Application. In most situation, static singletons can provide the same functionality in a more modular way. If your singleton needs a global context (for example to register broadcast receivers), the function to retrieve it can be given a Context which internally uses Context.getApplicationContext() when first constructing the singleton.
http://developer.android.com/reference/android/app/Application.html
I have a class named PatientDetails in which i am storing the values from the xml and then need to access its variables and method from the service as well from the activity at the same point of time ??
This is a typical multi thread scenario. You can do it without any troubles as long as you are just reading the data.
If you are reading the data from patient details class through your activity and writing data to it through your service you will get into run time exceptions. You have carefully synchronize the variables or methods in such cases.
One way to share a 'helper' class is to hold a 'static' reference to a single instance of it in the Application component of your app. Example...
public class MyApp extends Application {
public static detailsHelper;
#Override
public void onCreate() {
detailsHelper = new PatientDetails();
}
}
When you need to use the 'helper' in any other component such as an Activity or Service you simply reference it by the Application name as follows...
MyApp.detailsHelper.doSomething();
Technically speaking, under default conditions there is no such occurrence of two components accessing something at the same time because an Android Application and all of its components exist within a single process with a single thread of execution.
You should be very careful, however, if any of the components execute code which uses threads. For example, an Activity using an AsyncTask or perhaps using an IntentService which creates its own worker thread to do work. In this case, make sure any methods in the 'helper' class which write data, do so in a thread-safe manner.
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
I have a singleton that holds a lot of information on my App (ACCU.class).
I'm using the application context to do a single initialization and single finishing.
One of the key features is another singleton called IMCDefinition that reads from a raw resource named imc.xml. If I call the line IMCDefinition.getInstance(getResources().openRawResource(R.raw.imc)); from an Activity Context it works. From an Application context it doesn't...
Following goes the code:
public class App extends Application
{
public App()
{
IMCDefinition.getInstance(getResources().openRawResource(R.raw.imc));
ACCU.getInstance(this);
System.out.println("Global ACCU Object Initialized");
}
}
Done! You don't get to mess with the Constructor in this class. onCreate() is the way to go. Put your code there. Forget about the question. Should i put this in a separate answer?
Here's my case
1. start main and the only activity of my app, the activity is almost empty at the startup moment
2. bind to a local service, which is nearly a wrapper of my legacy native library
3. all views will be dynamically created during runtime
4. it's service who determines when and how to build views, of course, mostly in native C++ code and JNI calls
So, I'm required to get a Context, actually current activity, since every constructor of Views requires a Context as a parameter. But how can I get the Context and cache it, if possible?
Thanks.
Bind to the service in your activity and pass a context in some method like
service.setActivityContext(this);