[关闭]
@xujun94 2016-07-22T16:24:06.000000Z 字数 7558 阅读 1079

IntentService使用及源码分析


转载请注明原博客地址: http://blog.csdn.net/gdutxiaoxu/article/details/52000680

本篇博客主要简介一下三个问题:

  1. 什么是IntentService?
  2. 怎样使用IntentService
  3. IntentSerice()源码分析

1)什么是IntentService?

我们知道Service和Activity一样是Android的四大组件之一,Service简称为后台服务,具有较高的优先级别。我们平时在Activity中直接开启Service,是运行在主线程的。如果想要执行耗时任务,我们必须自己开启线程。而IntentService是把任务放在子线程中执行的。

3. 任务执行完毕以后会自动退出Service,不需要我们自己处理

2)下面我们来看一下我们要怎样使用IntentService?

  1. public class MyIntentService extends IntentService {
  2. private static final String ACTION_DOWNLOAD = "com.szl.intentservicedemo.action.DOWNLOAD";
  3. private static final String ACTION_UPLOAD = "com.szl.intentservicedemo.action.UPLOAD ";
  4. private static final String EXTRA_PARAM1 = "com.szl.intentservicedemo.extra.PARAM1";
  5. private static final String EXTRA_PARAM2 = "com.szl.intentservicedemo.extra.PARAM2";
  6. public static final String TAG="tag";
  7. public MyIntentService() {
  8. super("MyIntentService");
  9. }
  10. //这里省略了若干个方法
  11. //处理我们启动的Service
  12. @Override
  13. protected void onHandleIntent(Intent intent) {
  14. if (intent != null) {
  15. final String action = intent.getAction();
  16. if (ACTION_DOWNLOAD.equals(action)) {
  17. final String param1 = intent.getStringExtra(EXTRA_PARAM1);
  18. final String param2 = intent.getStringExtra(EXTRA_PARAM2);
  19. handleDOwnload(param1, param2);
  20. } else if (ACTION_UPLOAD.equals(action)) {
  21. final String param1 = intent.getStringExtra(EXTRA_PARAM1);
  22. final String param2 = intent.getStringExtra(EXTRA_PARAM2);
  23. handleUpload(param1, param2);
  24. }
  25. }
  26. }
  27. }
  1. <service
  2. android:name=".MyIntentService"
  3. android:exported="false">
  4. </service>
  1. Intent intent = new Intent(context, MyIntentService.class);
  2. intent.setAction(ACTION_UPLOAD);
  3. intent.putExtra(EXTRA_PARAM1, param1);
  4. intent.putExtra(EXTRA_PARAM2, param2);
  5. context.startService(intent);

测试代码如下

  1. public void onButtonClick(View view) {
  2. switch (view.getId()) {
  3. case R.id.btn_download:
  4. MyIntentService.startActionDownLoad(MainActivity.this, "下载", "发起者主线程");
  5. break;
  6. case R.id.btn_upload:
  7. MyIntentService.startActionUpload(MainActivity.this, "上传", "发起者主线程");
  8. break;
  9. default:
  10. break;
  11. }
  12. }

运行以上测试程序,依次点击模拟上传和模拟下载,将可在我们的控制台上看到以下的log信息

控制台输出的Log


IntentService源码分析

这里先贴出IntentService的源码

  1. public abstract class IntentService extends Service {
  2. private volatile Looper mServiceLooper;
  3. private volatile ServiceHandler mServiceHandler;
  4. private String mName;
  5. private boolean mRedelivery;
  6. private final class ServiceHandler extends Handler {
  7. public ServiceHandler(Looper looper) {
  8. super(looper);
  9. }
  10. @Override
  11. public void handleMessage(Message msg) {
  12. onHandleIntent((Intent)msg.obj);
  13. stopSelf(msg.arg1);
  14. }
  15. }
  16. /**
  17. * Creates an IntentService. Invoked by your subclass's constructor.
  18. *
  19. * @param name Used to name the worker thread, important only for debugging.
  20. */
  21. public IntentService(String name) {
  22. super();
  23. mName = name;
  24. }
  25. /**
  26. * Sets intent redelivery preferences. Usually called from the constructor
  27. * with your preferred semantics.
  28. *
  29. * <p>If enabled is true,
  30. * {@link #onStartCommand(Intent, int, int)} will return
  31. * {@link Service#START_REDELIVER_INTENT}, so if this process dies before
  32. * {@link #onHandleIntent(Intent)} returns, the process will be restarted
  33. * and the intent redelivered. If multiple Intents have been sent, only
  34. * the most recent one is guaranteed to be redelivered.
  35. *
  36. * <p>If enabled is false (the default),
  37. * {@link #onStartCommand(Intent, int, int)} will return
  38. * {@link Service#START_NOT_STICKY}, and if the process dies, the Intent
  39. * dies along with it.
  40. */
  41. public void setIntentRedelivery(boolean enabled) {
  42. mRedelivery = enabled;
  43. }
  44. @Override
  45. public void onCreate() {
  46. // TODO: It would be nice to have an option to hold a partial wakelock
  47. // during processing, and to have a static startService(Context, Intent)
  48. // method that would launch the service & hand off a wakelock.
  49. super.onCreate();
  50. HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
  51. thread.start();
  52. mServiceLooper = thread.getLooper();
  53. mServiceHandler = new ServiceHandler(mServiceLooper);
  54. }
  55. @Override
  56. public void onStart(Intent intent, int startId) {
  57. Message msg = mServiceHandler.obtainMessage();
  58. msg.arg1 = startId;
  59. msg.obj = intent;
  60. mServiceHandler.sendMessage(msg);
  61. }
  62. /**
  63. * You should not override this method for your IntentService. Instead,
  64. * override {@link #onHandleIntent}, which the system calls when the IntentService
  65. * receives a start request.
  66. * @see android.app.Service#onStartCommand
  67. */
  68. @Override
  69. public int onStartCommand(Intent intent, int flags, int startId) {
  70. onStart(intent, startId);
  71. return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
  72. }
  73. @Override
  74. public void onDestroy() {
  75. mServiceLooper.quit();
  76. }
  77. /**
  78. * Unless you provide binding for your service, you don't need to implement this
  79. * method, because the default implementation returns null.
  80. * @see android.app.Service#onBind
  81. */
  82. @Override
  83. public IBinder onBind(Intent intent) {
  84. return null;
  85. }
  86. /**
  87. * This method is invoked on the worker thread with a request to process.
  88. * Only one Intent is processed at a time, but the processing happens on a
  89. * worker thread that runs independently from other application logic.
  90. * So, if this code takes a long time, it will hold up other requests to
  91. * the same IntentService, but it will not hold up anything else.
  92. * When all requests have been handled, the IntentService stops itself,
  93. * so you should not call {@link #stopSelf}.
  94. *
  95. * @param intent The value passed to {@link
  96. * android.content.Context#startService(Intent)}.
  97. */
  98. @WorkerThread
  99. protected abstract void onHandleIntent(Intent intent);
  100. }

源码分析

分析之前我们先来看一下Service生命周期

这里我们以startService()为例分析,从我们启动一个IntentService,调用的过程大概是这样的,

构造方法 ->onCreate()- >onStartCommand()- >onStart()->Service running-->

  1. public IntentService(String name) {
  2. super();
  3. mName = name;
  4. }

其实很简单,只是调用父类的构造方法,并保存我们的那么字段

  1. @Override
  2. public void onCreate() {
  3. super.onCreate();
  4. HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
  5. thread.start();
  6. mServiceLooper = thread.getLooper();
  7. mServiceHandler = new ServiceHandler(mServiceLooper);
  8. }

简单来说,就是为我们初始化一个线程thread并启动它,并将线程的looper与我们的mServiceHandler绑定在一起。
* 3)接着我们来看onStartCommand()方法做了什么?

  1. @Override
  2. public int onStartCommand(Intent intent, int flags, int startId) {
  3. onStart(intent, startId);
  4. return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
  5. }

我们可以看到在onStartCommand转调了onStart()方法

  1. @Override
  2. public void onStart(Intent intent, int startId) {
  3. Message msg = mServiceHandler.obtainMessage();
  4. msg.arg1 = startId;
  5. msg.obj = intent;
  6. mServiceHandler.sendMessage(msg);
  7. }

在onStart()方法里面其实就是用我们的mServiceHandler发送信息(mServiceHandler.sendMessage(msg);),这样在我们handleMessage()里面讲可以收到我们的信息,在handleMessage()里面有调用onHandleIntent()去处理我们的Intent,这就是为什么我们需要重写onHandleIntent的原因。

  1. private final class ServiceHandler extends Handler {
  2. public ServiceHandler(Looper looper) {
  3. super(looper);
  4. }
  5. @Override
  6. public void handleMessage(Message msg) {
  7. onHandleIntent((Intent)msg.obj);
  8. stopSelf(msg.arg1);
  9. }
  10. }
  1. mServiceLooper = thread.getLooper();
  2. mServiceHandler = new ServiceHandler(mServiceLooper);
  1. public void handleMessage(Message msg) {
  2. onHandleIntent((Intent)msg.obj);
  3. stopSelf(msg.arg1);
  4. }

到此IntentService源码分析位置

转载请注明原博客地址: http://blog.csdn.net/gdutxiaoxu/article/details/52000680

例子源码下载地址: http://download.csdn.net/detail/gdutxiaoxu/9583047

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注