介绍
在Android中可以通过Service和IntentService创建服务:
Service
这是适用于所有服务的基类。扩展此类时,必须创建一个用于执行所有服务工作的新线程,因为默认情况下,服务将使用应用的主线程,这会降低应用正在运行的所有 Activity 的性能。
IntentService
这是 Service 的子类,它使用工作线程逐一处理所有启动请求。如果您不要求服务同时处理多个请求,这是最好的选择。 您只需实现 onHandleIntent() 方法即可,该方法会接收每个启动请求的 Intent,使您能够执行后台工作。
IntentService的优点:
- 创建默认的工作线程,用于在应用的主线程外执行传递给 onStartCommand() 的所有 Intent,所以不需要我们再单独的创建线程。
- 传递到IntentService中的任务是逐一执行的,所以不需要担心出现多线程问题
- 执行完所有任务后自动停止服务,不需要调用stopSelf()。
由此可见,使用 IntentService 类实现服务也许是最好的选择,IntentService的使用流程和Service一样,但它只需要实现onHandleIntent()方法,下面看一个IntentService的使用示例:
使用示例
- 创建服务
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
for (int i = 0; i < 10; i++) {
Log.e("===","第"+i);
try {
Thread.sleep(1*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e("===","服务自动结束");
}
}
这个服务只是在onHandleIntent方法中模拟了一个10秒倒计时并且打印了数字,并且在onDestroy()中打印了“服务自动结束”
2. 注册服务
<service android:name=".MyIntentService"/>
3 启动服务
startService(new Intent(MainActivity.this,MyIntentService.class));
打印结果:
05-14 21:46:30.711 11817-11895/com.example.wangc.myapplication E/===: 第0
05-14 21:46:31.714 11817-11895/com.example.wangc.myapplication E/===: 第1
05-14 21:46:32.716 11817-11895/com.example.wangc.myapplication E/===: 第2
05-14 21:46:33.718 11817-11895/com.example.wangc.myapplication E/===: 第3
05-14 21:46:34.720 11817-11895/com.example.wangc.myapplication E/===: 第4
05-14 21:46:35.722 11817-11895/com.example.wangc.myapplication E/===: 第5
05-14 21:46:36.724 11817-11895/com.example.wangc.myapplication E/===: 第6
05-14 21:46:37.725 11817-11895/com.example.wangc.myapplication E/===: 第7
05-14 21:46:38.726 11817-11895/com.example.wangc.myapplication E/===: 第8
05-14 21:46:39.727 11817-11895/com.example.wangc.myapplication E/===: 第9
05-14 21:46:40.731 11817-11817/com.example.wangc.myapplication E/===: 服务自动结束
从上面这个简单的示例可以看到两点
一,并没有在onHandleIntent()方法中去创建新的线程执行任务;
二,在任务执行完成后并没有手动调用stopself()方法。
这两点都可以从接下来的源码分析中找到答案,先看下它的源码
源码分析
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
public IntentService(String name) {
super();
mName = name;
}
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onDestroy() {
mServiceLooper.quit();
}
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
去掉注释之后的源码就上面这点,根据它的工作流程分析:
首先在onCreate()方法中创建了一个HandlerThread(其实就是一个带有Looper的线程),然后启动这个线程,并且拿到线程的Looper对象。再传给ServiceHandler这个内部类。所以这里就解释了前面的问题,为什么不需要再自己创建工作线程,因为它内部已经帮我们创建好了。
onStartCommand()执行服务,它内部调用onStart()方法,onStart()方法内部创建Message,并通过ServiceHandler发送出去。
ServiceHandler处理在onStart()方法中发送的消息。在handleMessage()方法中先调用onHandleIntent()方法,我们要处理的具体业务逻辑就放在这个方法内。最后调用stopSelf(msg.arg1)结束服务;这也就是为什么我们不需要自己手动调用stopself()方法。
最后在onDestroy()方法中调用mServiceLooper.quit()退出Looper。
总结
在大多数时候都可以使用IntentService因为它使用更简单,我们只需要实现onHandleIntent()方法,并且不需要去主动停止服务。