首页 > 移动平台 > 详细

Android Service 深度解析(1)

时间:2015-03-15 21:24:54      阅读:296      评论:0      收藏:0      [点我收藏+]

Android Service 深度解析(1)

       这段时间我重新对Android基础进行了学习,还是先从官方文档开始,做了关于Service的文档翻译,熟悉了关于Service的知识点。但是在用的时候还是有很多需要注意的地方,需要把这些知识点联系起来,因此有了这篇文章。我将主要从以下几个方面对Service类进行深度解析:
1、 Service的生命周期(看起来简单,实际上很复杂的);
2、 绑定运行Service(Bound Service)的多种形式实现及其使用;
       主要包括本地Service继承Binder类的实现、远程Service使用Messenger实现、远程Service的AIDL方式实现。(本来打算这篇一起写,篇幅太长,作为两篇吧)
如果您有兴趣继续阅读下去,但是您对Service的基础还不怎么熟悉的话,建议您先阅读以下三篇我对官方文档的翻译:
Service API文档 翻译:
http://blog.csdn.net/chtsx/article/details/44276105
Services 综合介绍 :
http://blog.csdn.net/chtsx/article/details/44276189
Bound Service 以绑定方式运行的Service :
http://blog.csdn.net/chtsx/article/details/44276241
*Service的生命周期*
       虽然Service在它的生命周期中涉及到的方法一共只有onCreate、onStartCommand、onBind、onUnbind、onDestory这几个,但是由于Service拥有两种运行方式,而且可以实现同时为多个客户端服务,支持跨进程,使得它的运行时状态真的很难让人清楚地掌握。而官方给的这个图也很难将Service的生命周期详细地表述。
技术分享
       为了好好把握Service在不同状态下的运行,我做了多种可能情况下的测试:
       在Android Studio下建立项目AndroidServiceFULLStudy,并新建一个名称为ServiceTest的工程。在ServiceTest工程下,建立一个ServiceLife类、一个MainActivity类,MainActivity与ServiceLife类中将我们执行的操作,与系统调用的生命周期方法都以日志的形式打印出来便于分析。
ServiceLife类:

public class ServiceLife extends Service {
    private String TAG = getClass().getSimpleName();
    MyBinder myBinder=new MyBinder();
    public ServiceLife() {
    }
    public class MyBinder extends Binder {
     public ServiceLife getService() {
      return ServiceLife.this; } }
    @Override
    public void onCreate() {
     Log.d(TAG, "ServiceLife------>onCreate()");
     super.onCreate(); }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
     Log.d(TAG, "ServiceLife------>onStartCommand()");
     return super.onStartCommand(intent, flags, startId); }
    @Override
    public IBinder onBind(Intent intent) {
     Log.d(TAG, "ServiceLife------>onBind()");
     return myBinder; }
    @Override
    public void onRebind(Intent intent) {
     Log.d(TAG, "ServiceLife------>onRebind()");
     super.onRebind(intent);
    }
    @Override
    public boolean onUnbind(Intent intent) {
     Log.d(TAG, "ServiceLife------>onUnbind()");
     return true;
    }
    @Override
    public void onDestroy() {
     Log.d(TAG, "ServiceLife------>onDestroy()");
     super.onDestroy();
    }
}

MainActivity类:

public class MainActivity extends ActionBarActivity {
    private String TAG = getClass().getSimpleName();
    Intent serviceIntent;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);
     Log.d(TAG, "MainActivity------>onCreate()");
     serviceIntent = new Intent(this,ServiceLife.class);}
    public void startService(View v) {
     Log.d(TAG, "MainActivity------>startService()");
     startService(serviceIntent);
    }
    public void stopService(View v) {
     Log.d(TAG, "MainActivity------>stopService()");
     stopService(serviceIntent);
    }
    public void bindService(View v) {
     Log.d(TAG, "MainActivity------>bindService()");
     bindService(serviceIntent, serviceConnection, Service.BIND_AUTO_CREATE);
    }
    public void unBindService(View v) {
     Log.d(TAG, "MainActivity------>unBindService()");
     unbindService(serviceConnection);
    }
   @Override
    protected void onDestroy() {
     Log.d(TAG, "MainActivity------>onDestroy()");
     super.onDestroy();
    }
    ServiceConnection serviceConnection = new ServiceConnection() {
     @Override
     public void onServiceConnected(ComponentName name, IBinder service) {
      Log.d(TAG, "MainActivity------>onServiceConnected()");
      ServiceLife.MyBinder binder = (ServiceLife.MyBinder) service;
      ServiceLife serviceLife = binder.getService();
     }
     @Override
     public void onServiceDisconnected(ComponentName name) {
      Log.d(TAG, "MainActivity------>onServiceDisconnected()");
     }
    };
}

MainActivity的界面布局这里就不再附上代码,贴上截图:
技术分享
       图中四个按钮分别对应执行MainActivity中startService、stopService、bindService、unBindService四个方法。
我们测试的过程如下,然后通过打印的日志进行分析:
○1多次点击STARTSERVICE按钮,再多次点击STOPSERVICE按钮:

03-15 16:55:26.924    D/MainActivity﹕ MainActivity------>onCreate()
03-15 16:55:30.554    D/MainActivity﹕ MainActivity------>startService()
03-15 16:55:30.574    D/ServiceLife﹕ ServiceLife------>onCreate()
03-15 16:55:30.574    D/ServiceLife﹕ ServiceLife------>onStartCommand()
03-15 16:55:39.644    D/MainActivity﹕ MainActivity------>startService()
03-15 16:55:39.644    D/ServiceLife﹕ ServiceLife------>onStartCommand()
03-15 16:55:40.024    D/MainActivity﹕ MainActivity------>startService()
03-15 16:55:40.034    D/ServiceLife﹕ ServiceLife------>onStartCommand()
03-15 16:55:40.304    D/MainActivity﹕ MainActivity------>startService()
03-15 16:55:40.314    D/ServiceLife﹕ ServiceLife------>onStartCommand()
03-15 16:55:45.144    D/MainActivity﹕ MainActivity------>stopService()
03-15 16:55:45.144    D/ServiceLife﹕ ServiceLife------>onDestroy()
03-15 16:55:45.504    D/MainActivity﹕ MainActivity------>stopService()
03-15 16:55:45.824    D/MainActivity﹕ MainActivity------>stopService()
03-15 16:55:46.054    D/MainActivity﹕ MainActivity------>stopService()
03-15 16:55:56.114    D/MainActivity﹕ MainActivity------>onDestroy()

如上日志得出结论,第一次点击STARTSERVICE时,将执行ServiceLife的onCreate与onStartCommand方法,此后,由于Service已经构建运行,之后点击STARTSERVICE按钮时,就只会执行onStartCommand方法;无论我们点击多少次STARTSERVICE按钮,我们只需点击一次STOPSERVICE按钮,Service就会执行onDestory销毁,之后我们继续点击STOPSERVICE按钮将不会有任何作用。
○2多次点击BINDSERVICE按钮,再多次点击UNBINDSERVICE按钮:

03-15 17:04:04.514   D/MainActivity﹕ MainActivity------>onCreate()
03-15 17:04:08.354   D/MainActivity﹕ MainActivity------>bindService()
03-15 17:04:08.374   D/ServiceLife﹕ ServiceLife------>onCreate()
03-15 17:04:08.374   D/ServiceLife﹕ ServiceLife------>onBind()
03-15 17:04:08.384   D/MainActivity﹕ MainActivity------>onServiceConnected()
03-15 17:04:09.174   D/MainActivity﹕ MainActivity------>bindService()
03-15 17:04:09.664   D/MainActivity﹕ MainActivity------>bindService()
03-15 17:04:09.954   D/MainActivity﹕ MainActivity------>bindService()
03-15 17:04:10.274   D/MainActivity﹕ MainActivity------>bindService()
03-15 17:04:13.824   D/MainActivity﹕ MainActivity------>unBindService()
03-15 17:04:13.824   D/ServiceLife﹕ ServiceLife------>onUnbind()
03-15 17:04:13.824   D/ServiceLife﹕ ServiceLife------>onDestroy()
03-15 17:04:16.944   D/MainActivity﹕ MainActivity------>unBindService()
03-15 17:04:16.944   W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception 

       如上日志显示,第一次点击BINDSERVICE按钮时,由于Service尚未运行,ServiceLife将会执行onCreate与onBind方法,当ServiceLife与MainActivity真正建立连接时,onServiceConnected将会被调用,但是之后多次点击BINDSERVICE按钮就没有意义了,当我们第一次点击UNBINDSERVICE时,ServiceLife将会执行onUnbind与onDestory方法,证明Service已经被销毁,当我们之后再点击UNBINDSERVICE时,程序将会发生运行时异常。因此,当并未与Service连接时,我们进行解绑,将会发生异常,这在编程中要注意。
○3按以下顺序依次点击:STARTSERVICE—> BINDSERVICE—>UNBINDSERVICE—> STOPSERVICE

03-15 17:18:58.774     D/MainActivity﹕ MainActivity------>startService()
03-15 17:18:58.794     D/ServiceLife﹕ ServiceLife------>onCreate()
03-15 17:18:58.794     D/ServiceLife﹕ ServiceLife------>onStartCommand()
03-15 17:19:01.014     D/MainActivity﹕ MainActivity------>bindService()
03-15 17:19:01.024     D/ServiceLife﹕ ServiceLife------>onBind()
03-15 17:19:01.034     D/MainActivity﹕ MainActivity------>onServiceConnected()
03-15 17:19:02.334     D/MainActivity﹕ MainActivity------>unBindService()
03-15 17:19:02.334     D/ServiceLife﹕ ServiceLife------>onUnbind()
03-15 17:19:06.364     D/MainActivity﹕ MainActivity------>stopService()
03-15 17:19:06.364     D/ServiceLife﹕ ServiceLife------>onDestroy()

       如上日志显示,点击STARTSERVICE按钮时,由于Service尚未运行,所以首先执行onCreate方法,再执行onStartCommand方法,之后再点击BINDSERVICE按钮时,由于Service已经运行,所以将会直接执行onBind方法,连接建立时,onServiceConnected得到调用;当我们点击UNBINDSERVICE时,onUnbind方法将得到调用,但是Service并不会被销毁;之后点击STOPSERVICE按钮,Service将会执行onDestory销毁。 当然,这种情况是最正常的情况,我们应该都能做出正常判断,但是,以下情况您是否能清楚地判断呢?
○4按以下顺序依次点击:STARTSERVICE—> BINDSERVICE—> STOPSERVICE—> UNBINDSERVICE
       看到这里你会不会觉得我已经调用stopService方法,这时Service会被销毁吧,?,后面又去调用UNBINDSERVICE?会发生异常吗?我们来看打出的日志:

03-15 17:29:02.164     D/MainActivity﹕ MainActivity------>onCreate()
03-15 17:29:13.214     D/MainActivity﹕ MainActivity------>startService()
03-15 17:29:13.234     D/ServiceLife﹕ ServiceLife------>onCreate()
03-15 17:29:13.254     D/ServiceLife﹕ ServiceLife------>onStartCommand()
03-15 17:29:14.294     D/MainActivity﹕ MainActivity------>bindService()
03-15 17:29:14.314     D/ServiceLife﹕ ServiceLife------>onBind()
03-15 17:29:14.324     D/MainActivity﹕ MainActivity------>onServiceConnected()
03-15 17:29:15.354     D/MainActivity﹕ MainActivity------>stopService()
03-15 17:29:17.674     D/MainActivity﹕ MainActivity------>unBindService()
03-15 17:29:17.674     D/ServiceLife﹕ ServiceLife------>onUnbind()
03-15 17:29:17.674     D/ServiceLife﹕ ServiceLife------>onDestroy()

       看到上面的日志,你会不会惊讶地发现在调用stopService之后,Service竟然无动于衷?当后面点击UNBINDSERVICE的时候,Service才解绑并销毁?
这里我们先不给出结论,看下一个测试。
○5按以下次序依次点击:BINDSERVICE—> STARTSERVICE—> UNBINDSERVICE—> STOPSERVICE
       这次你又会怎样猜测呢?居然先绑定,又去调用startService方法?这不乱扯吗?哈哈。看看下面的日志:

03-15 17:40:52.914     D/MainActivity﹕ MainActivity------>onCreate()
03-15 17:40:57.334     D/MainActivity﹕ MainActivity------>bindService()
03-15 17:40:57.364     D/ServiceLife﹕ ServiceLife------>onCreate()
03-15 17:40:57.364     D/ServiceLife﹕ ServiceLife------>onBind()
03-15 17:40:57.374     D/MainActivity﹕ MainActivity------>onServiceConnected()
03-15 17:40:57.964     D/MainActivity﹕ MainActivity------>startService()
03-15 17:40:57.974     D/ServiceLife﹕ ServiceLife------>onStartCommand()
03-15 17:40:58.714     D/MainActivity﹕ MainActivity------>unBindService()
03-15 17:40:58.724     D/ServiceLife﹕ ServiceLife------>onUnbind()
03-15 17:40:59.274     D/MainActivity﹕ MainActivity------>stopService()
03-15 17:40:59.274     D/ServiceLife﹕ ServiceLife------>onDestroy()

       看到如上日志,你是恍然大悟还是依然摸不着头脑呢?当我们点击BINDSERVICE按钮时,执行Service的onCreate、onBind方法,然后连接真正建立时调用onServiceConnected方法,这些都没问题,然后我们点击STARTSERVICE按钮,由于Service已经启动,所以直接执行onStartCommand方法,然后我们点击UNBINDSERVICE按钮,onUnbind方法被调用,但是并未销毁Service,直到点击STOPSERVICE按钮,onDestory才会执行。 现在你是否有些头绪了呢?如果没懂,别急,我们再进行一个测试以后,我就把总的结论写出来。
○6按以下次序依次点击:STARTSERVICE—> BINDSERVICE—> UNBINDSERVICE—> BINDSERVICE—> UNBINDSERVICE—> STOPSERVICE

03-15 17:54:16.404     D/MainActivity﹕ MainActivity------>onCreate()
03-15 17:54:20.414     D/MainActivity﹕ MainActivity------>startService()
03-15 17:54:20.434     D/ServiceLife﹕ ServiceLife------>onCreate()
03-15 17:54:20.434     D/ServiceLife﹕ ServiceLife------>onStartCommand()
03-15 17:54:21.364     D/MainActivity﹕ MainActivity------>bindService()
03-15 17:54:21.374     D/ServiceLife﹕ ServiceLife------>onBind()
03-15 17:54:21.384     D/MainActivity﹕ MainActivity------>onServiceConnected()
03-15 17:54:22.074     D/MainActivity﹕ MainActivity------>unBindService()
03-15 17:54:22.074     D/ServiceLife﹕ ServiceLife------>onUnbind()
03-15 17:54:26.224     D/MainActivity﹕ MainActivity------>bindService()
03-15 17:54:26.234     D/MainActivity﹕ MainActivity------>onServiceConnected()
03-15 17:54:26.234     D/ServiceLife﹕ ServiceLife------>onRebind()
03-15 17:54:27.214     D/MainActivity﹕ MainActivity------>unBindService()
03-15 17:54:27.214     D/ServiceLife﹕ ServiceLife------>onUnbind()
03-15 17:54:37.144     D/MainActivity﹕ MainActivity------>stopService()
03-15 17:54:37.154     D/ServiceLife﹕ ServiceLife------>onDestroy()

       哈哈哈,看到上面这个日志,真是让我哭笑不得!居然第二次绑定的时候直接就调用了onServiceConnected方法,之后又出现了个onRebind方法。
不知道细心的你在看我贴出的代码时有没有发现在ServiceLife类中我将onUnbind方法改为永远返回true了呢?那么把它改成true有什么作用呢?这里我贴一张官方的图,能很好地解释。我认为这张图逻辑表述得不错,就是丑了点,哈哈。
技术分享
       算了,为了更加有力地证明上图的正确性(官方都给图了,能错?原谅我的强迫症),与我下面的猜测,我将ServiceLife类中的onUnbind返回false,再把日志打印下。

03-15 18:08:28.134       D/MainActivity﹕ MainActivity------>onCreate()
03-15 18:08:31.244       D/MainActivity﹕ MainActivity------>startService()
03-15 18:08:31.264       D/ServiceLife﹕ ServiceLife------>onCreate()
03-15 18:08:31.264       D/ServiceLife﹕ ServiceLife------>onStartCommand()
03-15 18:08:34.344       D/MainActivity﹕ MainActivity------>bindService()
03-15 18:08:34.354       D/ServiceLife﹕ ServiceLife------>onBind()
03-15 18:08:34.364       D/MainActivity﹕ MainActivity------>onServiceConnected()
03-15 18:08:37.524       D/MainActivity﹕ MainActivity------>unBindService()
03-15 18:08:37.524       D/ServiceLife﹕ ServiceLife------>onUnbind()
03-15 18:08:39.204       D/MainActivity﹕ MainActivity------>bindService()
03-15 18:08:39.214       D/MainActivity﹕ MainActivity------>onServiceConnected()
03-15 18:08:43.364       D/MainActivity﹕ MainActivity------>unBindService()
03-15 18:08:45.274       D/MainActivity﹕ MainActivity------>stopService()
03-15 18:08:45.284       D/ServiceLife﹕ ServiceLife------>onDestroy()

       看到这个日志我真的想哭,我经过反复测试,结果就是这样!我对天发誓,在做上一个实验的时候,我都没想到结果会是这样!说好的官方的呢?第二次绑定的时候,onBind方法去哪里了呢?
       我使用的是小米1青春版,系统是最新开发版,基于ANDROID 4.1.2的,看到这里的朋友说明你的耐心真的很不错,有兴趣的话在你的机子上测试下会不会执行onBind方法,具体工程后面我会贴出链接。

       好了,上面的测试现在告一段落,Service的生命周期确实会很复杂,官方给出的生命周期图也很模糊,当然我也很难画一个很好的图,但是我可以从几个关键方法的角度,进行比较准确的解释。
onCreate():
       无论我们使用startService还是bindService方法启动Service,只要当前Service没有运行,就会执行onCreate方法;但是如果这个Service已经在执行了,那么onCreate方法就不会执行。记住,onCreate与onDestory成对出现;
onDestory():
       简单地说,就是Service销毁的时候执行。但是具体什么时候,很难描述,不好写,下面做一个表述。
       我们认为,只要调用过startService,那么Service就以独立方式运行;只要调用过bindService,那么Service就以绑定方式运行;如果startService和bindService都调用过,那么Service既是独立运行的又是绑定运行的。
       对于以独立方式运行的Service,只要我们调用stopService,那么它就退出独立运行方式,无论stopService之前调用过多少次startService,都会使Service退出独立运行方式;
       对于以绑定方式运行的Service,只要我们调用unbindService,那么就表示我这个客户端取消了与Service的绑定,而不论我这个客户端之前使用过多少次bindService,只需要一次unbindService就取消了绑定,而且只有绑定的客户端才能使用unbindService方法,未绑定客户端使用这个方法将会爆出异常;那么当所有的客户端都与Service取消绑定时,Service就退出了绑定运行方式。Service的onBind方法执行,表示Service进入绑定模式,Service的onUnbind方法执行表示Service退出绑定模式。但是,onBind方法不执行,Service也可能进入绑定模式,就像上面第5、6个测试一样。
       那么最后得出结论:当Service既不是已独立方式运行,又不是以绑定方式运行,这个Service就会被销毁了,onDestory就会执行。
onStartCommand(Intent intent, int flags, int startId):
       这个方法的执行时机比较简单,每次调用startService都会执行onStartCommand方法。参数Intent就是每次startService传入的intent,我们可以通过intent携带的数据,识别我们具体需要执行的任务。
onBind(Intent intent):
       当Service的第一个客户端第一次通过bindService方法绑定到这个Service的时候,才会执行onBind方法,后续的绑定都不再执行这个方法。它返回一个IBinder对象,这个IBinder对象将交给系统管理,后续调用bindService的时候,系统直接将IBinder对象返回给客户端,而不再调用onBind方法。
官方文档说,当Service运行于绑定模式和独立运行模式时,如果退出绑定模式时onUnbind返回了false,那么当再次进入绑定模式时将会执行onBind方法,这在我的测试中不是这样的,因此需要注意。
onUnbind(Intent intent):
       当所有与Service绑定的客户端全部解绑时,即Service退出绑定模式时,执行。
onRebind(Intent intent):
       当Service运行于绑定模式和独立运行模式时,如果退出绑定模式时onUnbind返回了true,那么当再次进入绑定模式时将会执行onRebind方法,而不会执行onBind方法。

       好了,这篇文章对Service生命周期各个方法做了测试和总结,相信你也有所收获吧。下一篇我将对如何实现Bound Service做具体介绍,有兴趣的可以继续看。
       本来准备花一个下午把Service相关问题弄清楚,结果一开始弄就蒙了,还是挺复杂的,花了三四天了,不过现在还是比较清楚。 当然,Service还有很多注意事项,比如处理系统杀死Service再重启的处理,这个在以后具体开发的时候再总结吧。
       本篇文章涉及到的代码见Github仓库:https://github.com/BBigBoy/AndroidServiceFULLStudy

Android Service 深度解析(1)

原文:http://blog.csdn.net/chtsx/article/details/44280029

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!