Keeping reference of an object for a task's lifetime - android

I am looking for a way to keep reference of an object/instance that's a member object of a service. I know in case of Activities, we can save it by the provided onSaveInstance method. However, I couldn't find any similar way for a service.
I can use static object but it's unsafe as there is no guaranty, if the reference would be valid the next time, the service is created.
Another possible way would be, I store all the data on storage & later on when the service is created again, I can read the data from storage. Then traverse through information/data provided by the another class & find the relevant reference for the info read from the storage, which I think is very expensive interms of execution time.
So I am looking for a way to get rid of all this process & keep a strong reference (of the object in service) in the memory as long as the task/app is running.
Regards

You can use application class to persist data as
public class MyApplication extends Application
{
public MyDataClass data = new MyDataClass();
}
Then call it in any activity/service by:
MyApplication appState = ((MyApplication)this.getApplication());
appState.data.useAGetterOrSetterHere(); // Do whatever you need to with the data here.
In your manifest mention it as follows::
<application android:name="yourpkgname.MyApplication"/>
More info are like
Application object is an object whose lifecycle is same as our Application.
When Application starts this object is created automatically by Android Framework.
When you want to share data between more than one activities of your application or you want to retain something at application level.In that scenario you can use Application object as a global store for your application.

Related

Main data model on android

I have an android application with a number of activities.
I have a singleton class holding my main data model which all activities access to get data.
The problem is that sometimes the android GC decides to destroy my singleton when the app in the background (when you press the home button).
Is there anyway that I can bypass this?
I've had this exact problem in a current application of mine, which needs to retain a large amount of data in various 'singleton' classes. The problem I encountered was as in your case; i.e. sometimes when bringing the application back to the foreground, some of the static 'singleton' classes have been destroyed.
The problem, I believe, is that the 'lifetime' of such classes can never be well defined or predicted. After all, it's a class sat there holding a reference to itself, so it's susceptible to being garbage collected when the system wants to grab some resources.
You're probably already aware that extending android.app.Application is a well-known alternative to using conventional Singletons. The solution that worked for me is to hold the actual instances of data singleton classes within an extension class of android.app.Application, whose lifecycle is well defined. Any other class that wants to access those singletons can obtain them using a getter in the Application class.
So for example I have a class called AppState that extends Application, that holds the instances within:
import android.app.Application;
public class AppState extends Application {
...
// "Singleton" instances that this Application extension looks after
private MSData singletonInstanceMSData;
public AppState() {
...
singletonInstanceMSData = new MSData();
...
// ---------------- Singleton instance control ----------------
public MSData getMSData(){
return singletonInstanceMSData;
}
// I also provide the means to 'reset' the instances on startup (this is
// something I need to do for my application - you may or may not need to)
public void resetControllerSpecificData(){
singletonInstanceMSData.reset();
...
Don't forget you'll need to modify your manifest if you extend Application.
AFAIR, lifespan os singleton is lifespan of his classloader - also complete VM . When user hit home button, your application goes in backgorund and is probably destroyed - you can not do anything against it. Your best bet is to save whatever is necessary in your onPause() callback ( or just use write through in every change of datza if you really paranoid )

is it possible to access one class file to access its methods or variable by a service and another by an activity AT THE SAME TIME?

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.

Lifecycle of enum based singleton on Android

A few days ago I've discovered that singleton can become anti-pattern in Android. My singleton (class with private constructor and instance stored in static field) was deleted (instance was deleted despite the fact other activities were still using this singleton (via getInstance() method) so another instance had to be created ) because Activity from which it was first invoked was deleted (after invoking finish for only this one activity).
I've read already how this problem can be resolved however I've also just read "Effective Java". There is said that "Single-element enum type is the bast way to implement a singleton".
So now I'm wondering what would be the lifecycle of singleton created this way in Android application? Would it be the same like in case of "standard singleton implementation" so after destroying activity from which it was invoked the first time it will be destroyed (even if it used also in other activities)?
I'm not asking about proper android singleton implemenation or the singleton pattern itself (is it pattern or anti-pattern etc) but I'd like to know what be the lifecycle of such enum singleton object and when it will be destroyed.
In all cases, the classes you use are tied to the ClassLoader that loaded them. This is true in Java in general, not just Android. Android will isolate activities by using new ClassLoaders each time -- at the least, it doesn't promise it won't, and it does as far as I can tell.
Any singleton, or other class-level state, is tied to the Class which is tied to the ClassLoader. This is why your state "disappears"; it's actually that your calling code is seeing a new Class in a new ClassLoader.
So, your enum-based trick, or anything else along these lines, would have exactly the same behavior. You just can't "persist" activity information this way. You can and should write to a SQLite DB. You could probably stash it in the SharedPreferences too.
The application object is a good location to store information which needs to be accessible to various activity or service instances. You can retrieve it like this (where this is an Activity or Service):
private MyApplication app;
in onCreate(...){
...
this.app = (MyApplication) this.getApplication();
...
}
Remember to set the name also in the manifest:
Set the attribute "name" of the "application" tag:
The value is the path to the class relative to the package of your app.
The application object is created when the app is started, you can initialize like in an activity or service in it's onCreate() method.
One thing to remember: The application object can survive closing your "last" activity. In this case you may get the same application object with the state from the previous interaction with your app. If this is a problem you must somehow detect the initial start of your app (e.g. using a special launcher activity without UI, which initializes the application object and then starts a new intent.
BTW, the same may happen with singletons if they have not yet been lost to garbage collection.
My secure singleton implementation is like that:
I create a singleton class which has an attribute of boolean 'didReceiveMemoryWarning';
public class SingleTon(){
public boolean didReceiveMemoryWarning = true;
...
...
}
In application first screen(It is exactly first launch screen)(I have a splash screen that is visible 3 sec)
SingleTon.getInstance().didReceiveMemoryWarning = false;
And in every Activity's onCreate() method, check this boolean data,
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(SingleTon.getInstance().didReceiveMemoryWarning){
{ Load your data from local to your SingleTon class,
because your app was released by OS};
}
}
it is my implementation.

Working with same data in three activities

I'm not very experienced in android specific components, so I just can't get where I need to look.
I have three activities:
1st gets info about some groups of objects, user selects some of this groups and activity needs to star next activity
2nd activity shows all objects from groups, that user selected at previous activity, here user can deselect some selected objects and then activity starts 3d activity
3d activity allows user to do something with selected objects
My solution is make some singleton model, that let activities get and save information about objects,
but i suppose, that android has some special components to provide data between activities
Help me to find this components^ please
It depends on the type of data that you want to share:
Primitive Data Types
To share primitive data between Activities/Services in an application, use Intent.putExtras(). For passing primitive data that needs to persist use the Preferences storage mechanism.
Non-Persistent Objects
For sharing complex non-persistent user-defined objects for short duration, the following approaches are recommended:
The android.app.Application class
The android.app.Application is a base class for those who need to maintain global application state. It can be accessed via getApplication() from any Activity or Service. It has a couple of life-cycle methods and will be instantiated by Android automatically if your register it in AndroidManifest.xml.
A public static field/method
An alternate way to make data accessible across Activities/Services is to use public static fields and/or methods. You can access these static fields from any other class in your application. To share an object, the activity which creates your object sets a static field to point to this object and any other activity that wants to use this object just accesses this static field.
A HashMap of WeakReferences to Objects
You can also use a HashMap of WeakReferences to Objects with Long keys. When an activity wants to pass an object to another activity, it simply puts the object in the map and sends the key (which is a unique Long based on a counter or time stamp) to the recipient activity via intent extras. The recipient activity retrieves the object using this key.
A Singleton class
There are advantages to using a static Singleton, such as you can refer to them without casting getApplication() to an application-specific class, or going to the trouble of hanging an interface on all your Application subclasses so that your various modules can refer to that interface instead.
But, the life cycle of a static is not well under your control; so to abide by the life-cycle model, the application class should initiate and tear down these static objects in the onCreate() and onTerminate() methods of the Application Class
Persistent Objects
Even while an application appears to continue running, the system may choose to kill its process and restart it later. If you have data that you need to persist from one activity invocation to the next, you need to represent that data as state that gets saved by an activity when it is informed that it might go away.
For sharing complex persistent user-defined objects, the following approaches are recommended:
Application Preferences
Files
contentProviders
SQLite DB
If the shared data needs to be retained across points where the application process can be killed, then place that data in persistent storage like Application Preferences, SQLite DB, Files or ContentProviders.
yes, you can send data between activities using Intents. Using the putExtra() function for that. If you want to pass your own objects, you need to implement Parcalable class.
There is no problem with using a singleton to share information between your Activities, especially if you need this data to be consistent throughout your whole app.
Alternatively you could use an Intent to pass data between Activities - putExtra().
Yes it does:
http://www.remwebdevelopment.com/dev/a33/Passing-Bundles-Around-Activities.html
Basically you can either send a Bundle or just use putExtra function for that.
try this way please
Intent i = new Intent(this, YourTragetedActivity.class);
i.putExtra("value1", "test1");
i.putExtra("value2", "test2");
startActivity(i);
//// On Your TragetedActivity
getIntent().getStringExtra("value1")
getIntent().getStringExtra("value2")

Using the Android Application class to persist data

I'm working on a fairly complex Android application that requires a somewhat large amount of data about the application (I'd say a total of about 500KB -- is this large for a mobile device?). From what I can tell, any orientation change in the application (in the activity, to be more precise) causes a complete destruction and recreation of the activity. Based on my findings, the Application class does not have the same life-cycle (i.e. it is, for all intents and purposes, always instantiated). Does it make sense to store the state information inside of the application class and then reference it from the Activity, or is that generally not the "acceptable" method due to memory constraints on mobile devices? I really appreciate any advice on this topic. Thanks!
I don't think 500kb will be that big of a deal.
What you described is exactly how I tackled my problem of losing data in an activity. I created a global singleton in the Application class and was able to access it from the activities I used.
You can pass data around in a Global Singleton if it is going to be used a lot.
public class YourApplication extends Application
{
public SomeDataClass data = new SomeDataClass();
}
Then call it in any activity by:
YourApplication appState = ((YourApplication)this.getApplication());
appState.data.UseAGetterOrSetterHere(); // Do whatever you need to with the data here.
I discuss it here in my blog post, under the section "Global Singleton."
Those who count on Application instance are wrong. At first, it may seem as though the Application exists for as long as the whole app process exists but this is an incorrect assumption.
The OS may kill processes as necessary. All processes are divided into 5 levels of "killability" specified in the doc.
So, for instance, if your app goes in the background due to the user answering to an incoming call, then depending on the state of the RAM, the OS may (or may not) kill your process (destroying the Application instance in the process).
I think a better approach would be to persist your data to internal storage file and then read it when your activity resumes.
UPDATE:
I got many negative feedbacks, so it is time to add a clarification. :) Well, initially I realy used a wrong assumption that the state is really important for the app. However if your app is OK that sometimes the state is lost (it could be some images that will be just reread/redownloaded), then it is fully OK to keep it as a member of Application.
If you want to access the "Global Singleton" outside of an activity and you don't want to pass the Context through all the involved objects to obtain the singleton, you can just define a static attribute in your application class, which holds the reference to itself. Just initialize the attribute in the onCreate() method.
For example:
public class ApplicationController extends Application {
private static ApplicationController _appCtrl;
public static ApplicationController getAppCtrl()
{
return _appCtrl;
}
}
Because subclasses of Application also can obtain the Resources, you could access them simply when you define a static method, which returns them, like:
public static Resources getAppResources()
{
return _appCtrl.getResources();
}
But be very careful when passing around Context references to avoid memory leaks.
Dave, what kind of data is it? If it's general data that pertains to the application as a whole (example: user data), then extend the Application class and store it there. If the data pertains to the Activity, you should use the onSaveInstanceState and onRestoreInstanceState handlers to persist the data on screen rotation.
You can actually override the orientation functionality to make sure that your activity isn't destroyed and recreated. Look here.
You can create Application class and save your all data on that calss for use that anywhere in your application.
I know this is the very old question but using the ViewModel from the jetpack components is the best way to preserve the data between Activity rotation.
The ViewModel class is designed to store and manage UI-related data in a lifecycle conscious way. The ViewModel class allows data to survive configuration changes such as screen rotations.

Categories

Resources