Service默认都是在应用程序的主线程(UI线程)中运行的,如果直接在 Service 中执行非常耗时的操作,应用程序将会被挂起,甚至会出现ANR错误。为了避免出现这种情况,我们会在Service中重新启动一个新的线程来进行耗时操作。方法如下:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
return START_STICKY;
}
IntentService 是Android SDK 中提供的一个现成的Service类来实现这个功能,官方解释如下:
Creates a default worker thread that executes all intents delivered to onStartCommand() separate from your application’s main thread.
Creates a work queue that passes one intent at a time to your onHandleIntent() implementation, so you never have to worry about multi-threading.
Stops the service after all start requests have been handled, so you never have to call stopSelf().
Provides default implementation of onBind() that returns null.
Provides a default implementation of onStartCommand() that sends the intent to the work queue and then to your onHandleIntent() implementation
因此我们只需要重写 onHandleIntent() 方法,在该方法内实现比较耗时的操作。另外,继承IntentService时,必须提供一个无参构造函数,且在该构造函数内,需要调用父类的构造函数。
测试代码如下:
import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
/**
* Created by Owen Chan on 16/5/3.
* Copyright © 2016 Owen Chan. All rights reserved.
*/
public class MyIntentService extends IntentService {
private static final String TAG = MyIntentService.class.getSimpleName();
public MyIntentService() {
super("MyIntentService");
Log.e(TAG,"----> constructor");
}
@Override
public void onCreate() {
super.onCreate();
Log.e(TAG, "---->onCreate thread id :" + Thread.currentThread().getId());
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e(TAG, "----> onDestroy");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "----> onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
protected void onHandleIntent(Intent intent) {
Log.e(TAG, "---->onHandleIntent thread id :" + Thread.currentThread().getId());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e(TAG, "---->onHandleIntent");
}
}
打印如下:
05-03 07:50:12.270 19954-19954/com.lincanbin.carbonforum E/MyIntentService: ----> constructor
05-03 07:50:12.272 19954-19954/com.lincanbin.carbonforum E/MyIntentService: ---->onCreate thread id :1
05-03 07:50:12.272 19954-19954/com.lincanbin.carbonforum E/MyIntentService: ----> onStartCommand
05-03 07:50:12.285 19954-29296/com.lincanbin.carbonforum E/MyIntentService: ---->onHandleIntent thread id :11540
05-03 07:50:12.458 19954-19954/com.lincanbin.carbonforum E/MyIntentService: ----> onStartCommand
05-03 07:50:12.617 19954-19954/com.lincanbin.carbonforum E/MyIntentService: ----> onStartCommand
05-03 07:50:12.807 19954-19954/com.lincanbin.carbonforum E/MyIntentService: ----> onStartCommand
05-03 07:50:17.286 19954-29296/com.lincanbin.carbonforum E/MyIntentService: ---->onHandleIntent
05-03 07:50:17.287 19954-29296/com.lincanbin.carbonforum E/MyIntentService: ---->onHandleIntent thread id :11540
05-03 07:50:22.288 19954-29296/com.lincanbin.carbonforum E/MyIntentService: ---->onHandleIntent
05-03 07:50:22.289 19954-29296/com.lincanbin.carbonforum E/MyIntentService: ---->onHandleIntent thread id :11540
05-03 07:50:27.290 19954-29296/com.lincanbin.carbonforum E/MyIntentService: ---->onHandleIntent
05-03 07:50:27.291 19954-29296/com.lincanbin.carbonforum E/MyIntentService: ---->onHandleIntent thread id :11540
05-03 07:50:32.292 19954-29296/com.lincanbin.carbonforum E/MyIntentService: ---->onHandleIntent
05-03 07:50:32.293 19954-19954/com.lincanbin.carbonforum E/MyIntentService: ----> onDestroy
从打印结果可以看出,MyIntentService的onCreate()所处的线程ID仍为1,说明它是在主线程中被执行的,且只被执行一次。然后,每次 start都会触发一下onStartCommand()方法。当onHandleIntent()处于运行中时,该Service仍然可以接受新的请求,但接受到新的请求后并没有立即执行,而是将它们放入了工作队列中,等待被执行。