I have read some articles about how to use/extend the Android Application class but I am still kind of unsure if I can use it for my needs.
In my Application, on startup, i read a JSON configuration file. This configuration file contains some basic infos about an external device. Because I need this infos in several other fragments/activities I simply store an object representation of this json file as a member variable of my Application class.
public App extends Application {
private ConfigurationContainer configuration;
...
getters / setters
}
When I need it i call getApplication().getConfigurationContainer().
Is this OK for my needs?
Yes, It is ok.
Follow this steps.
1.Override onCreate() method and load all the json configuration in this method.
public App extends Application {
private ConfigurationContainer configuration;
public void onCreate(){
super.onCreate();
// load json configuration.
}
// getter setter
}
Declare this class in manifest file.
<application android:name="com.packageName.App">.
Use this configuration in all your activity.
App ap = (App)getApplication();
ConfigurationContainer conf = ap.getConfigurationContainer()
Yes it is reasonable to store globally scoped variables (or objects) in your Application class. You should be careful that you are not storing too much data here, as it will consume memory that is never recovered as long as your app is running.
Your concept is fine, but there are some nuances about using the Application class in this way, it is suggested that you create a Singleton class (instantiated by your Application) to store values like this.
Here is a great SO related to this: Android Application as Singleton
Related
I'm part of an Android project that uses a global class that contains public static variables, like the example below:
public class Globals {
public static MyObject variable = "this is a test";
}
In the middle of using the application, this global variable's value will be changed let's say:
#Override
public void onCreate(Bundle savedInstanceState) {
Globals.variable = new MyObject(somethingHere);
}
And I came across using Headless Retained Fragments from these blog posts:
http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html
http://www.vogella.com/tutorials/AndroidFragments/article.html#headlessfragments
Problem:
I need to have a reference of an initialized object all over the application.
Question:
which is better to implement, a good practice, and practical? Or is there another way I could store a reference of an object all over the application?
The global class has been used over the project, and works fine, but are there any downsides of this implementation?
are there any downsides of this implementation?
Memory leaks, depending on what you are storing there. Leaks are why static data members are considered poor form in classic Java, even if we tend to use them more in Android app development.
Also, this data needs to be considered a cache, one that has to be able to be lazy-created on first access. Your process can be terminated at any point (wiping out the static data member) and the user can return to any activity in your app (courtesy of the recent-tasks list). If you want this data to survive process termination, the most likely solution will be to persist it in a file, database, or SharedPreferences.
All that being said, a retained fragment is a per-activity solution, not a per-application solution, and so it is not a valid alternative for your scenario AFAICT.
The work flow of my program is:
Launch app
Splash screen, check the server api, from the api get a list of file name
Download some of the file in file list , remove the downloaded file name from the list
App opened
when the download is finished , jump to main page that will start download another file in the list
The problem is , the list I was keep in the download manager , when I select don't leave activities in android setting , it will be killed. If I need a class that is some Data Class , that means I put a share data (A several hash map , array list) in it, and it keep updating (delete after async download finish) , and it never get killed. How can it be done? Thanks
The more general problem you are encountering is how to save state across several Activities and all parts of your application. A static variable (for instance, a singleton) is a common Java way of achieving this. I have found however, that a more elegant way in Android is to associate your state with the Application context. As you know, each Activity is also a Context, which is information about its execution environment in the broadest sense. Your application also has a context, and Android guarantees that it will exist as a single instance across your application. The way to do this is to create your own subclass of android.app.Application, and then specify that class in the application tag in your manifest. Now Android will automatically create an instance of that class and make it available for your entire application. You can access it from any context using the Context.getApplicationContext() method (Activity also provides a method getApplication() which has the exact same effect):
class MyApp extends Application {
private String myState;
public String getState() {
return myState;
}
public void setState(String s) {
myState = s;
}
}
class Blah extends Activity {
#Override public void onCreate(Bundle b) {
...
MyApp appState = ((MyApp) getApplicationContext());
String state = appState.getState();
...
}
}
This has essentially the same effect as using a static variable or singleton, but integrates quite well into the existing Android framework. Note that this will not work across processes (should your app be one of the rare ones that has multiple processes).
I'm developing an Android app that uses two singleton objects: one for business logic (similar to the model in MVC) and one for a Bluetooth connection. Some activities display data and need access to the former, while one lets the user connect/disconnect and needs access to the latter.
What is the preferred way of passing these objects around? Arguments to the activities? Global objects?
You can use Application Class. it is a base class for those who need to maintain global application state. You can provide your own implementation by specifying its name in your AndroidManifest.xml's tag, which will cause that class to be instantiated for you when the process for your application/package is created.
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 ,the function to retrieve it can be given a Context which internally uses Context.getApplicationContext() when first constructing the singleton.
ref- http://developer.android.com/reference/android/app/Application.html
Ex- Define in App class
public class AppData extends Application{
Object ob = new Object(); //Global Obj - Can be anything String etc
}
initialize in acticity like -
AppData ad= (AppData)getApplicationContext();
ad.ob = //yourValue
Access across the activities ->
Object obj = ((AppData)getApplicationContext()).ob;
and in manifest give the name of your app class-
<application
android:name=".AppData"
>
You might want to check out Dagger. This Dependency Injection framework (optimized for Android) allows to easily inject singletons into your activities/fragments.
// define this code in your common data access class which use thought your app or application master class
private static Object object=null;
public synchronized static Object getInstance(){
if(object==null){
object = new Object();
}
return object;
}
// this way define your two object.
Recently I have started development in Java for Android.
My idea is to create one static class which will load ton of stuff on the beginning and store results for a lifetime of application.
I have been reading lot of how to share object between activities and I think the best will be to create one static class. What do you think? Should I use another approach? I am asking because I have read lot of counter opinions over the internet.
Thank you.
I'm assuming that you were referring to static fields of a class, as opposed to static class which, as Wyzard pointed out, is something completely different. As a general rule of thumb, holding information in static fields is not a good idea in Java. The reason for this is that it prevents the ability to instantiate multiple instances of whatever it is you store in the class.
In the specific case of an Android application, the best way to deal with the issue of having data stored associated with the application itself is to subclass the android.app.Application class and use it to handle application-global data:
class FooApplication extends Application
{
private String privData;
public String getPrivData() {
return privData;
}
}
You then need to declare that this class is your main application class (instead of the default Application). In the application entry in AndroidManifest.xml add the following:
<application android:name="com.example.application.FooApplication"
...>
...
</application>
You can then look up the application instance from anywhere inside your application using the method Context.getApplicationContext() which will be an instance of your Application subclass:
FooApplication app = (FooApplication)Context.getApplicationContext();
String privData = app.getPrivData();
Depending on from where you are trying to look for subclass of "Application", you may have to invoke the "getApplicationContext()" without "Context":
FooApplication app = (FooApplication)getApplicationContext();
String privData = app.getPrivData();
The problem with your solution is that you're basically creating a huge stack of globals. It's sometimes unavoidable, but it has the same type of problems globals always have- you quickly end up with hard to read code that doesn't really have a good OO breakdown. You can use this, but use it sparingly- only with important data structures that are really going to be shared between many activities.
Android provides a class called Application, which is will not be gc'ed as long as your Application isn't killed. Use this class for initialization, static classes as containers are somewhat ugly, but i can't pinpoint why that is.
I only use them as containers for constants such as bitmasks which can't be expressed as EnumSets.
As the other posts mention SharedPreferences: I think the preferences exist to store values, but not to load your structures that you need for you application. These structures should be loaded from a construct that represent or make up a model for your data's semantics.
I'm trying to persist data objects throughout my Android app. I want to be able to access an object in one activity, modify it, save it, navigate to a new activity, and access the same object with the updated value.
What I'm essentially talking about is a cache, but my data objects are complex. For example, ObjectA contains ObjectB which contains ObjectC. Does anyone know if a good method, tool, or framework for persisting complex objects in Sql?
Put a static field in a subclassed Application. Also inside your manifest, put:
android:name="MyApp" inside your application tags.
Also to access from other files, simply use:
MyApp myApp = (MyApp)getApplicationContext();
See here How to declare global variables in Android?:
class MyApp extends Application {
private String myState;
public String getState(){
return myState;
}
public void setState(String s){
myState = s;
}
}
class Blah extends Activity {
#Override
public void onCreate(Bundle b){
...
MyApp appState = ((MyApp)getApplicationContext());
String state = appState.getState();
...
}
}
You could use an ORM framework, like OrmLite for mapping objects into sql, but it may be an overkill for you situation.
You could also make these shared object Parcelable and pass them between the Activities thru the Intents.
You could also save these objects into the SharedPreferences, so each Activity can access them whenever they feel the need to it, and the objects are also persisted this way. This may mean more IO access though, so take that into consideration as well. You could use e.g. Gson to serialize the objects more painlessly for this.
These are the solutions I'd consider. But whatever you do, don't put this common object into some kind of "standard" global static variable, like using a custom Application class, static field or any implementation of the Singleton pattern, these are really fragile constructs on Android.
Why don't you use a JSON serialization mechanism ?
In association with a static access to your objects you can easily build a lite-weight database with some basic functionnalities:
loadObjectsFromCache
saveObjectsInCache
getObjects
You can also store your objects in differents files, and use a streaming json parser like this one: http://code.google.com/p/google-gson/
It's the same that this one: http://developer.android.com/reference/android/util/JsonReader.html
but can be used even if your application api level is inferior to 11.
It use less memory than the basic DOM parser:
http://developer.android.com/reference/org/json/JSONObject.html,
but with the same speed.