Service与intentService

不要被服务的后台概念所迷惑,实际上服务并不会自动开启线程,所有的代码都是
默认运行在主线程当中的。也就是说,我们需要在服务的内部手动创建子线程,并在这里执行具
体的任务,否则就有可能出现主线程被阻塞住的情况。

我们就已经知道,服务中的代码都是默认运行在主线程当中的,如果直接在服务里去处理一些耗时的逻辑,就很容易出现 ANR(Application Not Responding)的情况。
在主线程中进行耗时操作,容易造成线程阻塞,从而使得 容易出现Application'Not Responding。

怎么办?可以使用 IntentService

Service所属的 stopself()method是指

public class MyService extends Service {
...
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
// 处理具体的逻辑
stopSelf();
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
}

stopSelf():

Stop the service, if it was previously started.  This is the same as
calling {@link android.content.Context#stopService} for this particular service.

可以停止之前已经开启了的服务。

以上的形式太麻烦,且容易出错,于是Android提供了一个方便的,可以自动停止服务(异步的方式)的类IntentService。

新建一个 MyIntentService 类继承自 IntentService,代码如下所示:
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService"); // 调用父类的有参构造函数
}
@Override
protected void onHandleIntent(Intent intent) {
// 打印当前线程的 id
Log.d("MyIntentService", "Thread id is " + Thread.currentThread(). getId());
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("MyIntentService", "onDestroy executed");
}
}
这里首先要提供一个无参的构造函数,并且必须在其内部调用父类的有参构造函数。然后要
在子类中去实现 onHandleIntent()这个抽象方法,在这个方法中可以去处理一些具体的逻辑,
而且不用担心 ANR 的问题,因为这个方法已经是在子线程中运行的了。这里为了证实一下,我
们在 onHandleIntent()方法中打印了当前线程的 id。另外根据 IntentService 的特性,这个
服务在运行结束后应该是会自动停止的,所以我们又重写了 onDestroy()方法,在这里也打印
了一行日志,以证实服务是不是停止掉了。

NOTE:除了onHandleIntent之外,MyIntentService 的其他的部分仍然运行在主线程中。

posted @ 2019-04-09 11:15  代码海洋中的一条鱼  阅读(166)  评论(0编辑  收藏  举报