I have the following design:
Activity/FragmentA upon a user action starts an AsyncTask to fetch a set of data.
While the AsyncTask is running, a progress indicator is displayed to the user.
When the AsyncTask finishes its task and fetches the resultset, it saves it in a singleton class serving as a shared datamodel.
When FragmentA is notified that the AsyncTask has finished (LocalBroadcastReceiver) then it start ActivityB/FragmentB which takes the set of results from the shared singleton and displays them in a ListView.
This works but since I am a newbie in android I am trying to understand and learn best practices.
E.g. I see a small delay from the time the progress bar is dismissed to the time the UI of ActivityB/FragmentB is displayed (during this latency the UI of ActivityA/FragmentA is still visible).
Also I think that somehow if the fetch of the items was done from FragmentB instead of FragmentA would make FragmentB "autonomous"
Overall can someone please help me understand how could I have implemented this differently using better/standard practices in android and the pros/cons of each approach?
Fragments
Fragments are small part of the activity which has their own life cycle, which provides developer more flexibility to deal with UI. Fragments has nothing to do with background processes.
Now your main question is about the background processes.
AsyncTask
This is nothing but the bit better version of thread with some predefined callbacks, when u need to perform some network operation which will take not more than 20 seconds, and after that it refreshes the UI, its better to use asycntask. Do not use Services (Avoid complexity, Keep it simple). You can use some third party library also.
IntentService
Now IntentService are better version of service, the main purpose of IntentService is to avoid performing long running operations on mainthread and provide queueing system to the developer. You should use services if you do not need user interaction while running long running operations (e.g syncing app with the server at the end of every day).
So for conclusion
User Interaction + short running network operation = AsyncTask
No User Interaction + long running network operation = IntentService + Broadcast Receiver to notify UI of needed
Related
How do I keep my android app running in the background even when it no longer has focus? What happens now is that, after being interruputed (e.g. a message arrives) and then when it gets the focus back, it just sits there with whatever had processed up to the point of interruption. Probably my design isn't so good since I can see no apparent way of having it resume from the point where it was interrupted. (One reason for the design is that it is imperative that output from a long-running query give intermediate results immediately instead of all at once at the end.)
I'd also like to be able to switch to another app but keep my app processing. I guess that amounts to the same situation as above.
Googling turned up service as a way of keeping an app running, but one hit suggested not to do this if the user must interact with the app, which is the case with my app.
I use one Asynctask to create my database (once; no problem so far if interrupted--on next execution, I just continue loading from where interrupted) and another AsyncTask to query it (this can be a very long-running task), but this approach doesn't keep the app running in the background. Any interruption either leaves output screen incomplete and dead or returns focus to user input screen.
Would changing the query feature (currently an AsyncTask) to a service be a good idea? Is it even feasible? (User doesn't interact with app during query.)
I currently have the following private classes:
private class DatabaseOpenHelper extends SQLiteOpenHelper
private class LoadDatabase extends AsyncTask<Object, Integer, Void>
private class QueryDB extends AsyncTask<Object, String, Void>
Your input will be appreciated.
EDIT
The first Answer below suggests that using Service will work.
I think that Googling has suggested that my task will be simpler if I extend IntentService.
ANOTHER EDIT
Yes, IntentService is exactly what I needed. See this. Changing from AsyncTask to IntentService is fairly straightforward.
For true background tasks the only standard way is service or your app can be killed.
Problems with AsyncTask:
non-static inner class can lead to memory leaks;
it tied to the lifecycle of a process (not the host Activity);
priority in the killing list is low;
Use service and send broadcast messages, form notifications to the user.
Note: by default services run in the UI thread, so still have to use threading.
IntentService is ok for serial tasks. If you want multiple parallel jobs extend Service.
What is the purpose with Service class?
Many examples with Bluetooth Low Energy uses Service classes for all Bluetooth communication, connecting, disconnecting, scanning for devices etc. Activity classes always call method from this Service class.
What about implementing all Bluetooth communication directly in an Activity class instead?. Why does nobody implement like that and uses a Service class instead?
From the documentation:
A Service is an application component that can perform long-running operations in the background and does not provide a user interface. Another application component can start a service and it will continue to run in the background even if the user switches to another application. Additionally, a component can bind to a service to interact with it and even perform interprocess communication (IPC). For example, a service might handle network transactions, play music, perform file I/O, or interact with a content provider, all from the background.
Basically it is a loosly coupled component independet from activitys lifecylce. The problem is in Android you can't really control when an activity will be created/destroyed, so for example if you are loading somenthing in an activity and you receive a call, your activity might get destroyed and the result of your update will be lost, or even worst your loading task won't finish and holds on to the activity and it can't be garbage collected and you create a memory leak.
So you use service for long running background tasks, but you just let them run as long as you have to, to avoid, again, memory leaks and be nice to your resources.
Caution: It's important that your application stops its services when it's done working, to avoid wasting system resources and consuming battery power. If necessary, other components can stop the service by calling stopService(). Even if you enable binding for the service, you must always stop the service yourself if it ever received a call to onStartCommand().
what about implementing all Bluetooth communication directly in an Activity class instead
you most likely end being killed by the framework for doing too much on UI thread (aka ANR - Application Not Responding). See Keeping Your App Responsive article on develoer site.
Anything that is not directly related to UI (like networking of any kind) should be offloaded to separate task. Be it AsyncTask:
This class allows to perform background operations and publish results
on the UI thread without having to manipulate threads and/or handlers.
or IntentService:
IntentService is a base class for Services that handle asynchronous
requests (expressed as Intents) on demand.
. The Service (not IntentService) is for slightly different purpose:
A Service is an application component representing either an
application's desire to perform a longer-running operation while not
interacting with the user or to supply functionality for other
applications to use.
Service class is used to perform , background non UI operations like playing audio file.Further service is the component that will run in background even if your activity gets destroyed ,While using Bluetooth we really do some non UI phone level operation and hence we use Services .
Activity class isn't a good place for any kind of communication tasks. It can be killed as soon as user switches to another activity. It shows UI, that means that we can't do much work in Activity's thread. Sometimes you can use somthing like
Thread t = new Thread(new Runnable() {
#Override
public void run() {
// do something here
}
});
t.start();
or more complicated things with AsyncTask but this is suitable for short-time actions.
Service will not be killed so fast, so it's good for background work of any kind. Just read Android documentation about services.
I'm developing an app which must heavily interact with the server.So user input name and password and after authorization the next tasks must be performed:
The app has to fetch all incoming and outcoming messages for this user and load them to SQLite database.
Fetch all user friends (JSON with id,names,contact_data) and also load it to the app's database
Jump to the next activity and display income messages from the local database.
The problem this operations are too slow and when app starts new activity it is nothing to fetch from the database :AsyncTasks have not completed yet.I'm forced to use AsyncTask.get() in order to wait when they all complete but this takes over 16 seconds to wait!So what should I do: use threads, or before loading fetched data to database hold it in memory and display it in the new activity instead of fetching it from the database?But even without database tasks other fetching tasks take nearly 10 seconds to wait!So what should I do?
Oke a couple of things going pretty wrong here.
Do not use AsyncTasks for Networking. Use a service. In short, this is because your AsyncTask will stop, as soon as the Activity that started it will stop. This means that network requests get aborted easily and data goes lost and has to re-start again when the Activity is opened again.
Do not use .get() on AsyncTasks. This makes the UI thread wait for the task to complete, making the whole AsyncTask idea kinda useless. In other words: This blocks your UI.
What you should do:
Read up on using services. You can also have a look at a great opensource library called RoboSpice to help you with this.
Stop using .get() on AsyncTasks, if you want to know when it is done just use a listener.
Execute AsyncTasks on a threadpool ( myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); ) when possible.
You should use a Service. This way it always can complete the tasks it was doing and you can complete all your tasks. Besides that you should initialize the app once, and after that only update the data.. that can't take 10 seconds.. than you're having an other problem.. But the nice thing of the service is that this can run in the background. see: Services in Android Tutorial
== Edit
Also take a look at GreenDao This library arranges fast SQlLite operations. Without the large setup!
AsyncTasks are not meant to run several small tasks concurrently at the same time. Quoting the docs
When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.
Use Threads in a ThreadPool when you want to run multiple tasks concurrently.
How you want to handle this situation is up to you. When the background tasks take too long, you can always show an alert dialog to the user and then take them to the activity once the data has been populated. Many apps show a 'Loading' screen when this happens. You can also show the 'Loading' Spinner control if no data is available yet. Never show a blank screen.
If the server side calls are under your control, employ some sort of caching to speed up the time. Any API call that lasts more than a second will make for an impatient user. If not employ one of the techniques mentioned in the previous paragraph. #Perception's technique is also one to consider if you can do it.
I am developing a Multiplayer Online word game on Android and would like to implement a thread that checks for server side events like the following:
Player join a game.
Player left a game.
Player won a game.
etc...
The thread will be responsible for listening for all kinds of events and dispatching events to the responsible activity If it's visible to the user.
In other words to be more clear, I've got a list of event and each activity must register to a subset of these events.
Events:
E1 - E2 - E3 - E4
Activities:
Activity 1 interested in E1 and E2.
Activity 2 interested in E1, E2 and E3.
Activity 3 interested in E3 and E4.
I am asking about the best design approach to implement a thread that runs in the background and can dispatch events to all activities?
Some Ideas:
-Implement an AsyncTask on the application level.
-Send broadcast intents to a custom actions.
-A service is not the best approach because it should be created to run in the background when the user is not interacting with your application.
Can you propose a best practice approach?
A good approach for this is to use a Service combined with AsyncTasks.
While a Service is useful while the user is not interacting with your application, that certainly isn't its only use. A Service is the logical home of anything that does not require a UI.
In data driven apps, I have used Services as API adapter layers. It is nice because I can launch it from any activity without worrying about whether it is already instantiated or whether I need to do any cleanup work after I'm done. The framework manages the service's lifecycle and tracks clients.
I think your case is similar. Each activity can use bindService and unbindService to register for updates as long as it needs. The service will continue to do its thing as long as any Activity is bound. The service can keep track of which activities need updates using the Intents received in onBind and onUnbind, and send them updates via specific Intents, or, more appropriately, the service can fire broadcast intents and the Activities can register for what they need.
Within the Service, you would run AsyncTasks (probably running them on AsyncTask.THREAD_POOL_EXECUTOR so you get more than one thread) to do your updates. Remember that the service itself is launched on the UI thread.
Another nice benefit to using a service is that it doesn't require an Activity to run. One use for this that comes to mind is post-shutdown cleanup. If you need to post scores or analytics or something when the user exits, you can allow the activity to close quickly and finish the longer-running work in the background.
Activities can request those longer individual tasks from the Service using startService, and the service won't exit until it calls stopSelf (or stopSelfResult).
The combination of start/stop and bind/unbind really allows for clean management of the service. It will run when and only when it needs to, and you can keep all your API access in one place.
Edit:
As if this wasn't a stout enough wall of text, I've come up with another good reason to use a Service. From the developer guide on processes & threads:
Because a process running a service is ranked higher than a process
with background activities, an activity that initiates a long-running
operation might do well to start a service for that operation, rather
than simply create a worker thread—particularly if the operation will
likely outlast the activity...
Can someone tell me the TRUE difference?
My rule of thumb is that an AsyncTask is for when I want to do something tied to single Activity and a Service is for when I want to do something that will carry on after the Activity which started it is in the background.
So if I want to do a small bit of background processing in the Activity without tying up the UI I'll use an AsyncTask. I'll then use the default Handler from that Activity to pass messages back to ensure updates happen on the main thread. Processing the updates on the main thread has two benefits: UI updates happen correctly and you don't have to worry so much about synchronisation problems.
If for example, I wanted to do a download which might take a while I'd use a Service. So if I went to another Activity in my application or another application entirely my Service could keep running and keep downloading the file so it would be ready when I returned to my application. In this case I'd probably use a Status Bar Notification once the download was complete, so the user could choose to return to my application whenever was convenient for them.
What you'll find if you use an AsyncTask for a long-running process it may continue after you've navigated away from the Activity but:
If the Activity is in the background when your processing is complete you may have problems when you try to update the UI with the results etc.
A background Activity is far more likely to be killed by Android when it needs memory than a Service.
Use Service when you've got something that has to be running in the background for extended periods of time. It's not bound to any activity. The canonical example is a music player.
AsyncTask is great when some stuff has to be done in background while in the current activity. E.g. downloading, searching for text inside a file, etc.
Personally I use Handlers only to post changes to the UI thread. E.g. you do some computations in a background thread and post the result via handler.
The bottom line: in most cases, AsyncTask is what you need.
To complement the other answers here regarding the distinction between service and AsyncTask, it is also worth noting[0]:
A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of.
A Service is not a thread. It is not a means itself to do work off of the main thread (to avoid Application Not Responding errors).
Services tend to be things that describes a significant part of your application - rather than an AsyncTask which is typically contributes to an Activity and/or improves UI responsiveness. As well as improving code clarity Services can also be shared with other applications, providing clear interfaces between your app and the outside world.
Rather than a book I would say the developer guide has lots of good answers.
[0] Source: http://developer.android.com/reference/android/app/Service.html#WhatIsAService
AsyncTask: When I wish to do something without hanging the UI & reflect the changes in the UI.
E.g.: Downloading something on Button Click, remaining in the same activity & showing progress bar/seekbar to update the percentage downloaded. If the Activity enters the background, there are chances of conflict.
Service: When I wish to do something in the background that doesn’t need to update the UI, use a Service. It doesn’t care whether the Application is in the foreground or background.
E.g.: When any app downloaded from Android Market shows notification in the Status Bar & the UI returns to the previous page & lets you do other things.
Service
A Service is an application component that can perform long-running operations in the background and does not provide a user interface. Another application component can start a service and it will continue to run in the background even if the user switches to another application. Additionally, a component can bind to a service to interact with.
When to use?
Task with no UI, but shouldn’t be too long. Use threads within service for long tasks.
Long task in general.
Trigger: Call to method onStartService()
Triggered from: Any Thread
Runs on: Main thread of its hosting process. The service does not create its own thread and does not run in a separate process (unless you specify otherwise)
Limitations / Drawbacks: May block main thread
AsyncTask
AsyncTask enables the proper and easy use of the UI thread. This class allows performing background operations and publishing results on the UI thread without having to manipulate threads and/or handlers. An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread.
When to use?
Small task having to communicate with main thread
For tasks in parallel use multiple instances OR Executor
Disk-bound tasks that might take more than a few milliseconds
Trigger: Call to method execute()
Triggered from: Main Thread
Runs on: Worker thread. However, Main thread methods may be invoked in between to publish progress.
Limitations / Drawbacks:
One instance can only be executed once (hence cannot run in a loop)
Must be created and executed from the Main thread
Ref Link