Activity那些事儿

1.Android在运行时,正常情况下,Activity的切换其实是将运行过的Activity压入栈中,每创建一个Activity就向栈中压入该Activity;当点击返回键的时候会销毁当前Activity,即将当前Activity从栈顶删除,接着显示栈中的第二个Activity(也即现在的栈顶Activity)。【注意:点击返回键是会destroy掉当前Activity的,而不是再将该Activity压入栈里】

2.想要按返回键时不再返回到前一个Activity,就要在前一个Activity跳转到当前Activity时执行this.finish();

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

一.Activity Lifecycle:

1.Android用Activity Stack来管理多个Activity,所以呢,同一时刻只会有最顶上的那个Activity是处于active或者running状态。其它的Activity都被压在下面了。

2. 如果非活动的Activity仍是可见的(即如果上面压着的是一个非全屏的Activity或透明的Activity),它是处于paused状态的。在系统内存不足的情况下,paused状态的Activity是有可被系统杀掉的。只是不明白,如果它被干掉了,界面上的显示又会变成什么模样?看来下回有必要研究一下这种情况了。

3.几个事件的配对可以比较清楚地理解它们的关系。Create与Destroy配成一对,叫entrie lifetime,在创建时分配资源,则在销毁时释放资源;往上一点还有Start与Stop一对,叫visible lifetime,表达的是可见与非可见这么一个过程;最顶上的就是Resume和Pause这一对了,叫foreground lifetime,表达的了是否处于激活状态的过程。

4.因此,我们实现的Activity派生类,要重载两个重要的方法:onCreate()进行初始化操作,onPause()保存当前操作的结果。

二.Process Lifecycle :

       在内存不足的时候,Android是会主动清理门户的,那它又是如何判断哪个process是可以清掉的呢?文档中也提到了它的重要性排序:

       1. 最容易被清掉的是empty process,空进程是指那些没有Activity与之绑定,也没有任何应用程序组件(如Services或者IntentReceiver)与之绑定的进程,也就是说在这个process中没有任何activity或者service之类的东西,它们仅仅是作为一个cache,在启动新的 Activity时可以提高速度。它们是会被优先清掉的。因此建议,我们的后台操作,最好是作成Service的形式,也就是说应该在Activity中启动一个Service去执行这些操作

       2.接下来就是background activity了,也就是被stop掉了那些activity所处的process,那些不可见的Activity被清掉的确是安全的,系统维持着一个LRU列表,多个处于background的activity都在这里面,系统可以根据LRU列表判断哪些activity是可以被清掉的,以及其中哪一个应该是最先被清掉。不过,文档中提到在这个已被清掉的Activity又被重新创建的时候,它的onCreate会被调用,参数就是onFreeze时的那个Bundle。不过这里有一点不明白的是,难道这个Activity被killed时,Android会帮它保留着这个Bundle吗?

       3.然后就轮到service process了,这是一个与Service绑定的进程,由startService方法启动。虽然它们不为用户所见,但一般是在处理一些长时间的操作(例如MP3的播放),系统会保护它,除非真的没有内存可用了。

       4.接着又轮到那些visible activity了,或者说visible process。前面也谈到这个情况,被Paused的Activity也是有可能会被系统清掉,不过相对来说,它已经是处于一个比较安全的位置了。

       5.最安全应该就是那个foreground activity了,不到迫不得已它是不会被清掉的。这种process不仅包括resume之后的activity,也包括那些onReceiveIntent之后的IntentReceiver实例。

       在Android Activity生命周期的讨论中,文档也提到了一些需要注意的事项:因为Android应用程序的生存期并不是由应用本身直接控制的,而是由 Android系统平台进行管理的,所以,对于我们开发者而言,需要了解不同的组件Activity、Service和IntentReceiver的生命,切记的是:如果组件的选择不当,很有可能系统会杀掉一个正在进行重要工作的进程

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

相同APP中,Activity1启动Activity2(通过FLAG_ACTIVITY_NEW_TASK启动,且定义了与Activity1不同的android:taskAffinity)后,HOME键回到桌面,再点击该APP图标,出现的不是Activity2,而是Activity1。原因:该app的启动时,系统将寻找root Activity所处的那个task,而该app的root activity为Activity1,所以显示Activity1界面。


APP1.Activity1启动APP2.Activity2(android:allowTaskReparenting 、 android:taskAffinity 皆默认)后两者taskID同,HOME键回到桌面,再点击该APP图标,出现仍是Activity2。原因类上,虽然APP2.Activity2的taskAffinity为默认的APP2,但默认不允许重新宿主,所以当其进入后台后也不会宿进APP2。


APP1.Activity1启动APP2.Activity2(android:allowTaskReparenting = true , android:taskAffinity 默认)后两者taskID同,HOME键回到桌面,再点击该APP图标,出现是Activity1,而若点击APP2图标则出现的是Activity2而非APP2的入口activity。原因类上,亦即APP2.Activity2的taskAffinity为默认的APP2,而允许重新宿主,则当其进入后台后会宿进APP2成为栈顶activity(按:重新宿主发生在组件进入后台时刻)。


APP1.Activity1启动APP2.Activity2(通过FLAG_ACTIVITY_NEW_TASK启动,android:allowTaskReparenting = true / false , android:taskAffinity 默认)后两者taskID不同,HOME键回到桌面,再点击该APP图标,出现是Activity1。

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

//以下属性为Activity的加载模式,控制跳转到栈中已有的Activity时是否重复产生同一个Activity的不同实例,还是跳转到该Activity的已有实例即可

AndroidManifest.xml文件中activity元素的android:launchMode属性:

  • standard //默认模式。该模式下,跳转到同一个Activity时会重复产生不同的实例;
  • singleTop //该模式下,若要跳转到的Activity已有实例存在于栈顶,则不重复产生实例,跳到栈顶实例即可,若即使该Activity已在栈中存在实例但不在栈顶,则在栈顶产生该Activity新的实例;
  • singleTask //该模式下,跳转到该Activity时只要栈中已存在其实例,则不再创建新实例,而是跳转到已有实例;
  • singleInstance //该模式下,跳转到该Activity时,在单独的一个栈里产生其实例,该栈只有一个Activity,若已有实例存在则不再产生新实例。该模式的应用,要从Task说起;

     

    详情如下:

            Task可以认为是一个栈,可放入多个Activity。比如启动一个应用,那么Android就创建了一个Task,后面依次启动的该应用的Activity都存在于这个栈中,即使调用其他应用的Activity,也存在于这个栈中。但是,有这样的需求,多个Task共享一个Activity,换句话说,不同的应用共享一个Activity(singleTask是在一个task中共享一个Activity)。现成的例子:比如我有一个应用是导游方面的,其中调用的google地图Activity。那么现在我比如按home键,然后到应用列表中打开google地图,你会发现显示的就是刚才的地图,实际上是同一个Activity。

            如果使用上面三种模式,是无法实现这个需求的,因为他们只能在本应用的栈里产生调用的Activity,而当切换到其他应用时也就进入了一个其他的栈,无法再用到前面应用的栈里的Activity。google地图应用中有多个上下文Activity,比如路线查询等的,导游应用也有一些上下文Activity。在各自应用中回退要回退到各自的上下文Activity中。        

            singleInstance模式解决了这个问题(绕了这么半天才说到正题)。让这个模式下的Activity单独在一个task栈中。这个栈只有一个Activity。导游应用和google地图应用发送的intent都由这个Activity接收和展示。

            这里又有两个问题:(1)如果是这种情况,多个task栈也可以看作一个应用。比如导游应用启动地图Activity,实际上是在导游应用task栈之上singleInstance模式创建的(如果还没有的话,如果有就是直接显示它)一个新栈,当这个栈里面的唯一Activity,地图Activity回退的时候,只是把这个栈移开了,这样就看到导游应用刚才的Activity了;(2)多个应用(Task)共享一个Activity要求这些应用都没有退出,比如刚才强调要用home键从导游应用切换到地图应用。因为,如果退出导游应用,而这时也地图应用并未运行的话,那个单独的地图Activity(task)也会退出了。  

    以上内容,详情参考:http://blog.csdn.net/berber78/article/details/41983617

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

    Activity的主要属性(AndroidManifest.xml中 <activity  android:XXX  ):

    allowTaskReparenting:设置成true时,和Intent的FLAG_ACTIVITY_NEW_TASK标记类似。

    alwaysRetainTaskStat:如果用户长时间将某个task移入后台,则系统会将该task的栈内容弹出只剩下栈底的activity,此时用户再返回,则只能看到根activity了。如果栈底的activity的这个属性设置成true,则将阻止这一行为,从而保留所有的栈内容。

    clearTaskOnLaunch:根activity的这个属性设置成true时,和上面的alwaysRetainTaskStat的属性为true情况搞好相反。

    finishOnTaskLaunch对于任何activity,如果它的这个属性设置成true,则当task被放置到后台,然后重新启动后,该activity将不存在了。

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

    一旦用户切换到其他应用,当前Activity就必须 pause, stop甚至被destroy,不能在后台处理其他事务。需要强调的事,严格来说你仍然可以在activity里创建自己的worker thread或async task之类做后台的事情,但这样做没有任何保障——因为一旦你所有的activity都被切换到了后台,系统随时可能kill掉你的process,你的后台任务随时可能悄无声息的死掉。

     

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

    当某个activity变得“容易”被系统销毁时,该activity的onSaveInstanceState就会被执行,除非该activity是被用户主动销毁的,例如当用户按BACK键的时候。
    注意上面的双引号,何为“容易”?言下之意就是该activity还没有被销毁,而仅仅是一种可能性。这种可能性有哪些?通过重写一个activity的所有生命周期的onXXX方法,包括onSaveInstanceState和onRestoreInstanceState方法,我们可以清楚地知道当某个activity(假定为activity A)显示在当前task的最上层时,其onSaveInstanceState方法会在什么时候被执行,有这么几种情况:
    1、当用户按下HOME键时。
    这是显而易见的,系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activity A是否会被销毁,故系统会调用onSaveInstanceState,让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则
    2、长按HOME键,选择运行其他的程序时。
    3、按下电源按键(关闭屏幕显示)时。
    4、从activity A中启动一个新的activity时。
    5、屏幕方向切换时,例如从竖屏切换到横屏时。
    在屏幕切换之前,系统会销毁activity A,在屏幕切换之后系统又会自动地创建activity A,所以onSaveInstanceState一定会被执行。
    总而言之,onSaveInstanceState的调用遵循一个重要原则,即当系统“未经你许可”时销毁了你的activity,则onSaveInstanceState会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据(当然你不保存那就随便你了)。
    至于onRestoreInstanceState方法,需要注意的是,onSaveInstanceState方法和onRestoreInstanceState方法“不一定”是成对的被调用的,onRestoreInstanceState被调用的前提是,activity A“确实”被系统销毁了,而如果仅仅是停留在有这种可能性的情况下,则该方法不会被调用,例如,当正在显示activity A的时候,用户按下HOME键回到主界面,然后用户紧接着又返回到activity A,这种情况下activity A一般不会因为内存的原因被系统销毁,故activity A的onRestoreInstanceState方法不会被执行。
    另外,onRestoreInstanceState的bundle参数也会传递到onCreate方法中,你也可以选择在onCreate方法中做数据还原。

     

     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值