第141页
以上说明开发人员仅需要实现onHandleIntent()方法来完成客户端提供的任务。由于IntentService类没有提供空参数的构造方法,因此需要提供一个构造方法。下面的代码是IntentService实现类的例子,在onHandlerIntent()方法中,仅让线程休眠了5秒钟。
public class HelloIntentService extends IntentService {
public HelloIntentService() {
super("HelloIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
long endTime = System.currentTimeMillis() + 5 * 1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
}
}
这就是实现IntentService类所必须的全部操作:没有参数的构造方法和onHandleIntent()方法。
如果开发人员决定重写其他回调方法,如onCreate()、onStartCommand()或onDestroy(),需要调用父类实现,这样IntentService能正确处理工作线程的生命周期。
例如,onStartCommand()方法必须返回默认实现:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent,flags,startId);
}
除onHandleIntent()方法外,仅有onBind()方法不必调用父类实现,该方法在服务允许绑定时实现。
13.2.2 继承Service类
如上所述,使用IntentService类将简化启动服务的实现。然而,如果需要让服务处理多线程(取代使用工作队列处理启动请求),则可以继承Service类来处理各个Intent。
作为对比,下面通过实现Service类来完成与实现IntentService类完全相同的任务。对于每次启动请求,它使用工作线程来执行任务,并且每次处理一个请求。
public class HelloService extends Service {
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
long endTime = System.currentTimeMillis() + 5 * 1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
stopSelf(msg.arg1);
}
}
@Override
public void onCreate() {
HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY _BACKGROUND);
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
}
如上所示,这比使用IntentService增加了许多代码。
然而,由于开发人员自己处理onStartCommand()方法调用,可以同时处理多个请求。这与示例代码不同,但是如果需要,就可以为每次请求创建一个新线程并且立即运行它们(避免等待前一个请求结束)。
onStartCommand()方法必须返回一个整数。该值用来描述系统停止服务后如何继续服务(如前所述,IntentService默认实现已经处理了这些,开发人员也可以进行修改)。onStartCommand()方法返回值必须是下列常量之一。
[√]START_NOT_STICKY
如果系统在onStartCommand()方法返回后停止服务,不重新创建服务,除非有PendingIntent要发送。为避免不在不需要的时候运行服务,这是最佳选择。
[√]START_STICKY
如果系统在onStartCommand()方法返回后停止服务,重新创建服务并调用onStartCommand()方法,但是不重新发送最后的Intent;相反,系统使用空Intent调用onStartCommand()方法,除非有PendingIntent来启动服务,此时,这些Intent会被发送。这适合多媒体播放器(或者类似服务),它们不执行命令但是无限期运行并等待工作。