Android关于Activity知识点总结(一)生命周期与状态

以下内容为复习总结,若有幸被大神看到,望指正其不准,补充其不足。万分感谢!!!

一、概述

Activity是Android的一个应用组件,它提供一个界面与用户进行交互,用户可通过点击、滑动等事件来执行拨打电话,发送信息邮件或查看地图等操作。每个Activity都获得一个用于绘制用户界面的窗口,窗口通常是充满屏幕的,但也可以小于屏幕并浮于其他窗口上。

二、Activity的四种状态

1、Running状态:一个新的Activity启动后,它位于屏幕的最前端,也位于栈(下面会写到)的最顶端,此时的Activity处于可见并可交互状态,即用户可直接进行点击,滑动等操作。Android也会试图最大可能的保持它的活动状态,杀死其他Activity来确保当前活动的Activity有足够的资源可使用,对应生命周期为onResume()。当另外一个Activity被激活时,此状态将转被暂停,变为Paused状态,对应生命周期为onPause()。

2、Paused状态:当Activity处于此状态时,它依然与窗口管理器保持联系,系统继续维护其内部状态,它仍然可见,但失去了焦点,不可与用户进行交互。此状态对应,在其上面打开一个对话框或是打开一个背景为透明的Activity,对应生命周期为onPause()。

3、Stopped状态:当Activity不可见时,此Activity处于Stopped状态时。需要注意的是,Activity在此状态时,如果下次激活此Activity时要使用之前的数据和UI状态,则一定要进行保存,否则一旦Activity关闭或退出时,当前数据和UI状态将丢失,此时对应生命周期为onStop()。

4、Killed状态:Activity被销毁或者启动之前,处于此状态。这时Activity已被从Activity栈中移除,需要重启才可以显示和使用,对应生命周期为:onDestroy()或被系统回收。

此为四种状态转换关系图:

三、Activity的生命周期和各阶段触发的事件

Activity共有七个生命周期方法:onCreate(),onRestart(),onStart(),onReusme(),onPause(),onStop(),onDestory()。

其中:onCreate()和onDestory(),onStart()和onStop(),onReusme()和onPause()和三对是一一对应关系。

以下为各生命周期方法之间调用关系图:谷歌官方图

1、Activity launched:

此操作为点击桌面图标启动程序。

2、onCreate()方法:

此方法只在Activity第一次被创建时调用,主要负责Activity的一般性的初始化设置,包括视图的创建(setContentView()),视图数据的绑定等等。

需要注意的是:若此Activity销毁前有对其数据或state进行保存(即系统对该Activity调用过onSaveInstanceState()函数),则可以通过其Bundle参数进行state恢复。

3、onStart()方法:

Activity正在由不可见变为可见时,会执行此方法,即(此时Activity已经可见了)只是用户是不可以与之交互的。此时可以注册一个广播。

此时有个特殊情况:就是当上面覆盖一个透明主题的Activity或上边有个对话框类型时,再返回此Activity不会调用此方法,因为此时Activity已为可见,正处于此生命周期中。

4、onResume()方法:

当Activity处于屏幕最前端时,此Activity处于可见并可以与用户进行交互操作。此时的Activity也处在Activity栈顶。

生命周期运行到此方法时,Activity处于Running状态。

特殊情况:同第三点onStart()中,此Activity被对话框类型或透明主题的Activity遮挡,当这个对话框类型组件或透明主题的Activity消失时,会触发此方法,而不是触发onStart()方法。

5、Activity Running :

此时Activity正处于激活状态,正在与用户进行交互。此时持续处于Running状态。

6、onPause()方法:

当Activity失去焦点时(即不可与用户进行交互),此时Activity无论是部分遮挡还是即将被全部遮挡,会回调此方法。此时返回此Activity使其重新获得焦点,则会执行onResume()方法(即6->4过程),所以他们两个是一一对应的。

此时Activity处于Pause状态(即暂停状态),此时Activity还是可见的。

需要注意:Android中指定如果onPause()在500ms内没有执行完毕的话就会强制关闭Activity,因此不可做耗时操作。

7、onStop()方法:

当Activity不需要展示给用户时,即完全不可见,可能是由于此Activity要被注销或者新的Activity完全遮挡此Activity,就会回调此方法。当Activity由不可见到可见过程中(7->10->3),会执行onRestart()方法,然后最终执行onStart()方法,此时Activity可见。

此时Activity处于Stopped状态。如果内存,紧张系统直接销毁Activity,则Activity将处于Killed状态。

需要注意:此时Activity还在内存中,没有被回收,如果内存紧张,系统会直接销毁Activity,而不会触发onStop()方法,所以要保存状态和信息时,应该在onPause()方法中,因为有可能onPause()方法会是Activity最后的生命周期方法。

8、onDestroy()方法:

当Activity被销毁时,会回调此方法,此方法只会调用一次。和onStop()方法一样,当内存紧张时会直接销毁Activity,而不会回调此方法。

此时Activity处于Killed状态。如果内存紧张,系统直接销毁Activity,则处于Killed状态。

9、Process is Killed :

Activity处于Killed状态,此效果和执行onDestroy()方法等效,都需要从新创建Activity实例。

触发条件:当内存紧张时Activity声明周期将不会执行完,即可能直接执行7->9或6->9,而不走完整的生命周期。

10、onRestart()方法:

此方法在Activity执行onStop()方法后,Activity重新由不可见到可见的过程中(onStart()方法之前)会执行。即在刚开始创建Activity时不会执行此方法。

此时Activity处于Stopped状态向Running状态过渡。

11、Activity shut down:

此时Activity被销毁,也可能是对应1的程序关闭。

四、Activity的几种跳转方式所执行的生命周期顺序

1、对于一个Activity创建销毁过程:

当启动Activity时:onCreate()->onStart()->onResume();

当按home键时:onPause()->onStop;

再次回到原Activity时:onRestart()->onStart()->onResume();

当退出当前Activity时:onPause()->onStop()->onDestory()。

2、当在A_Activity中跳转到B_Activity时:

先启动A时执行:onCreate()->onStart()->onResume();

然后打开B时:先执行A的onPause(),然后执行B的onCreate()->onStart()->onResume();

此时有两种情况:

(a)、当B_Activity完全覆盖A_Activity,此时A完全不可见,则执行A的onStop()方法,这时如果A调用finish()方法,则A还会执行onDestory();

   此时当从B_Activity返回A_Activity时,B执行onPause(),如果A未执行onDestory()方法时,A执行onRestart()->onStart()->onResume(),如果执行了onDestory()方法,则需要重新创建A的实例。

(b)、当B_Activity为透明主题或者是对话框的样式时,此时不会执行A的onStop()方法。

         此时当从B_Activity返回A_Activity时,B执行onPause(),A执行onResume(),

3、当横竖屏切换时:

横竖屏切换会涉及到Activity的 android:configChanges属性,这些属性包括如下:

(a)、orientation:消除横竖屏的影响

(b)、keyboardHidden:消除键盘的影响

(c)、screenSize:消除屏幕大小的影响,此属性值在android3.2以后添加

所以横竖屏切换时根据 android:configChanges 不同的属性值表现的方式也不同:

当前版本下真机实测:

(a)、当不设置Activity的android:configChanges 值时,横竖屏切换时会重新调用生命周期,先销毁Activity,再重建。

切换横竖屏时,生命周期只会执行一次,而不会执行onConfigurationChanged()方法:

onPauseon-->SaveInstanceState-->onStop-->onDestroy-->onCreate-->onStart-->onRestoreInstanceState-->onResume;

(b)、当设置Activity的android:configChanges="orientation"android:configChanges="orientation|keyboardHidden" 值时,

竖屏切换到横屏时,会重新调用生命周期,但先执行onConfigurationChanged()方法,然后销毁Activity,再重建。

onConfigurationChanged-->onPauseon-->SaveInstanceState-->onStop-->onDestroy-->onCreate-->onStart-->onRestoreInstanceState-->onResume;

横屏切换到竖屏时,只会执行onConfigurationChanged()方法,而不会重新调用生命周期:

onConfigurationChanged()方法

(c)当设置Activity的android:configChanges="orientation|keyboardHidden|screenSize" 值时,横竖屏切换时不会调用生命周期,执行onConfigurationChanged()方法。

注:screenSize 是在android3.2以后才出现,在3.2之前android:configChanges="orientation|keyboardHidden"的效果和以上c中一样,未实测。

以下为测试代码:

public class SwitchScreenOrientationActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_move);
        System.out.println("SwitchScreenOrientationActivity----->onCreate");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        System.out.println("SwitchScreenOrientationActivity----->onDestroy");
    }

    @Override
    protected void onPause() {
        super.onPause();
        System.out.println("SwitchScreenOrientationActivity----->onPause");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        System.out.println("SwitchScreenOrientationActivity----->onRestart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        System.out.println("SwitchScreenOrientationActivity----->onResume");
    }

    @Override
    protected void onStart() {
        super.onStart();
        System.out.println("SwitchScreenOrientationActivity----->onStart");
    }

    @Override
    protected void onStop() {
        super.onStop();
        System.out.println("SwitchScreenOrientationActivity----->onStop");
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        System.out.println("SwitchScreenOrientationActivity----->onRestoreInstanceState");
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        System.out.println("SwitchScreenOrientationActivity----->onSaveInstanceState");
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if(newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
        {
            System.out.println("现在是横屏转竖屏");
        }else if(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
        {
            System.out.println("现在是竖屏转横屏");
        }
    }
}

总结:因此在切换屏幕时会出现一些错误或bug,很有可能是设置android:configChanges属性值方式不准确,引起生命周期的改变,从而丢失数据。所以有以上可以看到在生命周期发生变化时,还会回调两个方法:在onStop之前会调用onSaveInstanceState(),我们可以在这里对Activity的状态和数据进行保存,在重新显示该Activity的onResume方法之前会调用onRestoreInstanceState()方法,我们可以在此方法中恢复之前保存的状态和数据。

当然我们也可以完全屏蔽掉Activity的切换屏幕的操作:

1、可以在xml中设置属性:

       android:screenOrientation="portrait" 始终以竖屏显示 
       android:screenOrientation="landscape" 始终以横屏显示

2、可以在代码中设置:

       Activity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);以竖屏显示                     

       Activity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);以横屏显示

参考:

https://www.cnblogs.com/KingSkull/p/6095062.html


猜你喜欢

转载自blog.csdn.net/wwp9527/article/details/82112955