Acitivty生命周期

时光总嘲笑我的痴心妄想 提交于 2019-12-01 19:37:51

Acitivty 有七个生命周期:

onCreate:当第一次调用一个Activity就会执行onCreate方法

onStart:当Activity处于可见状态的时候就会调用onStart方法

onResume:当Activity可以得到用户焦点的时候就会调用onResume方法,由被覆盖状态回到前台或解锁屏调用此方法。

onRestart:当Activity没有被销毁的时候重新调用这个Activity就会调用onRestart方法

onPause:当Activity被遮挡住的时候就会调用onPause方法,暂停当前activity。

onStop:当Activity处于不可见状态的时候就会调用onStop方法

onDestory:当Activity被销毁时会调用onDestory方法


环境:一共两个页面,A,B A页面有一个button点击之后打开B页面

activity启动的时候:onCreate ---> onStart ---> onResume,打开A页面:启动时调用,可见状态调用,获取焦点调用。

点击button后打开B页面此时A页面的状态是:onPause--->onStop,首先暂停A页面activity,然后对B页面的activity执行上面的三步,然后对A页面进行停止操作。

当按返回键时:onRestart--->onStart--->onResume,首先暂停B页面,其次对A页面重新调用,可见状态调用,获取焦点是调用,最后在停止B页面。

以下是运行时print截图:

   


通过实施这些方法,您可以监视Activity生命周期中的三个嵌套循环

1、entire lifetime (整个生命周期)

一个Activity整个生命周期,存在于onCreate()方法和onDestroy()调用之间。你的Activity应该在onCreate()方法里执行设置全局状态(如定义布局)并在onDestroy()方法里释放所有剩余资源。例如,如果你的活动有一个线程在后台运行下载网络数据它可以在onCreate()创建该线程然后onDestroy()停止线程

2、visible lifetime(可见生命周期)

一个Activity可见生命周期,存在于onStart()和onStop()调用之间。在此期间用户可以看到屏幕上的activity并与之交互。当一个其他的Activity启动,并且这个Activity完全不可见的时候,onStop()方法就会被调用。在这两个方法,你可以保持该Activity需要展示给用户的资源例如,您可以在onStart()方法里注册一个BroadcastReceiver来监控你的UI的变化,并在onStop()方法里注销它。在整个生命周期的活动中,系统可能会调用onStart()和onStop()多次,因为活动之间交替进行隐藏或显示给用户。

3、 foreground lifetime(前台生命周期)

一个Activity前台生命周期,存在于onResume()和onPause()调用之间。在这段时间里,这个Activity在其他所有Activity的前面,拥有用户输入焦点。一个Activity可以经常在前台状态发生转换—比如,当设备休眠或者弹出了个对话框。因为经常会发生转换,所以在这两个方法之间的代码应该是轻量级的,防止导致其他转换变慢使得用户需要等待。


一个Activity本质上只有三种状态:

Resumed(运行)、Paused(暂停)、Stopped(停止),因为从Activity被创建之后,它只可能在这三种状态保持长久的停 留,其他的回调方法结束后的状态都只能称之为过渡状态。比如进入到onStart方法后,执行完该方法,会立即进入到OnResume方法。(这里所说的 状态都是指对应的某个方法返回之后)。

     Activity相当于一个servlet,我们的Activity处在这个容器中,一切创建实例、初始化、销毁实例等过程都是容器来调用的,这也就是所谓的“Don't call me, I'll call you.”机制。

我们来看一下这一张经典的生命周期流程图:


相信不少朋友也已经看过这个流程图了,也基本了解了Activity生命周期的几个过程,我们就来说一说这几个过程。

1.启动Activity:系统会先调用onCreate方法,然后调用onStart方法,最后调用onResume,Activity进入运行状态。

2.当前Activity被其他Activity覆盖其上或被锁屏:系统会调用onPause方法,暂停当前Activity的执行。

3.当前Activity由被覆盖状态回到前台或解锁屏:系统会调用onResume方法,再次进入运行状态。

4.当前Activity转到新的Activity界面或按Home键回到主屏,自身退居后台:系统会先调用onPause方法,然后调用onStop方法,进入停滞状态。

5.用户后退回到此Activity:系统会先调用onRestart方法,然后调用onStart方法,最后调用onResume方法,再次进入运行状态。

6.当前Activity处于被覆盖状态或者后台不可见状态,即第2步和第4步,系统内存不足,杀死当前Activity,而后用户退回当前Activity:再次调用onCreate方法、onStart方法、onResume方法,进入运行状态。

7.用户退出当前Activity:系统先调用onPause方法,然后调用onStop方法,最后调用onDestory方法,结束当前Activity。

生命周期对于用户体验的实际作用

    activity生命周期不同的周期可以写不同的代码,举个例子,比如你正在播放音乐的时候突然电话来了,这个时候不可能一边接电话一边听音乐吧?这时你就需要在相应的周期里面对播放进行处理,比如你可以在当前activity失去焦点的时候暂停播放。


我还找了一些资料用以扩充学习原文链接

每一个活动( Activity )都处于某一个状态,对于开发者来说,是无法控制其应用程序处于某一个状态的,这些均由系统来完成。 
但是当一个活动的状态发生改变的时候,开发者可以通过调用 onXX() 的方法获取到相关的通知信息。 
在实现 Activity 类的时候,通过覆盖( override )这些方法即可在你需要处理的时候来调用。 
•onCreate :当活动第一次启动的时候,触发该方法,可以在此时完成活动的初始化工作。 
onCreate 方法有一个参数,该参数可以为空( null ),也可以是之前调用 onSaveInstanceState()方法保存的状态信息。
•onStart :该方法的触发表示所属活动将被展现给用户。 
•onResume :当一个活动和用户发生交互的时候,触发该方法。 
•onPause :当一个正在前台运行的活动因为其他的活动需要前台运行而转入后台运行的时候,触发该方法。这时候需要将活动的状态持久化,比如正在编辑的数据库记录等。 
•onStop :当一个活动不再需要展示给用户的时候,触发该方法。如果内存紧张,系统会直接结束这个活动,而不会触发 onStop 方法。 所以保存状态信息是应该在onPause时做,而不是onStop时做。活动如果没有在前台运行,都将被停止或者Linux管理进程为了给新的活动预留足 够的存储空间而随时结束这些活动。因此对于开发者来说,在设计应用程序的时候,必须时刻牢记这一原则。在一些情况下,onPause方法或许是活动触发的 最后的方法,因此开发者需要在这个时候保存需要保存的信息。 
•onRestart :当处于停止状态的活动需要再次展现给用户的时候,触发该方法。 
•onDestroy :当活动销毁的时候,触发该方法。和 onStop 方法一样,如果内存紧张,系统会直接结束这个活动而不会触发该方法。 
•onSaveInstanceState :系统调用该方法,允许活动保存之前的状态,比如说在一串字符串中的光标所处的位置等。 
通常情况下,开发者不需要重写覆盖该方法,在默认的实现中,已经提供了自动保存活动所涉及到的用户界面组件的所有状态信息。
  
4. 必调用的三个方法:onCreate() –> onStart() –> onResume(),用AAA表示
(1)父Activity(A)启动,点击启动子Activity(B),子Actvity退出,返回父Activity调用顺序如下:
AAA –> onFreeze() –> onPause() –> B onCreate() -> B onStart() -> B onResume –> onStop() –> onRestart() –> onStart()->onResume()
(2)用户点击Home,Actvity调用顺序如下
AAA –> onFreeze() –> onPause() –> onStop() — Maybe –> onDestroy()
( 3 ) 用户点击back键,Activity调用顺序如下:
AAA-> onPause() –> onStop() –> onDestroy() ->onCreate()->onStart()->onResume()
(4)调用finish(), Activity调用顺序如下 
AAA –> onPause() –> onStop() –> onDestroy() 
(5)在Activity上显示dialog, Activity调用顺序如下 
AAA -> onPause()
(6)在父Activity上显示透明的或非全屏的activity,Activity调用顺序如下 
AAA –> onFreeze() –> onPause() 
(7)设备进入睡眠状态,Activity调用顺序如下 
AAA –> onFreeze() –> onPause()

5. 和其他手机平台的应用程序一样,Android的应用程序的生命周期是被统一掌控的,也就是说我们写的应用程序命运掌握在别人(系统)的手里,我们不能改变它,只能学习并适应它。
简单地说一下为什么是这样:我们手机在运行一个应用程序的时候,有可能打进来电话发进来短信,或者没有电了,这时候程序都会被中断,优先去服务电话的基本功能,另外系统也不允许你占用太多资源,至少要保证电话功能吧,所以资源不足的时候也就有可能被干掉。 
言归正传,Activity的基本生命周期如下代码所示: 
Java 代码 
public class MyActivity extends Activity {  
protected void onCreate(Bundle savedInstanceState);  
protected  void onStart();
protected  void onResume();
protected  void onPause();
protected  void onStop();
protected  void onDestroy();
}   
        
       你自己写的Activity会按需要重载这些方法,onCreate是免不了的,在一个Activity正常启动的过程中,他们被调用的顺序是 onCreate -> onStart -> onResume, 在Activity被干掉的时候顺序是onPause -> onStop -> onDestroy ,这样就是一个完整的生命周期,但是有人问了 ,程序正运行着呢来电话了,这个程序咋办?中止了呗,如果中止的时候新出的一个Activity是全屏的那么:onPause->onStop,恢 复的时候onStart->onResume,如果打断这个应用程序的是一个Theme为Translucent 或者Dialog 的Activity那么只是onPause ,恢复的时候onResume 。 
详细介绍一下这几个方法中系统在做什么以及我们应该做什么: 
onCreate:   在这里创建界面,做一些数据的初始化工作 
onStart:   到这一步变成用户可见不可交互的 
onResume:   变成和用户可交互的,(在activity栈系统通过栈的方式管理这些个Activity的最上面,运行完弹出栈,则回到上一个Activity) 
onPause:到这一步是可见但不可交互的,系统会停止动画等消耗CPU 的事情
        从上文的描述已经知道,应该在这里保存你的一些数据,因为这个时候你的程序的优先级降低,有可能被系统收回。在这里保存的数据,应该在onResume里读出来,注意:这个方法里做的事情时间要短,因为下一个activity不会等到这个方法完成才启动 
onstop:变得不可见,被下一个activity覆盖了 
onDestroy: 这是activity被干掉前最后一个被调用方法了,可能是外面类调用finish方法或者是系统为了节省空间将它暂时性的干掉,可以用 isFinishing()来判断它,如果你有一个Progress Dialog在线程中转动,请在onDestroy里把他cancel掉,不然等线程结束的时候,调用Dialog的cancel方法会抛异常的。 onPause,onstop, onDestroy,三种状态下activity都有可能被系统干掉,为了保证程序的正确性,你要在onPause()里写上持久层操作的代码,将用户编 辑的内容都保存到存储介质上(一般都是数据库 )。实际工作中因为生命周期的变化而带来的问题也很多,比如你的应用程序起了新的线程在跑,这时候中断了,你还要去维护那个线程,是暂停还是杀掉还是数据 回滚,是吧?因为Activity可能被杀掉,所以线程中使用的变量和一些界面元素就千万要注意了,一般我都是采用Android的消息机制 [Handler,Message]来处理多线程和界面交互的问题。这个我后面会讲一些。 

相关问题:
1. 能说下Android应用的入口点吗?
真正的Android入口点是application的main,你可以看下androidmanifest.xml的包含关系就清楚了。可以没有Activity但是必须有Application。
2. 如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态?
在”暂停 onPause” 状态将数据保存。
3. 如何退出Activity?如何安全退出已调用多个Activity的Application?
对于单一Activity的应用来说,退出很简单,直接finish()即可。当然,也可以用killProcess()和System.exit()这样的方法。

4. 返回键与Home键区别?
   back键默认行为是finish处于前台的Activity的,即Activity的状态为Destroy状态为止,再次启动该Activity是从 onCreate开始的(不会调用onSaveInstanceState()方法)。Home键默认是stop前台的Activity即状态为 onStop为止,而不是Destroy,若再次启动它,会调用onSaveInstanceState() 方法,保持上次Activity的状态则是从OnRestart开始的---->onStart()--->onResume()。

5. 如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态?onSaveInstanceState()
当你的程序中某一个Activity A在运行时,主动或被动地运行另一个新的Activity B,这个时候A会执行onSaveInstanceState()。B完成以后又会来找A,这个时候就有两种情况:一是A被回收,二是A没有被回收,被回 收的A就要重新调用onCreate()方法,不同于直接启动的是这回onCreate()里是带上了参数savedInstanceState;而没被 收回的就直接执行onRestart()->onStart()->onResume(),跳过onCreate()了。

6. 你后台的Activity被系统回收怎么办:onSaveInstanceState 
当你的程序中某一个Activity A 在运行时中,主动或被动地运行另一个新的Activity B,这个时候A会执行 
Java代码   
public void onSaveInstanceState(Bundle outState) {    
super.onSaveInstanceState(outState);    
outState.putLong("id", 1234567890);

B 完成以后又会来找A, 这个时候就有两种情况,一种是A被回收,一种是没有被回收,被回收的A就要重新调用onCreate()方法,不同于直接启动的是这回 onCreate()里是带上参数savedInstanceState,没被收回的就还是onResume就好了。 
savedInstanceState是一个Bundle对象,你基本上可以把他理解为系统帮你维护的一个Map对象。在onCreate()里你可能会用到它,如果正常启动onCreate就不会有它,所以用的时候要判断一下是否为空。 
Java代码 
if(savedInstanceState != null){     
long id = savedInstanceState.getLong("id");

就像官方的Notepad教程里的情况,你正在编辑某一个note,突然被中断,那么就把这个note的id记住,再起来的时候就可以根据这个id去把那 个note取出来,程序就完整一些。这也是看你的应用需不需要保存什么,比如你的界面就是读取一个列表,那就不需要特殊记住什么,哦, 没准你需要记住滚动条的位置(滚动条的位置如何记住?)...

7. 怎样关闭一个Activity;怎样关闭一个Application?
ActivityManager activityMgr= (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
activityMgr.restartPackage(getPackageName());
最后还需要添加这个权限才行:
<!-- 关闭应用程序的权限 -->
<uses-permission android:name="android.permission.RESTART_PACKAGES" />

8. 横竖屏切换的生命周期

9. Activity栈
   上面提到开发者是无法控制Activity的状态的,那Activity的状态又是按照何种逻辑来运作的呢?这就要知道 Activity 栈。
每个Activity的状态是由它在Activity栈(是一个后进先出LIFO,包含所有正在运行Activity的队列)中的位置决定的。
当一个新的Activity启动时,当前的活动的Activity将会移到Activity栈的顶部。
如果用户使用后退按钮返回的话,或者前台的Activity结束,在栈上的Activity将会移上来并变为活动状态。如下图所示:

   2.JPG 

    一个应用程序的优先级是受最高优先级的Activity影响的。当决定某个应用程序是否要终结去释放资源,Android内存管理使用栈来决定基于Activity的应用程序的优先级。
Activity状态 
一般认为Activity有以下四种状态: 
活动的:当一个Activity在栈顶,它是可视的、有焦点、可接受用户输入的。Android试图尽最大可能保持它活动状态,杀死其它Activity来确保当前活动Activity有足够的资源可使用。当另外一个Activity被激活,这个将会被暂停。 
暂停: 在很多情况下,你的Activity可视但是它没有焦点,换句话说它被暂停了。有可能原因是一个透明或者非全屏的Activity被激活。 
当被暂停,一个Activity仍会当成活动状态,只不过是不可以接受用户输入。在极特殊的情况下,Android将会杀死一个暂停的Activity来为活动的Activity提供充足的资源。当一个Activity变为完全隐藏,它将会变成停止。 
停止:当一个Activity不是可视的,它“停止”了。这个Activity将仍然在内存中保存它所有的状态和会员信息。尽管如此,当其它地方需要内存 时,它将是最有可能被释放资源的。当一个Activity停止后,一个很重要的步骤是要保存数据和当前UI状态。一旦一个Activity退出或关闭了, 它将变为待用状态。 
待用: 在一个Activity被杀死后和被装在前,它是待用状态的。待用Acitivity被移除Activity栈,并且需要在显示和可用之前重新启动它。


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!