2

I need to make a design decision.
From what I read in the android developers site I think I want to implement a Service which launches an AsyncTaskLoader to load data from an OS process in the background.
In the android developers site documentation it says that AsyncTaskLoader can be used in Activities and Fragments, but no mention of Services.

Is it a bad practice to use AsyncTaskLoader in a Service?
If so, how do I collect data from a running OS process in the background? (Note: I need the collection to go on even if the app is closed/destroyed)

ilomambo
  • 8,290
  • 12
  • 57
  • 106

2 Answers2

2

Loaders are generally used for UI elements that are created and destroyed relatively often, and need to access the previously queried objects without re-querying every time. A Service won't be destroyed mid load like an Activity or Fragment will, so spawning a new Thread is considered the best practice for loading data in the background in a Service.

SeanPONeil
  • 3,901
  • 4
  • 29
  • 42
  • Do you happen to have link to some example? – ilomambo Feb 11 '13 at 19:59
  • The IntentService will keep a queue of Intents to process, and run onHandleIntent in a background Thread. Here's a nice tutorial on IntentServices http://mobile.tutsplus.com/tutorials/android/android-fundamentals-intentservice-basics/ – SeanPONeil Feb 11 '13 at 20:32
  • See my response to kabuko about IntentSevice – ilomambo Feb 11 '13 at 20:40
1

Loaders are really for Activities and Fragments, it might make sense to consider an IntentService if you just want a good way to do some work in background threads. Is there something specific that looked useful in AsyncTaskLoader?

Either way you won't be able to keep collecting if your app is destroyed. If your app is destroyed, it's not there to do any work. A Service of some sort is definitely what you want to use to do work in the background though.

kabuko
  • 36,028
  • 10
  • 80
  • 93
  • Yes, I wrote that the AsyncTaskLoader would be launched from a service. Nothing special about AsyncTaskLoader, the documentation says Loaders are to be used to gather data. BTW, services are not run in separate Threads, they run in the UI thread. – ilomambo Feb 11 '13 at 20:12
  • 1
    @ilomambo by default yes, but that's why I mentioned [`IntentService`](http://developer.android.com/reference/android/app/IntentService.html)... – kabuko Feb 11 '13 at 20:13
  • It says in the doc that "An operation running on an IntentService can't be interrupted" and also "If an operation is running in an IntentService, and you send it another request, the request waits until the first operation is finished.". I actually may need to stop the background work, which is an OS process generating output all the time; it is not clear I can do it with IntentService. – ilomambo Feb 11 '13 at 20:35
  • 1
    You can create a HandlerThread in a Service. That will not run on a UI thread. It is a recommended approach to do background activities. See 'Extending the Service class' in http://developer.android.com/guide/components/services.html. IntentService classes are general purpose and easier to implement a work queue but if you want to do multi-threading, see the link. – praneetloke Feb 11 '13 at 20:37
  • After some thoguht it seems to me maybe I can tweak IntentService and finish the background work by using onStartCommand() as message handler rather than queueing all intent requests. – ilomambo Feb 11 '13 at 20:48
  • @ilomambo there is a library I'm working on that does exactly that. It's a sexier implementation of the IntentService that will make your code cleaner: http://github.com/casidiablo/groundy you can use it from Maven or grab a jar from the download section https://github.com/casidiablo/groundy/downloads/ (latest one is the 0.7-SNAPSHOT). – Cristian Feb 13 '13 at 03:39
  • @Cristian Thank you, but I finally got it, it is not so complicated in the end. I made the IntentService also a bound service (overriding *onBind()*). This allows me to stop the service by just creating a method to do it and calling it as *mService.forceStop()*. I also created a method *mService.isRunning()* to check the service status. It is quite simple when you get it. – ilomambo Feb 13 '13 at 07:23
  • When you delegate the background work (making requests for data normally) to a thread running in a service, you need to be aware of all the headaches when communicating back to the main ui thread. Namely, how does your ui respond when it's currently backgrounded or destroyed and the request continues to run then completes (or even fails). AsyncTaskLoader and the LoaderManager listener callbacks are very helpful for that situation as no ui related commands will execute until the activity or fragment is foregrounded again. – worked Dec 28 '15 at 21:37
  • Adding to my above comment... This is also helpful for rotation, if either the request is currently running or has finished, either way a new request will not fire if the loader is found and/or is started, finishing like normal or returning the previously gotten data. Both cases might sound trivial, but trust me, it can quickly become a nightmare when a service is managing your requests in Android. – worked Dec 28 '15 at 21:42