后台处理指南
后台处理指南 | Android 开发者 | Android Developers https://developer.android.google.cn/guide/background?hl=zh-cn
Processing data in the background is an important part of creating an Android application that is both responsive for your users as well as a good citizen on the Android platform. Doing work on the main thread can lead to poor performance and therefore a poor user experience.
This guide explains what qualifies as background work, defines background task categories, provides you with criteria to categorize your tasks, and recommends APIs that you should use to execute them.
Core principle
In general, you should take any blocking tasks off the UI thread. Common long-running tasks include things like decoding a bitmap, accessing storage, working on a machine learning (ML) model, or performing network requests.
Definition of background work
An app is running in the background when both the following conditions are satisfied:
- None of the app's activities are currently visible to the user.
- The app isn't running any foreground services that started while an activity from the app was visible to the user.
Otherwise, the app is running in the foreground.
Note: Consider a case in which a foreground service starts while an activity from the app is visible to the user. The user subsequently navigates away from the app and returns to the home screen. In such cases, the app is running in the foreground until the service's lifecycle ends.
Common types of background work
Background work falls into one of three primary categories:
- Immediate: Needs to execute right away and complete soon.
- Long Running: May take some time to complete.
- Deferrable: Does not need to run right away.
Likewise, background work in each of these three categories can be either persistent or impersistent:
- Persistent work: Remains scheduled through app restarts and device reboots.
- Impersistent work: No longer scheduled after the process ends.
Figure 1: Types of background work.
Approaches to background work
You should approach impersistent or persistent work differently:
- All persistent work: You should use WorkManager for all forms of persistent work.
- Immediate impersistent work: You should use Kotlin coroutines for immediate impersistent work. For Java programming language users, read the guide on threading for recommended options.
- Long-running and deferrable impersistent work: You shouldn't use long-running and deferrable impersistent work. You should instead complete such tasks through persistent work using WorkManager.
The following table lays out which approach you should take for each type of background work.
Category | Persistent | Impersistent |
---|---|---|
Immediate | WorkManager | Coroutines |
Long running | WorkManager | Not recommended. Instead, perform work persistently using WorkManager. |
Deferrable | WorkManager | Not recommended. Instead, perform work persistently using WorkManager. |
Immediate work
Immediate work encompasses tasks which need to execute right away. These are tasks which are important to the user or which you otherwise can't schedule for deferred execution at a later time. They are important enough that they might need to remain scheduled for prompt execution even if the app closes or the device restarts.
Recommended solution
For persistent immediate work, you should use WorkManager with a OneTimeWorkRequest
. Expedite a WorkRequest with setExpedited()
.
For impersistent immediate work, you should use Kotlin coroutines. If your app uses the Java programming language, you should use RxJava or Guava. You can also use Executors
.
Examples
- An app needs to load data from a data source. However, making such a request on the main thread blocks it and causes UI jank. The app instead makes the request off the main thread in a coroutine.
- An app needs to send a message in a chat app. The app creates a
Worker
and enqueues the task as aWorkRequest
. It expedites theWorkRequest
withsetExpedited()
.
Long-running work
Work is long running if it is likely to take more than ten minutes to complete.
Recommended solution
WorkManager allows you to handle such tasks using a long-running Worker
.
Note: Where possible, you should chunk workloads and handle tasks as deferrable work. Only use a long-running Worker
where you can't chunk your workload.
Example
An app needs to download a large file which you can't chunk. It creates a long-running Worker
and enqueues the download. The app then downloads the file in the background over fifteen minutes.
Deferrable work
Deferrable work is any work that does not need to run right away.
Recommended solution
Scheduling deferred work through WorkManager is the best way to handle tasks that don't need to run immediately but which ought to remain scheduled when the app closes or the device restarts.
Example
An app wants to regularly sync data with a backend. The user does not trigger the sync, and the work should take place when the device is idle. The recommended approach is to use a PeriodicWorkRequest
with a custom Worker
and constraints for these scenarios.
Alarms
Alarms are a special use case that are not a part of background work. You should execute background work through the two solutions outlined above, coroutines and WorkManager.
You should only use AlarmManager only for scheduling exact alarms such as alarm clocks or calendar events. When using AlarmManager to schedule background work, it wakes the device from Doze mode and its use can therefore have a negative impact on battery life and overall system health. Your app is responsible for such impacts.
Replace foreground services
Android 12 restricts launching foreground services from the background. For most cases, you should use setForeground()
from WorkManager rather than handle foreground services yourself. This allows WorkManager to manage the lifecycle of the foreground service, ensuring efficiency.
You still should use foreground services to perform tasks that are long running and need to notify the user that they are ongoing. If you use foreground services directly, ensure you shut down the service correctly to preserve resource efficiency.
Some use cases for using foreground services directly are as follows:
- Media playback
- Activity tracking
- Location sharing
- Voice or video calls
后台处理指南
为了创建既能迅速响应用户、又能遵守 Android 平台政策规定的 Android 应用,在后台处理数据是重要的一环。本指南定义了后台任务类别、提供了任务分类标准,并推荐了执行任务所应使用的 API。
指导原则
一般来说,运行时间超过几毫秒的所有任务都应委派给台线程。长时间运行的常见任务包括解码位图、访问存储空间、处理机器学习 (ML) 模型、执行网络请求等。
后台任务的类别
后台任务分为以下几个主要类别:
- 即时任务
- 延期任务
- 精确任务
如需对任务进行分类,请回答以下问题,并遍历图 1 中的相应决策树:
- 任务是否需要在用户与应用进行互动时完成?
- 如果是,则应将此任务归类为即时任务。 如果不是,请继续回答第二个问题。
- 任务是否需要在精确的时间点运行?
- 如果您确实需要在精确的时间点运行任务,则应将任务归类为精确任务。
大多数任务不需要在精确的时间点运行。通常,任务允许运行的时间点存在细微差异,具体取决于网络可用性和剩余电量等条件。无需在精确时间点运行的任务应归类为延期任务。
图 1. 此决策树可帮助您确定哪个类别最适合您的后台任务。
推荐的解决方案
下面几部分将介绍针对各个后台任务类型的推荐解决方案。
即时任务
对于应在用户离开特定作用域或完成某项互动时结束的任务,我们建议使用 Kotlin 协程。许多 Android KTX 库都包含适用于常见应用组件(如 ViewModel
)和常见应用生命周期的现成可用的协程作用域。
如果您是 Java 编程语言用户,请参阅 Android 上的线程处理,了解推荐的选项。
对于应立即执行并需要继续处理的任务,即使用户将应用放在后台运行或重启设备,我们也建议使用 WorkManager
并利用其对长时间运行的任务的支持。
在特定情况下(例如使用媒体播放或主动导航功能时),您可能希望直接使用前台服务。
延期任务
凡是不直接与用户互动相关且日后可随时运行的任务,都可以延期执行。建议为延期任务使用 WorkManager
解决方案。
如果您希望某些可延期异步任务即使在应用退出或设备重启后仍能正常运行,使用 WorkManager
可以轻松地调度这些任务。如需了解如何调度这些类型的任务,请参阅 WorkManager
相关文档。
精确任务
需要在精确时间点执行的任务可以使用 AlarmManager
。
如需详细了解 AlarmManager
,请参阅设置重复闹铃时间。