Activity生命周期

Android官方文档和其余很多资料都对Activity生命周期进行了详细介绍,在结合资料和项目开发过程当中遇到的问题,本文将对Activity生命周期进行一次总结。html

Activity是由Activity栈进管理,当来到一个新的Activity后,此Activity将被加入到Activity栈顶,以前的Activity位于此Activity底部。Acitivity通常意义上有四种状态:android

1.当Activity位于栈顶时,此时正好处于屏幕最前方,此时处于运行状态app

2.当Activity失去了焦点但仍然对用于可见(如栈顶的Activity是透明的或者栈顶Activity并非铺满整个手机屏幕),此时处于暂停状态ide

3.当Activity被其余Activity彻底遮挡,此时此Activity对用户不可见,此时处于中止状态函数

4.当Activity因为人为或系统缘由(如低内存等)被销毁,此时处于销毁状态;this

在每一个不一样的状态阶段,Adnroid系统对Activity内相应的方法进行了回调。所以,咱们在程序中写Activity时,通常都是继承Activity类并重写相应的回调方法。spa

先贴一张来自官方文档(http://developer.android.com/reference/android/app/Activity.html)的图,相信你们都看到过。code

 

图中详细给出了Activity整个生命周期的过程,以及在不一样的状态期间相应的回调方法。orm

图中须要注意一下几点:htm

1.Activity实例是由系统自动建立,并在不一样的状态期间回调相应的方法。一个最简单的完整的Activity生命周期会按照以下顺序回调:onCreate -> onStart -> onResume -> onPause -> onStop -> onDestroy。称之为entire lifetime。

2.当执行onStart回调方法时,Activity开始被用户所见(也就是说,onCreate时用户是看不到此Activity的,那用户看到的是哪一个?固然是此Activity以前的那个Activity),一直到onStop以前,此阶段Activity都是被用户可见,称之为visible lifetime。

3.当执行到onResume回调方法时,Activity能够响应用户交互,一直到onPause方法以前,此阶段Activity称之为foreground lifetime。

在实际应用场景中,假设A Activity位于栈顶,此时用户操做,从A Activity跳转到B Activity。那么对AB来讲,具体会回调哪些生命周期中的方法呢?回调方法的具体回调顺序又是怎么样的呢?

开始时,A被实例化,执行的回调有A:onCreate -> A:onStart -> A:onResume。

当用户点击A中按钮来到B时,假设B所有遮挡住了A,将依次执行A:onPause -> B:onCreate -> B:onStart -> B:onResume -> A:onStop。

此时若是点击Back键,将依次执行B:onPause -> A:onRestart -> A:onStart -> A:onResume -> B:onStop -> B:onDestroy。

至此,Activity栈中只有A。在Android中,有两个按键在影响Activity生命周期这块须要格外区分下,即Back键和Home键。咱们先直接看下实验结果:

此时若是按下Back键,系统返回到桌面,并依次执行A:onPause -> A:onStop -> A:onDestroy。

此时若是按下Home键(非长按),系统返回到桌面,并依次执行A:onPause -> A:onStop。因而可知,Back键和Home键主要区别在因而否会执行onDestroy。

此时若是长按Home键,不一样手机可能弹出不一样内容,Activity生命周期未发生变化(由小米2s测的,不知道其余手机是否会对Activity生命周期有影响)。

因为Android自己的特性,使得如今很多应用都没有直接退出应用程序的功能,按照通常的逻辑,当Activity栈中有且只有一个Activity时,当按下Back键此Activity会执行onDestroy,那么下次点击此应用程图标将从从新启动,所以,当前很多应用程序都是采起如Home键的效果,当点击了Back键,系统返回到桌面,而后点击应用程序图标,直接回到以前的Activity界面,这种效果是怎么实现的呢?

经过重写按下Back键的回调函数,转成Home键的效果便可。

@Overridepublic void onBackPressed() {
    Intent home = new Intent(Intent.ACTION_MAIN);
    home.addCategory(Intent.CATEGORY_HOME);
    startActivity(home);
}

固然,此种方式经过Home键效果强行影响到Back键对Activity生命周期的影响。注意,此方法只是针对按Back键须要退回到桌面时的Activity且达到Home效果才重写。

或者,为达到此类效果,Activity实际上提供了直接的方法。

1 activity.moveTaskToBack(true);

moveTaskToBack()此方法直接将当前Activity所在的Task移到后台,同时保留activity顺序和状态。

 

在以前的项目开发过程当中,当时遇到一个很奇怪的问题:手机上的“开发者选项”中有一个“不保留活动”的设置,当开启此设置,手机上的设置提示是“用户离开后即销毁每一个活动”,开启后,对于其余的应用程序是从A Acticity到B Activity,而后Back键回到A,此时,其余应用程序只是先白屏(有可能黑屏等,取决于主题设置)一下,而后A开始可见,可是个人应用程序中出现的一个结果倒是直接返回到了桌面。一开始百思不得其解。最后终于定位出问题。首先,咱们须要明确开启此设置项后对Activity生命周期的影响。开启此设置项后,当A到B时,假设B所有遮挡住了A,将依次执行A:onPause -> B:onCreate -> B:onStart -> B:onResume -> A:onStop -> A:onDestroy。是的,A在系统本来的生命周期回调中增长了onDestroy。此即“用户离开后即销毁每一个活动”的含义。但此时须要注意的是,只要没有认为的调用A的finish()方法,虽然A执行了onDestroy,但Activity栈中依然保留有A,此时B处于栈顶。那么在B中按Back键回到A时,将依次执行:B:onPause -> A:onCreate -> A:onStart -> A:onResume -> B:onStop -> B:onDestroy。没错,A从onCreate开始执行了。此处也就解释了为何A可能会出现白屏(或黑屏等)一下的缘由了。

那么为何个人应用程序会跟其余应用程序出现不同呢?最后定为出问题在于当时个人应用程序中为了作到彻底退出应用程序效果,专门使用了一个Activity栈去维护Activity(当时是借鉴了网上的此类实现方案,如今想一想,实在不必,且不说Android自己特性决定了不必经过如此方法去达到退出效果,仅仅是此方法自己也存在很大的问题,如今在网上依然能见到有很多文章说到应用程序退出可使用此方法,哎。。),在onCreate中入栈,onDestroy出栈,调用了以下方法

1 // 结束Activity&从堆栈中移除2 AppManager.getAppManager().finishActivity(this);

其中,AppManager中finishActivity函数具体定义是:

复制代码

 1 /** 2  * 结束指定的Activity 3  */ 4 public void finishActivity(Activity activity) { 5     if (activity != null) { 6         activityStack.remove(activity); 7         activity.finish(); 8         activity = null; 9     }10 }

复制代码

至此,相信你们应该看出问题的所在了吧。

没错,问题在于执行了activity的finish()方法!! activity的finish()方法至少有两个层面含义,1.将此Activity从Activity栈中移除,2.调用了此Activity的onDestroy方法。对于不开启“不保留活动”的设置项,实际上也没什么影响,可是一旦开启此设置,问题显露无疑。开启此此设置后,正常状况下离开A,即便执行了A的onDestroy,Activity栈中仍是有A的,可是我这样写后,finish()方法一执行,Activity栈中就没有A了,所以,当点击Back键时,Activity栈中已经没有此应用的任何Activity了,直接来到了手机桌面。

可能,有些人会说,我就是要经过此种方法想去彻底退出应用程序,同时但愿本身的Activity栈和系统中Activity栈保持一致,怎么办呢?

在此,能够经过以下改写去实现:

 

复制代码

/*** 结束指定的Activity */public void finishActivity(Activity activity) {    if (activity != null) {    // 为与系统Activity栈保持一致,且考虑到手机设置项里的"不保留活动"选项引发的Activity生命周期调用onDestroy()方法所带来的问题,此处须要做出以下修正
    if(activity.isFinishing()){
        activityStack.remove(activity);        //activity.finish();
        activity = null;
    }
    }
}

复制代码

 

以此谨记!

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

此外,对于不一样的启动模式或Intent Flags或操做行为(如横竖屏切换)等有可能会影响到Activity生命周期,此类问题将放在后续相关文章中进行总结。

相关文章
相关标签/搜索