I have a case in my Android application in which I need to perform a long running task. At the end of that task I will use that info. I have multiple activities that need to access that info and I do not need to recalculate it each time.
The simple answer is create a 'static' class that can store the info. If the info is not yet there, it can start an AsyncTask to get the info. If the info has already been obtained/calculated it can just give back the info.
However I am wondering if a service is a better pattern/idea in this case. Can I use a service in Android, have that service obtain the data and allow other activities to ask that service for the data?
However I am wondering if a service is a better pattern/idea in this case
If the task will take longer than a second or so, I recommend the use of IntentService. That way, if your app moves to the background while the work is going on (e.g., incoming phone call), Android is less likely to terminate your process, allowing you to complete your work.
If the task will take longer than 10-15 seconds, I recommend the use of a WakeLock as well, perhaps in the form of my WakefulIntentService. Otherwise, the device may fall asleep while the work is being done.
and allow other activities to ask that service for the data?
You only want a service around while it is actively delivering value to the user. Sitting around waiting for activities to ask it questions is not actively delivering value to the user. IntentService automatically destroys itself when the work is complete.
When the data is ready, use an in-process event bus (e.g., greenrobot's EventBus, Square's Otto, LocalBroadcastManager) to tell interested parties that the data is ready. If you also need to hold onto the results past that point, use an appropriate feature of the bus (e.g., sticky events with greenrobot's EventBus, the #Producer pattern with Otto), or have a separate singleton cache.
If the information is needed at different points of the Application life cycle then, then I would suggest storing it using shared preference. That would give you the option of accessing the information next time you would start the App.
However, if you would need to notify an activity of the availability of the information I would use some bus in the application. Incase you wanted to use Otto be mindful that it has been discontinued in faver of Rx. a link to Otto's github page
Related
My Activity (call it A) starts an IntentService (call it IS) as one step in a larger task (call it T). IS may run for an hour or more; when it finishes it must tell A somehow, so that A can take the next step in task T. But, by the time IS finishes, User may have done many things, including killing A altogether. Nevertheless, when User restarts it, A must realize IS has finished, so that A can take the next step in task T.
There are many suggestions how to communicate from IS to A: Intent, PendingIntent, Broadcast and Receiver, ResultReceiver, Messenger thread, etc. [I haven't provided links because a simple search will show them.] But all presume A is alive at the time the message is sent. It seems IS simply cannot send a message to a dead A.
Or can it?
SharedPreferences might be the way to persist a message from IS to A. When it finishes, IS sets flag F in SharedPreferences. Now F is persistent, even if A is dead when F is set. When User re-starts A, it checks F. If F is set, A knows IS finished, and now A can take the next step in task T.
Moreover, if A has a SharedPreferences Listener, then IS can signal A whether A is dead or alive; and IS needs no other means of communication at all.
In fact, it seems SharedPreferences Listeners might be the VERY BEST way in general to communicate and coordinate, as long as messages are only occasional and short.
Does this make sense? SharedPreferences was not designed for messaging, so I fear some hidden consequences. What do you think?
It seems IS simply cannot send a message to a dead A.
Correct. You can use an event bus to post an event that A can pick up, and if A does not pick it up, you can persist the details for A to find out about later.
I demonstrate the basic event bus "UI or fallback" pattern in these sample apps for:
greenrobot's EventBus 2.x
LocalBroadcastManager
Square's Otto
In my case, the fallback behavior is to raise a Notification, but that is not a requirement.
SharedPreferences was not designed for messaging, so I fear some hidden consequences
One is performance. SharedPreferences always performs disk I/O. Using this as a fallback for cases where there is no running instance of A is fine. Using it all the time is not ideal.
Also note that there is nothing much magical about using SharedPreferences here. Any form of persistence would work (e.g., database, other sort of file). Particularly if there might be several messages from IS that need to be queued up, I would consider using Tape.
I need a shared list of computers made available to all my app's activities. The list of computers needs to be upated by two background tasks of some kind, one that blocks on a socket waiting to receive data, and another task that periodically purges computers from the list. What is the proper Android way of doing this to avoid running into activity lifecycle problems? Specifically,
Can/should I use a singleton to maintain and expose the list to the activities and background tasks? (I'm familiar with thread synchronization issues and am prepared to deal with that.)
Can/should I use the IntentService class (two separate instances for the work I need to carry out) or is there a better way? Do I need to use a BroadcastReceiver in that case or could I still store the list in some common place, like a singleton?
How do I avoid keeping my services running when my application is put in the background?
Updated answer for updated question
You can use a Singleton if you don't have a problem with losing your data when your app get's killed (e.g. when you can rebuild the data on restart). In this case you should check that all your components run in the same process (which is default).
You should not use IntentService for intra-app-communication, however bound Services might be an option here
If you bind services from an Activity and unbind them in onPause, they get automatically stopped (if there are no other bound contexts and they weren't started with startService)
If you think your tasks are too complex to accomplish in the same Service, I would recommend two Services bound by an Activity and backed by a ContentProvider which e.g. can be backed by a database.
Old answer
The issues you expierenced might be a problem of Thread-safety (or the lack of it)
Two Intent Services just to share data within an application is definetly way over the target
A broadcast is the right way to notify components of a change
You might want to take a look at Content Providers
Another solution might be a service, which can be bound by all your other components
You can use Database to maintain the UDP packets with timestamp.
Also periodically check the last sync time from Database to check whether UDP packet is coming or not. Hope you know how to use Database.
I've read by many people to not use AsyncTask for web requests, but rather use IntentService, since AsyncTask is bound the lifecycle of its activity. is that always the case? cause I'm making a social media app, And I wonder if each action the user makes should launch a service (for example, press like, add comment, etc)?
Do not use AsyncTask, as you may have read, it is problematic on Activity recreate. However, you may use AsyncTaskLoader with LoaderManager, which is designed to fix the problem.
And there is one point you are wrong with IntentService, you do not launch a service everytime using IntentService. You are submitting requests to the same service only (unless it is being killed), and the IntentService pull requests from the stack.
I tend to use a mixture of both. I use an IntentService when requesting/posting data from a server, then deserialising it and storing it locally. All this could take several seconds depending on the amount of data returned and the server's response time.
I would use an AsyncTask within an activity if I know that the request is going to be very quick. I use it for more fire and forget small tasks.
The important thing to bear in mind is that your AsyncTask is tied to your activity. And if your activity gets destroyed (due to an orientation change etc.) then you could easily have an NPE in the onPostExecute().
If the task you wish to perform is specific to a Context and is considered garbage once you leave the Context, such as if you consider the user session to be invalid once they leave, then an AsyncTask is a good choice.
However, if the task is specific to a context and may take a long time to perform and you want the user to be able to leave and come back later to see the result, a service may be well suited even though the task is specific to a Context.
If the task you wish to perform is applicable outside the scope of a Context, then a service may be better suitable.
If you just always use a service, you'll probably be over complicating your code.
I am writing an application that shows "Japanese Traditional Time" (JTT for short). There are several components (notification, widgets, application itself, alarms) which all use the same data - current JTT.
My current version uses a single service that does all the calculation and uses a Handler to notify everyone about "ticking", mimicking ACTION_TIME_TICK.
However with alarms I need to also have a way to translate "usual time" to JTT and vice versa. The calculations are quite CPU-heavy (it's all based on sunrises and sunsets) and thus I prefer having it all done in a single place and then cached (calculating stuff knowing sunrise and sunset times is not as heavy).
So I have several ways to do that now:
Keep it all in Service
And use binding to request the data I need. It's actually already done in one case and seems a bit cumbersome since I have to handle asynchronous responses
Move to content provider
And use content observers instead of broadcasting
Or send broadcasts from provider
Combine both ways
Use content provider to calculate the data for service which in turn will broadcast it when needed
Which would be better? Maybe something else?
Content providers are for structured data, so it doesn't really fit your use case. Not sure what you mean by 'asynchronous responses'? Calling a remote service is usually just like a local function call, it will block and return a value when done. If you have to notify multiple components a broadcast is the way to go. Explore using a LocalBroadcast if all components are in the same process (check Android support library source), or set a permission on it to make sure other apps cannot get it if you need to send a system-wide (regular) one.
I'm sticking with "just service" - I have discovered Sticky Broadcasts which actually cover the problem I had with common Broadcasts (having to request latest data from service after registering but before getting the first "tick") and that leaves me with much less cases where I need actual service connection.
I'm currently learning to develop for Android and I'm having a somewhat hard time figuring out when and how to use services. I have already seen the numerous questions asked about very similar things, but I can't quite find the exact answer to my questions.
I have an app which talks to a restful api. I fetch several lists which I would like to cache in memory and only update if the user hits a refresh button, or certain activities are created. If a list is refreshed, sometimes several activities need to be notified, so that they update their content (if they are on screen at the time). I store the data I retrieve in value objects.
On a non-android app I would usually create a sort of dataproxy class in a singleton pattern. I could ask the dataproxy to update its data via http request, and then it would send some kind of system-wide notification as soon as the data is changed, so the interested views can all be updated. I hope this makes sense.
My question is now: How do I do this the android way? Do I bind and unbind to a dataproxy service, which I can actively ask to fetch certain data? Should I do my non-persistent caching in this service or somewhere else? Do I need AIDL, or can I just use normal objects for moving data between a service and an activity? Although I find the android dev guide pretty well written and useful, I haven't found much information on services best practice.
Thank you in advance!
How do I do this the android way?
You assume that there is a single "android way".
Do I bind and unbind to a dataproxy service, which I can actively ask to fetch certain data?
You can either bind, or send commands via startService().
Should I do my non-persistent caching in this service or somewhere else?
If you're sure that you only want it to be in RAM, I'd lean towards static data members. Make the service be the "do-er", not the store.
That being said, I'd treat this more as a synchronization pattern, with the real store being a database or directory, with a cache in RAM. Users will find this less frustrating -- under your current plan, if they are in your app, then take a phone call for a while, they'll have to have you download all the data again.
Do I need AIDL, or can I just use normal objects for moving data between a service and an activity?
If they are all in the same process, normal objects is fine via binding, or use Intent extras for the command pattern.
Now, back to:
How do I do this the android way?
Option #1: Wrap your store in a ContentProvider and use ContentObserver for changes.
Option #2: Have your service send a broadcast to your package when the data changes, so the foreground activity can find out about the change via a BroadcastReceiver registered via registerReceiver(). Other activities simply grab a fresh look at the data in onResume() -- the only one that immediately needs to know of the data change is the one the user is interacting with, if any.
Option #3: Use the binding pattern with the service, and have the foreground activity register a listener with the service. The service calls the listener when data is updated. Once again, ather activities simply grab a fresh look at the data in onResume()
Option #4: Cook up your own listener system as part of your static data members, being very very careful to avoid memory leaks (e.g., static reference to an activity or service that is destroyed, preventing its garbage collection).
There are probably other options, but this should get you started.
The Google IO session mentioned by Andrew Halloran:
http://www.google.com/events/io/2010/sessions/developing-RESTful-android-apps.html
Check out the Google I/O session videos. I implemented REST api calls the easy BUT wrong way. It wasn't until watching this Google I/O video that I understood where I went wrong. It's not as simple as putting together an AsyncTask with a HttpUrlConnection get/put call.