Android四大组件之Activity篇(二)(Activity的生命周期)

来源:互联网 发布:手机支持什么网络 编辑:程序博客网 时间:2024/05/16 15:44

锲而舍之,朽木不折;锲而不舍,金石可镂。——《荀子》

          在上一篇文章中,我们简单的归纳了下Activity的创建、启动、关闭以及数据传送的相关知识点。那么在本篇文章中,我们将重点对Activity的一个比较重要的知识点进行归纳总结,Activity的生命周期,很重要,无论是在平时的开发应用中还是在找工作的笔试面试中,这个问题频频出现,所以很有必要重点归纳总结。这里需要归纳的知识点有Activity的四个状态、七个生命周期方法、三个嵌套循环生命周期、还有特定场景下的生命周期等等……

(1)、Activity的四种基本状态:

              Active/Runing:一个新Activity启动入栈后,它在屏幕最前端,处于栈的最顶端,此时它处于可见并可和用户交互的激活状态。

              Paused:当Activity被另一个透明或者Dialog样式的Activity覆盖时的状态。此时它依然与窗口管理器保持连系,系统继续维护其内部状态,所以它仍然可见,但它已经失去了焦点故不可与用户交互。

              Stoped:当Activity被另一个Activity覆盖、失去焦点并不可见时处于Stoped状态。

              Killed:Activity被系统杀死回收或者没有被启动时处于Killed状态。

(2)、Activity的几个生命周期方法:

       onCreate创建时调用,或者程序在暂停、停止状态下被杀死之后重新打开时也会调用。

       onStart:onCreate之后或者从停止状态恢复时调用。

       onResume:onStart之后或者从暂停状态恢复时调用,从停止状态恢复时由于调用onStart,也会调用onResume。

       onPause:进入暂停、停止状态,或者销毁时会调用。

       onStop:进入停止状态,或者销毁时会调用。一般我们在这里保存activity的状态信息。

       onDestroy:销毁时调用。在这里一般做些释放资源,清理内存等工作。

       onRestart:从停止状态恢复时调用。

            相对应的生命周期图如下所示:

              

(3)、Activity的三个嵌套生命周期:

                       

            在Activity中用7个方法定义了Activity的完整的生命周期,实现这7个方法,可以帮我们监视其中的三个嵌套生命周期循环:

        ①、Activity的完整的生命周期:自第一次调用onCreate()开始,直至调用onDestory()方法为止。onCreate():可以设置所有“全局”状态以完成初始化。onDestroy():释放所有的系统资源。

        ②、Activity的可视化生命周期:自onStart()调用开始直到相应的onStop()调用结束。这两个方法可以随着应用程序是否为用户可见而被多次调用。

        ③、Activity的前台生命周期:自onResume()调用起,至相应的onPause()调用为止。在此期间,Activity位于前台最上面并与用户进行交互。

(4)、Activity中特殊的两个方法:

       Activity的onSaveInstanceState()onRestoreInstanceState()并不是生命周期方法,他们不同于onCreate()、onPause()等生命周期方法,它们并不一定会被触发。当应用遇到意外情况(如:内存不足、用户直接按Home键)由系统销毁一个Activity时,onSaveInstanceState()会被调用。但是当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState()就不会被调用。因为在这种情况下,用户的行为决定了不需要保存Activity的状态。通常onSaveInstanceState()只适用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。

       另外,当屏幕的方向放生了改变,Activity会被摧毁并且被重新创建,如果你想在Activity被摧毁前缓存一些数据,并且在Activity被重新创建后恢复缓存的数据。可以重写Activity的onSaveInstanceState()和onRestoreInstanceState()方法,如下:

public class PreferencesActivity extends Activity {    private String name;    protected void onRestoreInstanceState(Bundle savedInstanceState) {         name = savedInstanceState.getString("name");//被重新创建后恢复缓存的数据          super.onRestoreInstanceState(savedInstanceState);    }    protected void onSaveInstanceState(Bundle outState) {         outState.putString("name", "liming");//被摧毁前缓存一些数据          super.onSaveInstanceState(outState);    }}

        注意: 必须要调用onSaveInstanceState()方法和onRestoreInstanceState()的父类实现,这样默认的父类实现才能保存视图状态的信息。

(5)、横竖屏切换时的Activity的生命周期:

         这里我们需要通过一个实验,然后根据实验结果进行归纳总结,为了整齐,以代码形式给出(来之网络,地址忘了吐舌头):

//1、新建一个Activity,并把各个生命周期打印出来//2、运行Activity,得到如下信息      onCreate-->     onStart-->     onResume-->//3、按crtl+f12切换成横屏时      onSaveInstanceState-->     onPause-->     onStop-->     onDestroy-->     onCreate-->     onStart-->     onRestoreInstanceState-->     onResume-->//4、再按crtl+f12切换成竖屏时,发现打印了两次相同的log     onSaveInstanceState-->     onPause-->     onStop-->     onDestroy-->     onCreate-->     onStart-->     onRestoreInstanceState-->     onResume-->     onSaveInstanceState-->     onPause-->     onStop-->     onDestroy-->     onCreate-->     onStart-->     onRestoreInstanceState-->     onResume-->//5、修改AndroidManifest.xml,把该Activity添加android:configChanges="orientation",执行步骤3     onSaveInstanceState-->     onPause-->     onStop-->     onDestroy-->     onCreate-->     onStart-->     onRestoreInstanceState-->     onResume-->//6、再执行步骤4,发现不会再打印相同信息,但多打印了一行onConfigChanged     onSaveInstanceState-->     onPause-->     onStop-->     onDestroy-->     onCreate-->     onStart-->     onRestoreInstanceState-->     onResume-->     onConfigurationChanged-->//7、把步骤5的android:configChanges="orientation" 改成android:configChanges="orientation|keyboardHidden",执行步骤3,就只打印onConfigChanged     onConfigurationChanged-->   //8、执行步骤4     onConfigurationChanged-->     onConfigurationChanged-->

对上面的实验结果进行分析,我们可以得出如下结论:

         ①、默认情况下,当“屏幕方向”或“键盘显示隐藏”变化时都会销毁当前的Activity,创建新的Activity。

         ②、默认情况下(没有设置android:configChanges属性):

                >>> 竖屏切换横屏:销毁当前Activity之后,创建一个新的Activity实例。

                >>> 横屏切换竖屏:销毁当前的Activity之后,创建一个新的Activity实例,新的Activity实例很快就被销毁,接着又会创建一个新的Activity实例。如果只希望创建一个实例,可以配置android:configChanges="orientation";

那么基于上面的知识点,在日常的开发中,如果我们不想在横竖屏切换时让Activity销毁该怎么办呢?

 方法一:①、在AndroidMainfest.xml中为Activity设置configChanges属性,如下:

 <application android:icon = “@drawable/icon”   android:label = “@string/app_name”>       <activity android:name = “.MainActivity”  android:label = “@string/app_name”                      android:configChanges = “orientation|keyboardHidden”>           <intent-filter>             ……             </intent-filter>       </activity> </application>

       上面的android:configChanges属性指定了要捕获“屏幕方向”和“键盘显示隐藏”变化,当捕获到这些变化后会调用Activity的onConfigurationChanges()方法。
       configChangesconfig有如下选项:

                 orientation: 屏幕在纵向和横向间旋转;
                 keyboardHidden: 键盘显示或隐藏;
                 fontScale:用户变更了首选的字体小;
                 locale :用户选择了不同的语言设定;
                 keyboard:键盘类型变更,例如手机从键盘切换到全键盘;
                 touchscreen或navigation:键盘或导航方式变化;

       注意:如果缺少了keyboardHidden选项,不能防止Activity的销毁,并且在之后提到的onConfigurtionChanged事件中只能捕获竖屏变横屏的事件,不能捕获横屏变竖屏的事件。

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

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

                 、在对应的Activity中重写:onConfigurationChanged方法:

   public class MainActivity extends Activity {               private TextView textView;               @Override               public void onCreate(Bundle savedInstanceState) {                         super.onCreate(savedInstanceState);                         setContentView(R.layout.main);                         Log.i("--Main--", "onCreate");                         textView=(TextView)findViewById(R.id.tv_id);               }          @Override               public void onConfigurationChanged(Configuration newConfig) {                         super.onConfigurationChanged(newConfig);                         Log.i("--Main--", "onConfigurationChanged");                if(newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE){                                  textView.setText("当前屏幕为横屏");                         }else{                       textView.setText("当前屏幕为竖屏");                         }               }         }

   注:如果项目不需要屏幕切换时可以设置为:

       1、 android:screenOrientation="portrait"始终以竖屏显示 

              2、 android:screenOrientation="landscape"始终以横屏显示

方法二:上面是通过配置文件设置屏幕的横竖屏切换的,下面通过代码区控制屏幕的横竖屏切换:

       private OnClickListener onClick=new OnClickListener() {                       @Override                       public void onClick(View v) {                                 //设置屏幕为横屏                                   if(v==butLandscrpe){                            MainActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);                                    }else{                            //设置为置屏幕为竖屏                               MainActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);                    }              }     };     //监听系统设置的更改         @Override      public void onConfigurationChanged(Configuration newConfig) {                      super.onConfigurationChanged(newConfig);                      String message=newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE?"屏幕设置为:横屏" : "屏幕设置为:竖屏";                    showToast(message);         }

(6)、Back键和Home键相关的Activity的生命周期:

                      当我们按Back键时,我们当前的Activity界面退出,我们看不到了,这时候我们先后调用了onPause() -> onStop() -> onDestory()三个方法;

              当我们正在浏览一个新闻页面的时候,突然想听歌了,那么我们会选择按Home键,然后去打开音乐应用程序,而当我们按Home的时候,对应的新闻页的Activity先后执行了onSaveInstanceState() -> onPause() -> onStop()这几个方法,这时候应用程序没有销毁。而当我们再次启动Activity的应用程序时,则先后分别执行了onRestart() -> onStart() -> onResume() 这几个方法。

                 注意:这里要知道几种情形的Activity相对应的生命周期方法的调用过程,分别为:打开一个应用、关闭一个应用、完全覆盖(停止)、没有完全覆盖(暂停)、屏幕的横竖屏切换、BackHome键等。

  网上看到的一个关于Activity的生命周期管理的系列文章挺好,地址
                            http://wiki.eoe.cn/page/Managing_the_Activity_Lifecycle.html

原创粉丝点击