面试题--- Service的生命周期与Activity生命周期区别

    简述activity/service生命周期

组件的生命周期 

应用程序组件都有一个生命周期,从响应IntentAndroid实例开始到这个实例被销毁。在这期间,他们或许有效或许无效,有效时或许对用户可见或许不可见。下面我们就来讨论四个基本组件的生命周期,包括在生命周期内的各种状态,以及状态之间的转换。这几种状态可能的结果是:进程让他们停止, 然后实例被销毁。  
一、activity生命周期  
   一个activity有三个基本的状态:  
activity在前台运行时(在activity当前任务的堆栈顶),为活动或者运行状态。这时activity会响应用户的操作。  
activity失去焦点但是对用户仍然可见时为paused暂停状态。此时,别的activity在他的上面,透明或者备有被全部覆盖。所以其中一些暂停的activity也可以被显示。一个暂停的activity是处于活动状态的(他维护着所有的状态保存着信息,并且依然附着在窗口管理器)。  
如果一个activity完全被另一个activity所掩盖那他会处于stop状态。但仍然保存着原来的状态和信息。然而,如果别的地方需要更多的内存而且这个activity仍一直处于隐藏状态,那么系统有可能会杀死他的进程。  
如果一个activity是暂停或者停止状态,系统可以清理他们占用的内存,或者调用finish()方法,或者直接结束他的进程。当他再次显示给用户时,会完全的重新运行并且加载以前所存储的信息。  
activity状态之间的转换,是通过以前的受保护方法完成的:  
void onCreate(Bundle savedInstanceState)  
void onStart()  
void onRestart()  
void onResume()  
void onPause()  
void onStop()  
void onDestroy()  

这些都是钩子函数,你可以重写他们,当状态改变时做一些适当的处理。所有的activity在首次运行时必须实现onCreate()方法来初始化安装。activity可以实现onPause()来提交数据改变,然后准备停止与用户的交互。  
调用超类  

每一个实现的activity生命周期方法都会先调用一下父类的方法,例如:  
view plaincopy to clipboardprint?  
protected void onPause() {    
    super.onPause();    
    . . .    
 
protected void onPause() {  
    super.onPause();  
    . . .  
 

通过这两者比较?,7个方法定义了一个activity的整个生命周期的方法。你可以实现并且监测这三个嵌套循环:  

整个生命周期  
调用onCreate()方法和onDestroy()之间称为一个activity的完整的生命周期。activity会在onCreate()里执行所有的初始化安装,在onDestroy()方法里释放所有的剩余资源。例如:一个从网络下载程序的线程,就需要在onCreate()方法里创建,在onDestroy()方法里销毁。  

可见生命周期  
可见生命周期是从onStart()方法到onStop()方法的时间。这段时间,用户会在屏幕上看到这个activity。尽管他可能不是在最顶层显示,也没有和用户进行任何交互。这两个方法之间,你可以保持需要向用户显示的资源。例如:你可以在onStart()方法时注册一个BroadcastReceiver检测某些变化来改变你的界面,当用户看不到这个activity的界面时可以在onStop()里注销这个BroadcastReceiver。这两个方法可以被调用很多次,在可见和对用户隐藏时,作为候补的activity待命。  

前台显示周期  
一个activityonResume()方法指导一个onPause()方法称为前台显示周期。此时他在其他的activity之上显示并且与用户交互。一个activity可以频繁的在这两个方法之间过度,例如:当设备休眠或者另一个新的activity启动时,它会进入onPause()状态,当一个activity运行结束或者新的接收到Intent请求时,activityonResume()会被调用。因此,这两个方法里的代码量会很少。  

下图说明了上面说的几个循环,里面的箭头说明了两个状态之间是否可以相互转换。有色的椭圆是activity主要的几个状态。正方形和长方形代表activity在状态之间转变时我们可以实现的一些回调方法。  

注意killable这列,它指明了进程在调用方法返回后是否可以被系统杀死,而不执行其他的代码。onPause(), onStop(), and onDestroy()这三个方法可以,因为onPause方法首先被执行,他是唯一一个一定会被调用的方法当进程被杀死时,但是onStop()和onDestroy()方法不会。因此,你可以在onPause()方法里保存一些连续的数据,例如编辑。  
killable这列被标记成no的方法,保护activity防止他们被调用时,被进程杀死。例如:一个activity是处于可被杀死的状态,当activityonPause()方法跳转到onResume()方法时,在OnPause方法回调之前是不会被杀死的。  

正如后面的章节:进程和生命周期,一个没有定义为“killable”activity仍然可以被系统结束,但这时会发生在特殊情况下,比如没有其他资源时。  

保存activity的状态  

当系统(而不是用户)关闭一个activity来节省内存时,用户希望再次启动activity时会回到当时的状态。  
为了在activity被杀死之前捕获他的状态,你可以实现 onSaveInstanceState()方法,Android会在一个activity将要被关闭时调用这个方法,也就是在onPause()方法之前。他回传递给方法一个Bandle对象,你可以用key-value的方式保存你的数据。当activity再次运行时。这个Bandle对象会传递给onCreate()方法、onStart()方法、onRestoreInstanceState()方法。这几个方法都能重建当时的activity状态。  

不像onPause()和刚才讨论的其他几个方法,onSaveInstanceState()和onRestoreInstanceState()方法不是生命周期方法。不是不是总被调用。例如:Androidactivity将要被系统销毁之前调用onSaveInstanceState()方法,当activity实例被用户的操作销毁时(例如按下Back键),是不会调用这个方法的。这种情况下没有理由保存他的状态。 

Coordinating activities  
当一个activity启动了另一个activity,他们都经历了生命周期的转换。一个暂停了或者结束了,其他的activity启动。一种情况你可能需要调节这些activity  
生命周期方法的回调顺序都是定义好的,尤其当两个activity在同一进程下:  

1.当前运行的activityonPause()方法被调用。  
2.然后将要运行的activityonCreate()、onStart()、onResume()方法被依次调用。  
3.然后,如果将要运行的activity不太可见,那么onstop()方法会被调用。  
二、Service的生命周期:  
有了 Service 类我们如何启动他呢,有两种方法:  

      • Context.startService()  
      • Context.bindService()  
     1.  在同一个应用任何地方调用 startService() 方法就能启动 Service 了,然后系统会回调 Service 类的 onCreate() 以及 onStart() 方法。这样启动的 Service 会一直运行在后台,直到 Context.stopService() 或者 selfStop() 方法被调用。另外如果一个 Service 已经被启动,其他代码再试图调用 startService() 方法,是不会执行 onCreate() 的,但会重新执行一次 onStart()   
      2. 另外一种 bindService() 方法的意思是,把这个 Service 和调用 Service 的客户类绑起来,如果调用这个客户类被销毁,Service 也会被销毁。用这个方法的一个好处是,bindService() 方法执行后 Service 会回调上边提到的 onBind() 方发,你可以从这里返回一个实现了 IBind 接口的类,在客户端操作这个类就能和这个服务通信了,比如得到 Service 运行的状态或其他操作。如果 Service 还没有运行,使用这个方法启动 Service 就会 onCreate() 方法而不会调用 onStart()  
      总结:  
      1. startService()的目的是回调onStart()方法,onCreate() 方法是在Service不存在的时候调用的,如果Service存在(例如之前调用了bindService,那么ServiceonCreate方法已经调用了)那么startService()将跳过onCreate() 方法。  
      2.  bindService()目的是回调onBind()方法,它的作用是在Service和调用者之间建立一个桥梁,并不负责更多的工作(例如一个Service需要连接服务器的操作),一般使用bindService来绑定到一个现有的Service(即通过StartService启动的服务)。  
      由于Service onStart()方法只有在startService()启动Service的情况下才调用,故使用onStart()的时候要注意这点。  
与 Service 通信并且让它持续运行  
      如果我们想保持和 Service 的通信,又不想让 Service 随着 Activity 退出而退出呢?你可以先 startService() 然后再 bindService() 。当你不需要绑定的时候就执行 unbindService() 方法,执行这个方法只会触发 Service 的 onUnbind() 而不会把这个 Service 销毁。这样就可以既保持和 Service 的通信,也不会随着 Activity 销毁而销毁了。  
提高 Service 优先级  
      Android 系统对于内存管理有自己的一套方法,为了保障系统有序稳定的运信,系统内部会自动分配,控制程序的内存使用。当系统觉得当前的资源非常有限的时候,为了保 证一些优先级高的程序能运行,就会杀掉一些他认为不重要的程序或者服务来释放内存。这样就能保证真正对用户有用的程序仍然再运行。如果你的 Service 碰上了这种情况,多半会先被杀掉。但如果你增加 Service 的优先级就能让他多留一会,我们可以用 setForeground(true) 来设置 Service 的优先级。  
      为什么是 foreground ? 默认启动的 Service 是被标记为 background,当前运行的 Activity 一般被标记为 foreground,也就是说你给 Service 设置了 foreground 那么他就和正在运行的 Activity 类似优先级得到了一定的提高。当让这并不能保证你得 Service 永远不被杀掉,只是提高了他的优先级。  
三、androidservice的生命周期与activity类似,但是有一些不同:  
onCreateonStart是不同的  
通过从客户端调用Context.startService(Intent)方法我们可以启动一个服务。如果这个服务还没有运行,Android将启动它并且在onCreate方法之后调用它的onStart方法。如果这个服务已经在运行,那么它的onStart方法将被新的Intent再次调用。所以对于单个运行的Service它的onStart方法被反复调用是完全可能的并且是很正常的。  

onResumeonPause以及onStop是不需要的  

回调一个服务通常是没有用户界面的,所以我们也就不需要onPauseonResume或者onStop方法了。无论何时一个运行中的Service它总是在后台运行。  
onBind  
如果一个客户端需要持久的连接到一个服务,那么他可以调用Context.bindService方法。如果这个服务没有运行方法将通过调用onCreate方法去创建这个服务但并不调用onStart方法来启动它。相反,onBind方法将被客户端的Intent调用,并且它返回一个IBind对象以便客户端稍后可以调用这个服务。同一服务被客户端同时启动和绑定是很正常的。  
onDestroy  

Activity一样,当一个服务被结束是onDestroy方法将会被调用。当没有客户端启动或绑定到一个服务时Android将终结这个服务。与很多Activity时的情况一样,当内存很低的时候Android也可能会终结一个服务。如果这种情况发生,Android也可能在内存够用的时候尝试启动被终止的服务,所以你的服务必须为重启持久保存信息,并且最好在onStart方法内来做。 

--------------------------------------------------------------------------------------------------

activity的生命周期

oncreate(Bundle savedInstanceState):activity第一次被创建的时候调用。这里是你做所有初始化设置的地方──创建视图、绑定数据至列表等。如果曾经有状态记录,则调用此方法时会传入一个包含着此activity以前状态的包对象做为参数 

onRestart():在activity停止后,在再次启动之前被调用。 

onStart():当activity正要变得为用户所见时被调用。

onResume():在activity开始与用户进行交互之前被调用。此时activity位于堆栈顶部,并接受用户输入。 

onPause():当系统将要启动另一个activity时调用。此方法主要用来将未保存的变化进行持久化,停止类似动画这样耗费CPU的动作等。这一切动作应该在短时间内完成,因为下一个activity必须等到此方法返回后才会继续。 

onStop():当activity不再为用户可见时调用此方法。这可能发生在它被销毁或者另一个activity(可能是现存的或者是新的)回到运行状态并覆盖了它。

onDestroy():在activity销毁前调用。这是activity接收的最后一个调用。这可能发生在activity结束(调用了它的 finish() 方法)或者因为系统需要空间所以临时的销毁了此acitivity的实例时。你可以用isFinishing() 方法来区分这两种情况。

协调activity

当一个activity启动了另外一个的时候,它们都会经历生命周期变化。一个会暂停乃至停止,而另一个则启动。这种情况下,你可能需要协调好这些activity

生命周期回调顺序是已经定义好的,尤其是在两个activity在同一个进程内的情况下:

1. 调用当前activity onPause() 方法。 

2. 接着,顺序调用新启动activityonCreate() onStart()onResume()方法。 

3. 然后,如果启动的activity不再于屏幕上可见,则调用它的onStop()方法。 

总之:1Activity 从创建到进入运行态所触发的事件  onCreate()-->onStart-->onResume()

          2、从运行态到停止态所触发的事件                  onPause()--->onStop()

          3、从停止态到运行态所触发事件                     onRestart()-->onStart()--->onResume()

     4、从运行态到暂停态所触发事件                     onPause()

          5、从暂停态到运行态所触发事件                     onResume()

横竖屏幕切换生命周期

1.不设置Activityandroid:configChanges,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次

2.设置Activityandroid:configChanges="orientation",切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次

3.设置Activityandroid:configChanges="orientation|keyboardHidden",切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法.

service的生命周期

启动Service时可调用startServicebindService()方法来启动,用这两种方法启动的Service的生命周期是不同的。

Service的生命周期只有onCreate,onStartonDestroy,没有onResume,onPauseonStop,大多数时间Service都是运行的,但在严重的内存压力下它也可能被系统kill,如果被kill,系统会在稍后尝试重新启动这个Service

Service的调用

途径一:
调用Context.startService()启动Service,调用Context.stopService()Service.stopSelf()Service.stopSelfResult()关闭Service的调用。

Service生命周期分析:
注:onCreate,onStart(),onDestroy()Service生命周期相关的方法
Context.startService()启动Service时,如果Service本身没有运行,则调用onCreate()->onStart()完成Service启动。如果Service已经运行,则只调用onStart()onStart()可以多次被调用。
Service关闭必须调用Context.stopService()Service.stopSelf()Service.stopSelfResult()方法,关闭之前调用onDestroy()方法,否则如果Context直接退出而没有停止Service的话,Service会一直在后台运行。该Service的调用者只能再启动后通过stopService关闭Service
生命周期顺序为:onCreate()->onStart()->onDestroy()

途径二:
调用Context.bindService()进行初始化绑定,使用Context.unbindService()取消绑定,由于ServiceContext是绑定关系,当Context退出或被销毁时,Service也会相应退出。

Service生命周期分析:
调用Context.bindService()时,Service会经历onCreate->onBind()onBind将返回给客户端一个IBind实例,IBind允许客户端回调服务的方法。此时ContextService是绑定在一起的,Context退出了,Service调用onUnbind()->onDestroy()相应退出。
生命周期顺序为:onCreate->onBind(只一次,不可多次绑定)->onUnbind->onDestroy()

BroadcastReceiver只能通过startService启动Service,因为广播本身生命周期很短,bind的话没有意义

果不是通过bindService创建的服务(但仍然通过bindService得到了服务对象),就可能unbindService后还在运行,否则应该是结束掉了。

你可能感兴趣的:(service,面试题,activity)