I have an application that keeps some complex data in memory between activities.
As for now I use a Singleton class that use SharedPreferences in getters and setters.
What I want: As long as my application is live and showing in the recent apps, I want a class to never get released or find a way to achieve this another way without consequences.
So I was wondering, is a better way available to me?
Would a Service be better?
If so, should I start and/or bind it?
If you go with a service, you wouldn't bind it as unbinding could cause it to stop.
You could create a static object and create it in a custom Application class. So for as long as your application is alive the object is held by a strong reference.
Or a combination, use a singleton class but let the application class store the reference to prevent garbagecollection(GC)
after chat:
a service running in its own process should be the most persistent thing you could build. However you need to communicate with the service via AIDL, a cross-process bridge, which draws performance if the communication is high-speed.
Related
Let's say we develop an app with web authorisation. We need some "global" service to determine whether the user is logged. If user is logged, the service must provide some data (such as cookies, auth token, etc) to identity user, otherwise the service must have a way to set this data.
There are couple of ways of doing it. We can use static context (singleton or just static fields) to store this data. We also may create some Service to get all this data from.
But what way is recommended by Google? What way is ideologically correct? Perhaps there are other ways to implement that?
Don't know what's recommended by Google but if you need an object that lives as long as your application lives then it would be the Application object.
So subclass your own MyApplication extends Application, define whatever fields you need in there and then declare MyApplication in manifest and access by (MyApplication)getApplication()
Create manager (singleton pattern) that describes your app model. Yes, make sure also that it does not hold context of Activity, Service and etc. If need context, make sure to call getApplicationContext().
Singelton is the simplest way doing it (+design pattern)
But from time to time, there may be problems using singeltons: if the application process is killed, which will happen almost undoubtedly if you leave the app in the background too long, your singleton will be recreated, and so your private int data will be reset to a default value.
Maybe if you don't want to use too much shared data you can use sharedpreferences to avoid this.
Else you could try Extending the Application class.
Hope helps
I have an application which play music. I can remotely add music to a device.
I use a service to be able to run it even if myapplication is not started.
I have an custom adapter to display musics in my activity, but musics data are in my service class.
How can get the data from the service and use it to my custom adapter to display musics ?
I found some solutions like to put my objects in a derived Application class, but if all my activities are destroyed I think the application is destroyed too, isn't it?
Thanks
Use your suggested solution of putting the objects in a derived Application class.
Your Application will not get destroyed if you still have a Service running. That is the beauty of using this technique - as long as any Activity or Service is running in your app, the Application lives in memory.
Alternatively, a functionally similar technique is to use an explicit singleton for your data. For a long discussion on why this is better than using the application, check out the answers to this question:
Singletons vs. Application Context in Android?
The flip side of these techniques is memory management. Since the Application or singleton is always in memory, you may find you are using too much memory with all your objects. So that is something you will have to pay careful attention to.
Consider using weak references to your objects, backed by your DB or shared preferences. Read up a bit about WeakHashMap.
im wondering if it would be a bad idea to create a Singleton that is used between some Android Activities and a Android Service. As far as I know the static fields, in my case the Singleton, is available as long as the whole Process is alive.
My plan is to use a singleton instead of Parcelable to share data between my activities and a Background service. So my Activity1 will add some data by calling MySingleton.getInstance().addData(foo); then I would sent an Intent to inform my Service that new Data has been added to the singleton. Next my BackgroundService would handle the intent and call MySingleton.getInstance().getLatestData(); then it would process the data (takes some time). The result of the service would next be "post" back by using the singleton and fire a broadcast intent, which are handled by the Activity1 (if alive) and the Activity1 will retrieve the result from the singleton.
Do you guys think thats a bad idea?
EDIT:
What I want to implement is an peace of software that downloads data from a web server parse it and return the result. So my Activity would create DownloadJob Object. The DownloadJob-Object would be put into the DownloadScheduler (Singleton) which queues and manage all DownloadJobs. The DownloadScheduler would allow to run 5 DownloadJobs at the same time and use a queue to store the waiting. The effective Download would be done by the DownloadService (IntentService), which gets informed over an Intent that the a new DownloadJob should now be executed (downloaded) right now. The DowanlodService would retrieve the next job from the DownloadSchedulers queue (PriorityBlockingQueue) and return the Result by setting DownloadJob.setResult(...) and fires up an broadcast intent, that the Result is ready, which will be received by the DownloadScheduler which would remve the job from the queue and inform the Activity that the download is complete etc.
So in my scenario I would use the singleton to access the DownloadJobs from the DownloadService instead of making a DownloadJob Parcelable and pass it with the Intent. So i would avoid the problem, that I have two DownloadJobs in memory (one on the "Activity Site" and one on "Service site").
Any suggestions how to solve this better?
Is it true that static instances, like DownloadScheduler(Singleton), would be used by freed by the android system on low memory? So would subclassing the Application and hold there the reference (non static) avoid this problem?
If you are using the singleton just as shared memory between a background service which I assume is performing operations on a different thread, you may run into synchronization issues and or read inconsistent data.
If the data in the singleton is not synchronized, you have to be careful because you are relying on your "protocol" to be sure that nobody is reading while your background thread is writing (which may lead to errors).
On the other hand, if it is synchronized, you are risking to face anr error because the activity which reads the data may be blocked waiting the service to finish to write the data in the singleton.
As the other said, you also have to keep in mind that your singleton may be freed if the os needs resources, and that your data may not be there anymore.
I'd rather use an event bus such as otto or eventbus
EDIT:
Using a singleton as the entry point of background (intent) service is the approach suggested in 2010 Virgil Dobjanschi talk about building rest client applications for android.
The suggested approach is having a singleton that performs as controller of ongoing requests. Please consider also that request to intent service are already queued by the os, so you can throw several intents that will be processed sequentially by the intent service.
Some time ago I also tried take that as a starting point for a library, which still remains unfinished. YOu can find the sources here
What I would certainly not do is to store your data in the singleton. The approach I would prefer is to store the data in some persistent storage (such as sql / preferences / file / content provider) and let the client know of the change through a broadcast message (or, if you are using a content provider, through an observer).
Finally, to some extent this is the approach followed by the robospice library, which looks quite mature and ships a lot of interesting features such as caching.
A better idea is to subclass Application and put any long living objects in there. By subclassing Application you can properly handle startup and shutdown of the application something you can't easily do with a singleton. Also by using an Application Activites and Services can share access to the models within your program without resorting to parcelables. And you can avoid all of the problems Singletons bring to your program.
You also don't have to resort to storing everything in a database which requires lots of boiler plate code just to shove a bunch of data in there. It doesn't do anything for sharing behavior between parts of your application and doesn't do anything to facilitate communication and centralization of activities. If you really need to persist state between shutdowns great use it, but if not you can save yourself a lot of work.
You could also look into using something like Roboguice which makes injecting shared models into your Activities and services.
You might find this helpful:
what's design pattern principle in the Android development?
Using a singleton like this is not necessarily a bad idea, but you will lose it's state if Android decides to stop your process. You may want to consider storing your state instead in a SQLite database or a persistent queue (take a look at tape for a good example).
I have been told recently that extending the Application Class in order to use it as a Singleton was a bad practice but without any explanation.
So what are the potentials problem behind the use of this class ? I have seen it used in many projects.
Also, if using the Application Class is a bad idea, what are the alternatives to store application level variables ?
Using a Singleton approach is not really a bad idea, but it may be troublesome in the cases when being used in a multi-threaded environment where one thread sets a value to a variable and the other thread may over-write that value without any notice.
However, in order to keep application level instances/variables, it is suggested to extend Application class and define it in your AndroidManifest.xml as the default one. Since the application's context is created only once (till the application is running and stays in the memory) when you launch that application, so you may define some variables inside that class to make them availabe anywhere in your application's code using public methods.
Moreover, you may use your application class as Singleton too, since its guaranteed to be created only once when launched.
The problem with using a Singleton class, as well as extending the Application class, is that if the application process is killed - which is very likely to happen when the app is left too long in background - the object will lose all your data.
However, using Application class may be a good option in cases when your app is in foreground or does not stay to much in background (although not 100% risk free).
As an alternative, you could save the data into SharedPreferences, or if your object is more complex, save it in a database.
Another option would be to combine both the use of Application, plus SharedPreferences for example. First try to retrieve the variable from Application instance, if the variable is null, then retrieve it from SharedPreferences.
I'm quite new to Android development.
When is it a good idea to create an Android Service instead of just using a simple Singleton class?
Take, for example, the data layer downloading information feeds from the internet.
Using a Service seems too much for some cases but sometimes I might need access to a Context so I'm a little unsure about how to design the app.
If it is okay for your process to be killed (along with the singleton) immediately after the user leaves its activities, then use a singleton. If you need it to continue running for some duration after that, use a service. If you would like to continue running after the user leaves it, but can live with it not because the user is now on to something else where memory is needed more, then use a singleton.
The decision between these two only comes down to the lifecycle of your app. For this purpose, that is all a service does -- ask the platform to modify its management of your process. If you need a context in a singleton, just use Context.getApplicationContext() to retrieve the global context for your process.