Independence Day: All apps run in their own process
All applications run in their own process and are built using 4 key components
- Activities – typically the screen that the user sees
- Services – a component that does work in the background
- Content providers – a component that manages a shared set of data
- Broadcast receivers – a component that responds to a broadcast message
Apps are isolated from each other as each Android application runs in its own process
Don’t re-invent the wheel
Instead of duplicating code, your apps can use another app’s components.
Your app can use another app’s components
When your app starts, and none of its components are running, the system starts a new process.
If you start a component in another app, it runs in the process for that app, not in yours.
It’s all about memory
All processes are kept alive in memory for as long as possible. Even when you exit an app, its processes may be kept alive in memory – maybe the process is shared by another app, and in some cases the process is kept alive in case it’s needed again.
Processes are killed when memory is needed for the more important processes.
It’s vicious man!
Processes don’t shut down cleanly. They can be killed for their memory at any time. Bad luck for any components they contain as they’re killed too.
Android follows a set of rules when deciding which processes to kill – depending on the state of any components that may be running in the process. The rules are based on two facts:
- How important is the process to the user’s current experience
- How long has it been since the process was last used
Survival of the fittest: The Process lifecycle
Android kills the process once it has decided to do so and releases the resources so that they can be used elsewhere. Processes with the lowest importance are killed first.
Android can re-launch an app (the process) based on its last state when the process was killed. Have a look at the article, Persisting the Activity Instance State.
You should structure your app so that its priority will make sure that it is not killed while it is doing something important.
The process lifecycle
Death or glory: The process lifecycle hierarchy
- Active process – active processes have components that the user is interacting with. Android will try to keep these processes alive by reclaiming memory elsewhere
- Visible process – these have visible activities which are not in the foreground. The user is not interacting with them. These processes will only be killed under extreme circumstances
- Service process – they have running services and are treated as an Active process. They won’t be killed unless their resources are badly needed
- Background process– these contain activities that are not visible. There is no user interaction with them. They can be killed at any time. These processes are killed according to the last-seen-first-killed principle
- Empty process – they don’t have any active application components. They’re only kept alive to improve start-up time when next the component is needed. These processes are killed when resources are needed
Android ranks a process at the highest level it can, based on the importance of components currently active in the process. So, for example, if a process has a visible activity and a running service, it will be ranked as a visible process.
A processes’ rank can also increase if other processes are dependent on it (other apps are using components in this process) – processes can’t be ranked lower than the process it is serving.
If you’re doing a long-running background operation, like file uploads, rather use a service to do it. Its process is less likely to be killed. On the other hand, using a background thread ranks its process as a background process which is more likely to be killed for its resources.
Similarly broadcast receivers should also use services rather than background threads.
Your next tattoo: Thread rules
Bear the following in mind when working with threads:
- Don’t block the Main thread
- Don’t try and access the UI Toolkit (the elements that the user interacts with) directly from the worker thread
King of the castle: The Main thread
All apps, when started, run in a single Main thread. It’s also known as the User Interface (or UI) thread.
All components that run in the same process run in this thread.
Everything runs on a single thread by default
But there’s the problem!
Running everything on a single thread can result in poor response times and the display of the dreaded Application Not Responding dialog:
The ANR dialog informs the user of the problem and allows them to exit the app
You should design your app so that this dialog never appears.
So what triggers the ANR dialog?
- If an app can’t respond to user input within 5 seconds
- If Broadcast receivers haven’t finished executing within 10 seconds
How can you avoid the ANR dialog?
Most importantly, don’t block the main thread.
Any method running in the main thread should do as little work as possible in the main thread.
Do as little work as possible in your activity’s onCreate and onResume methods.
Use separate threads for long-running tasks. Such as file operations, network look-ups, database transactions, and complex calculations
Android offers a number of alternatives for moving your processing to the background.
- You can use your own Threads and use the Handler class to notify the main thread when the work is done
- You can use the AsyncTask class to do the work in the background. Have a look at the tutorial, Using an AsyncTask to download a file. Their downfall is that AsyncTasks are killed when the activity is killed. They’re ideal for short-lived background tasks. Use a service for longer running operations
- Use Loaders for asynchronous data loading. Have a look at the tutorial, Loading data using Android’s Loaders
- IntentServices are the best practice for background services performing set tasks like internet updates or data processing. They process the work on a background thread for you and pass results to the main thread. Have look at the tutorial, Using an IntentService to do background work
- You can use Broadcast receivers to do small amounts of work in the background like saving a setting or registering a notification. Instead of using threads for intensive tasks, use an IntentService for long-running work in response to an intent broadcast
You may want to investigate StrictMode which can help you find long-running operations on the main thread.
If you are doing work in the background, you should:
- Show the progress – you could use a progress bar to do this
- Use a splash screen for initial setup to indicate loading in progress
Using a separate thread to free the Main thread
If you use a separate thread then remember not to access the User Interface directly from the worker thread.
Don’t kill me, keep me running in the background
Sometimes you may want an operation to continue in the background without being killed, like playing music for example.
Broadcast Receivers run on the main thread but you can use them to run an application in the background for a short time (less than 10 seconds).
Broadcast Receivers can launch an app even if it is not running. They’re great for posting notifications.
You can use a Broadcast Receiver to start a service.
Services run on the main thread but you can use them for long-running background operations.
If you’re using a Service to do long-running operations, then get the Service to start a separate thread to perform the work.
A number of Services can run at the same time which could result in a memory shortage. If memory is needed, processes hosting Services will, like background processes, be killed. Android will restart them later if needed when memory is available.
You can request that a Service run in the foreground so they won’t be killed. This is useful for playing music for example. If you do this, you must send a notification to the user notifying them that the Service is running.
Have a look at our Using Threads Tutorial where we show you how to use threads to do background work.
I hope that you have found this tutorial helpful.