定义
IntentService继承与Service,用来处理异步请求,客户端通过startService(Intent)方法传递请求给IntentService,IntentService在onCreate()中通过HandlerThread单独开启一个线程来依次处理所有Intent请求对象所对应的任务。这样以免事物处理阻塞线程引起ANR。执行完所一个Intent请求对象所对应的工作后,如果没有新的Intent请求达到,则自动停止Service,否则执行下一个Intent请求所对应的任务。
IntentService在处理事物时,还是采用Handler方式,创建一个叫ServiceHandler的内部Handler,并把它直接绑定到HandlerThread所对应的子线程中,ServiceHandler把处理一个Intent所对应的事物都封装到onHandlerIntent()中,因此我们直接实现onHandlerIntent(),再在里面根据Intent的不同进行不同的事物处理就可以,另外,IntentService默认实现了onBind()方法,返回值为null
对照源码再看一遍
//创建的内部ServiceHandler,把处理每一个Intent所对应的事物都封装到onHandlerIntent()方法中
//因此我们直接实现onHandlerIntent()方法来处理
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);
}
}
//需要重写实现的onHandlerIntent()
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
@Override
public void onCreate() {
super.onCreate();
//通过HandlerThread单独开启线程来依次处理所有Intent请求对象对应的任务,以免 ANR。
// 当执行完一个Intent请求对象的任务时,如果没有新的Intent请求任务达到,则自动停止Service,否则执行下一条
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
//实例化内部ServiceHandler,将其与HandlerThread所对应的子线程绑定。
mServiceHandler = new ServiceHandler(mServiceLooper);
}
使用IntentService需要实现的两个方法:
构造函数
IntentService的构造函数一定是参数为空的构造函数,然后再在其中调用super(“name”)这种形式的构造函数。因为Service的实例化是系统来完成的,而且系统是用参数为空的构造函数来实例化Service的,如下写法
public MyIntentService() {
super(“MyIntentService”);
}实现虚函数onHandleIntent
在里面根据Intent的不同进行不同的事务处理。
好处:处理异步请求的时候可以减少写代码的工作量,比较轻松地实现项目的需求。
IntentService与Service的区别
Service不是独立的进程,也不是独立的线程,它是依赖于应用程序的主线程的,不建议在Service中编写耗时的逻辑和操作,否则会引起ANR。
IntentService 它创建了一个独立的工作线程来处理所有的通过onStartCommand()传递给服务的intents(把intent插入到工作队列中)。通过工作队列把intent逐个发送给onHandleIntent()。 不需要主动调用stopSelft()来结束服务。因为,在所有的intent被处理完后,系统会自动关闭服务。
默认实现的onBind()返回null。
IntentService实例介绍
MyIntentService.java类,记得在Manifest.xml文件中注册
public class MyIntentService extends IntentService {
private String tag = this.getClass().getSimpleName();
public MyIntentService() {
super("MyIntentService");
}
@Override
public void onCreate() {
super.onCreate();
Log.e(tag,"onCreate()");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(tag,"onStartCommand()");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e(tag,"onDestroy()");
}
@Override
protected void onHandleIntent(Intent intent) {
//根据Intent的不同进行不同的事务处理
String taskName = intent.getExtras().getString("taskName");
switch (taskName) {
case "task1":
Log.e(tag, "do task1");
break;
case "task2":
Log.e(tag,"do task2");
break;
default:
break;
}
}
}
Activity中开启服务,启动服务时一定要用显示,因为android规定在5.0以后要用显示
public class MyIntentServiceActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_intent_service);
Intent i = new Intent(this,MyIntentService.class);
Bundle bundle = new Bundle();
bundle.putString("taskName", "task1");
i.putExtras(bundle);
startService(i);
Intent i2 = new Intent(this,MyIntentService.class);
Bundle bundle2 = new Bundle();
bundle2.putString("taskName", "task2");
i2.putExtras(bundle2);
startService(i2);
startService(i); //多次启动
}
}
结果如下:
E/MyIntentService: onCreate()
E/MyIntentService: onStartCommand()
E/MyIntentService: do task1
E/MyIntentService: onStartCommand()
E/MyIntentService: onStartCommand()
E/MyIntentService: do task2
E/MyIntentService: do task1
E/MyIntentService: onDestroy()