IntentService 是Service的子类,因此它不是普通的Service,它比普通的service增加了额外的功能.
service 本身存在2个问题:
- Service不会专门启动一条单独的进程,Service与它所在的应用位于同一进程中.
- Service也不是专门一条新的线程,因此不应该在Service中直接处理耗时的任务.
开发者如果需要在Service中处理耗时操作,建议在service中另外开启一条新线程来处理该耗时操作, IntentService正好可以弥补上述两个不足,IntentService将会使用队列来管理请求的Intent,每当客户端代码通过Intent请求启动 IntentService时,IntentService会将该Intent加入到队列中 .然后开启一条新的worker 线程来处理该Intent 请求. 对于异步的startService( ) 请求,IntentService会按次序依次处理队列中 Intent,该线程保证同一时刻只处理一个 Intent.由于IntentService使用新的worker 线程处理 Intent请求.因此IntentService不会阻塞主线程,所以 IntentService自己就可以处理耗时操作.
IntentService具有如下特征:
- IntentService 会创建单独的 worker线程来处理所有的Intent请求.
- IntentService 会创建单独的 worker线程来处理 onHandleIntent( )方法实现的代码,因此开发者无须处理多线程问题.
- 当所有的请求处理完成后,IntentService会自动停止,因此开发者无须调用 stopSelf()来停止该 Service.
- 为 Service的onBind()方法提供了默认实现,默认实现的 onBind()方法,返回null.
- 为 Service的onStartComment()方法提供了默认实现,该实现会将请求Intent添加到队列中.
从上面的介绍可以看出,扩展 IntentService实现Service 无须重写 onBind()方法 onStartComment() 方法,只要重写 onHandleIntent( )方法即可.
下面的实例中的界面包含了两个按钮,一个启动普通的Service,一个启动IntentService,两个Service都需要处理耗时操作.
package com.test.service.intentservice;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import com.test.service.R;
public class IntentServiceActivity extends AppCompatActivity {
Button btnStartService, btnStartIntentService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intent_service);
btnStartService = (Button) findViewById(R.id.start_service2);
btnStartIntentService = (Button) findViewById(R.id.start_intent_service);
initListener();
}
private void initListener() {
//开启普通的 service
btnStartService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 创建需要启动的Service的Intent
Intent intent = new Intent(IntentServiceActivity.this, MyService.class);
// 启动Service
startService(intent);
}
});
//开启 IntentService
btnStartIntentService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startService(new Intent(IntentServiceActivity.this, MyIntentService.class));
}
});
}
}
普通的Service
该Service 执行 耗时任务任务 可能导致 ANR 异常
package com.test.service.intentservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
/**
* 普通的 Service
*
* 切勿忘记 在清单文件中配置
*/
public class MyService extends Service {
public MyService() {
}
@Override //必须实现的方法
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//该方法内执行 耗时任务任务 可能导致 ANR 异常
long endTime = System.currentTimeMillis() + 20 * 1000;
Log.d("MyService", "onStartCommand");
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Log.d("MyService", "耗时任务执行完成");
return START_STICKY;
}
}
IntentService
package com.test.service.intentservice;
import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
/**
* IntentService
*/
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
// IntentService 会使用单独的线程 来执行该方法的代码
@Override
protected void onHandleIntent(Intent intent) {
//该方法内执行耗时操作,比如下载文件等,此处只是让线程暂停 20秒
long endTime = System.currentTimeMillis() + 20 * 1000;
Log.d("MyIntentService", "onHandleIntent");
while (System.currentTimeMillis()<20){
try {
wait(endTime-System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Log.d("MyIntentService", "耗时操作执行完毕");
}
}