Training—Running in a Background Service
阅读:http://developer.android.com/training/run-background-service/index.html
The
IntentService
class provides a straightforward structure for running an operation on a single background thread. This allows it to handle long-running operations without affecting your user interface's responsiveness. Also, anIntentService
isn't affected by most user interface lifecycle events, so it continues to run in circumstances that would shut down anAsyncTask
An
IntentService
has a few limitations:
- It can't interact directly with your user interface. To put its results in the UI, you have to send them to an
Activity
.- Work requests run sequentially. If an operation is running in an
IntentService
, and you send it another request, the request waits until the first operation is finished.- An operation running on an
IntentService
can't be interrupted.However, in most cases an
IntentService
is the preferred way to simple background operations.
IntentService拥有自己的一个线程,但是它有相对的限制:
1、不能处理UI,因为UI控制必须在UI线程;
2、你传递给他的认识将会排成队列一个个来,也就是说串行运行,一个任务直到运行完了才运行下个任务;
3、无法被打断;
public class RSSPullService extends IntentService { @Override protected void onHandleIntent(Intent workIntent) { // Gets data from the incoming Intent String dataString = workIntent.getDataString(); ... // Do work here, based on the contents of dataString ... } }
a simple example,就是你用intent启动的时候它去获取数据并且开始做事情。
<application android:icon="@drawable/icon" android:label="@string/app_name"> ... <!-- Because android:exported is set to "false", the service is only available to this app. --> <service android:name=".RSSPullService" android:exported="false"/> ... <application/>
声明。要注意这里并没有过滤器,这意味着,只有本程序能调用这个service。
调用它吧:
/* * Creates a new Intent to start the RSSPullService * IntentService. Passes a URI in the * Intent's "data" field. */ mServiceIntent = new Intent(getActivity(), RSSPullService.class); mServiceIntent.setData(Uri.parse(dataUrl)); // Starts the IntentService getActivity().startService(mServiceIntent);
启动了它,当然要在它的运行过程中获取它的相关信息。
To send the status of a work request in an
IntentService
to other components, first create anIntent
that contains the status in its extended data. As an option, you can add an action and data URI to thisIntent
.Next, send the
Intent
by callingLocalBroadcastManager.sendBroadcast()
. This sends theIntent
to any component in your application that has registered to receive it. To get an instance ofLocalBroadcastManager
, callgetInstance()
.
通过intent来发送状态,然后使用 LocalBroadcastManager.sendBroadcast()来发送给所有已经注册了的组件(- -跟设计模式一模一样嘛)。
public final class Constants { ... // Defines a custom Intent action public static final String BROADCAST_ACTION = "com.example.android.threadsample.BROADCAST"; ... // Defines the key for the status "extra" in an Intent public static final String EXTENDED_DATA_STATUS = "com.example.android.threadsample.STATUS"; ... } public class RSSPullService extends IntentService { ... /* * Creates a new Intent containing a Uri object * BROADCAST_ACTION is a custom Intent action */ Intent localIntent = new Intent(Constants.BROADCAST_ACTION) // Puts the status into the Intent .putExtra(Constants.EXTENDED_DATA_STATUS, status); // Broadcasts the Intent to receivers in this app. LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent); ... }
然后接下来你就写一个继承BroadcastReceiver的类去接受intent。而上面所提到的注册就是声明一个过滤器来获取广播了,例如:
// Class that displays photos public class DisplayActivity extends FragmentActivity { ... public void onCreate(Bundle stateBundle) { ... super.onCreate(stateBundle); ... // The filter's action is BROADCAST_ACTION IntentFilter mStatusIntentFilter = new IntentFilter( Constants.BROADCAST_ACTION); // Adds a data filter for the HTTP scheme mStatusIntentFilter.addDataScheme("http");
// Instantiates a new DownloadStateReceiver DownloadStateReceiver mDownloadStateReceiver = new DownloadStateReceiver(); // Registers the DownloadStateReceiver and its intent filters LocalBroadcastManager.getInstance(this).registerReceiver( mDownloadStateReceiver, mStatusIntentFilter); ...
动态绑定intent和receiver。
A single
BroadcastReceiver
can handle more than one type of broadcastIntent
object, each with its own action. This feature allows you to run different code for each action, without having to define a separateBroadcastReceiver
for each action. To define anotherIntentFilter
for the sameBroadcastReceiver
, create theIntentFilter
and repeat the call toregisterReceiver()
. For example:
当然,一个receiver是可以绑定多个intent的。
Sending an broadcast
Intent
doesn't start or resume anActivity
. TheBroadcastReceiver
for anActivity
receives and processesIntent
objects even when your app is in the background, but doesn't force your app to the foreground. If you want to notify the user about an event that happened in the background while your app was not visible, use aNotification
. Never start anActivity
in response to an incoming broadcastIntent
.
请注意service的intent并不会启动activity,你也不应该启动或者强迫activity到前台,如果你需要传递信息,使用Notification。