下载demo:http://download.youkuaiyun.com/detail/u013100574/9679069
简介
IntentService是继承于Service并处理异步请求的一个类,在 IntentService 内有一个工作线程来处理耗时操作,启动 IntentService 的方式和启动传统 Service 一样
1. IntentService 与Service 对比
先看Service本身存在两个问题:
- Service不会专门启动一条单独的进程,Service与它所在应用位于同一个进程中;
- Service也不是专门一条新线程,因此不应该在Service中直接处理耗时的任务;
IntentService特征
- 会创建独立的worker线程来处理所有的Intent请求;
- 会创建独立的worker线程来处理onHandleIntent()方法实现的代码,无需处理多线程问题;
- 所有请求处理完成后,IntentService会自动停止,无需调用stopSelf()方法停止Service;
- 为Service的onBind()提供默认实现,返回null;
- 为Service的onStartCommand提供默认实现,将请求Intent添加到队列中;
- 另外,可以启动 IntentService 多次,而每一个耗时操作会以工作队列的方式在IntentService 的 onHandleIntent 回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。
2.比较Service 和 IntentService 处理耗时操作的结果
首先创建一个 Service 服务,在其 onStartCommand() 中执行一个20s的耗时。
MyService .class
package com.app.service;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
/**
* author: Yangbin
* time : 2016/11/10 14:27
* desc :
*/
public class MyService extends Service {
String TAG = "MyService";
public static void startMyService(Context mContext) {
Intent intent = new Intent(mContext, MyService.class);
mContext.startService(intent);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "-->开始睡眠");
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "-->睡眠结束");
return super.onStartCommand(intent, flags, startId);
}
}
注册服务
<service android:name=".MyService" />
启动服务
for (int i = 0; i < 20; i++) {
MyService.startMyService(this);
}
运行结果
运行结果ANR错误
然后试试 IntentService
IntentService 默认实现了 OnBind(),返回值为 null。
IntentService 必须实现 MyIntentService() 构造方法和 onHandleIntent(Intent intent)。
注意:
IntentService 的构造函数一定是参数为空的构造函数,然后再在其中调用 super(“name”) 这种形式的构造函数。 因为
Service 的实例化是系统来完成的,而且系统是用参数为空的构造函数来实例化Service的。
MyIntentService .class
package com.app.service;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
/**
* author: Yangbin
* time : 2016/11/10 12:28
* desc :
*/
public class MyIntentService extends IntentService {
String TAG = "MyIntentService";
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
Log.d(TAG, "-->开始睡眠");
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "-->睡眠结束");
}
public static void startMyIntentService(Context mContext) {
Intent intent = new Intent(mContext, MyIntentService.class);
mContext.startService(intent);
}
}
和上面Service一样的启动和注册
结果正常运行,没有ANR
截取部分日志
结果是20组 有序的这样开始-结束 开始-结束,所以IntentService是等前面的请求结束之后再执行下一个。 这个证实了 IntentService 采用单独的线程每次只从队列中拿出一个请求进行处理
3.IntentService 的生命周期和执行过程
我把生命周期方法全打印出来了,待会我们来看看它执行的过程是怎样的。
MyIntentService2 .class
package com.app.service;
import android.app.IntentService;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
/**
* author: Yangbin
* time : 2016/11/10 14:24
* desc :
*/
public class MyIntentService2 extends IntentService {
String TAG = "MyIntentService2";
public MyIntentService2() {
super("MyIntentService2");
}
@Override
public void onCreate() {
Log.d(TAG, "onCreate");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onStart(Intent intent, int startId) {
Log.d(TAG, "onStart");
super.onStart(intent, startId);
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind");
return super.onBind(intent);
}
@Override
public void setIntentRedelivery(boolean enabled) {
super.setIntentRedelivery(enabled);
Log.d(TAG, "setIntentRedelivery");
}
@Override
protected void onHandleIntent(Intent intent) {
//Intent是从Activity发过来的,携带识别参数,根据参数不同执行不同的任务
String action = intent.getExtras().getString("param");
Log.d(TAG, "获取参数:" + action);
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy");
super.onDestroy();
}
}
接下来是 Activity,在 Activity 中创建2个带不同值的 Intent 来启动 IntentService:
MainActivity.class
package com.app.service;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Operation 1
Intent startServiceIntent = new Intent(this, MyIntentService2.class);
Bundle bundle = new Bundle();
bundle.putString("param", "oper1");
startServiceIntent.putExtras(bundle);
startService(startServiceIntent);
//Operation 2
Intent startServiceIntent2 = new Intent(this, MyIntentService2.class);
Bundle bundle2 = new Bundle();
bundle2.putString("param", "oper2");
startServiceIntent2.putExtras(bundle2);
startService(startServiceIntent2);
}
}
运行结果
从结果可以看到,onCreate 方法只执行了一次,而 onStartCommand 和 onStart 方法执行了两次,开启了两个 Work Thread,这就证实了之前所说的,启动多次,但IntentService 的实例只有一个,这跟传统的 Service 是一样的。Operation1 也是先于 Operation2 打印,并且我让两个操作间停顿了20s,最后是 onDestroy 销毁了IntentService。
4 . 总结
这就是IntentService,一个方便我们处理业务流程的类,它是一个Service,但是比Service更智能。
个人觉得,IntentService 为什么可以处理耗时任务? 应该从源码上面来分析,IntentService 是直接继承与 Service的,继承Service后 它的代码一共就100多行。
内部在 onCreate()时,新建了一个HandlerThread 实例。
(HandlerThread 是一个Thread的 子类,HandlerThread 内部 有点线我们的UI线程,内部一个Looper loop循环一直轮询消息 获得消息 处理消息。)
而IntentService, 内部有一个Handler子类 ServiceHandler,它的Looper用的是这个HandlerThread 的Looper,IntentSerivce 在onStart()通过发送Message,ServiceHandler在处理Message 调用的是 onHandleIntent。 所以
简单的说一个IntentService,内部就创建了一个线程,通过Android提供的 Handler Message Looper,这些消息处理的类 构成了一个消息处理的模型。所以IntentService 的onHandleIntent 这个方法其实是在IntentService 中开辟的一个子线程中处理的。
下载demo:
[http://download.youkuaiyun.com/detail/u013100574/9679069]