乐读文学

Android从入门到精通

乐读文学 > 科普学习 > Android从入门到精通

第141页

书籍名:《Android从入门到精通》    作者:明日科技


以上说明开发人员仅需要实现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会被发送。这适合多媒体播放器(或者类似服务),它们不执行命令但是无限期运行并等待工作。