一、Activity状态

  Activity有三种状态:active/running、paused、stopped。

  1、active/running状态,在当前屏幕时,即用户可见的Activity,位于当前Task的栈顶。

  2、paused状态,Activity失去焦点但对用户依然可见。也就是说在它上面有另外一个非全屏或者透明的Activity,并成为了当前的焦点。它还没有被其他的Activity完全遮盖住,而paused的Activity依然是alive状态的,它保留着所有的状态和成员信息并连接至窗口管理器,但当系统处于极低内存的情况下,仍然可以杀死这个Activity。

  3、stopped 状态,当Activity完全被另一个Activity覆盖时,它仍然保留所有的状态和成员信息。但它不再被用户可见,所以它的窗口将被隐藏,当其它地方需要内存,则系统经常会杀死这个Activity。

  当Activity是paused或者stopped状态时,系统可以通过要求它结束(调用它的finish()方法)或直接杀死它的进程来将它驱出内存。当它再次为用户可见的时候,它只能完全重新启动并恢复至以前的状态。

启动并恢复至以前的状态。

二、为什么会有这么麻烦的状态变化

  1、手机屏幕大小有限,只能看到有限的界面数量,用户需要通过Back键或Home键或其他方式切换Activity。

  2、在有手机来电时,系统会优先切换显示电话接听界面。

  由于上述的一些原因,确实存在界面随时可能发生切换的情况,最佳方式当然不是每次都直接销毁之前的界面,很多时候我们也需要在回到之前界面后恢复之前的状态。我们需要了解这些状态,当然还包括要掌握Activity的“生命周期”等知识,这样就能够在Activity发生变化时,知其所以然,并能够根据需求采取一定的措施,例如切换界面时,保存当前的界面信息,即使其被意外杀死也能恢复之前状态。

三、Activity生命周期

  当一个Activity从这个状态转变到另一个状态时,它被以下列protected方法所通知:

public class Activity extends ApplicationContext
{
protected void onCreate(Bundle savedInstanceState); protected void onStart(); protected void onRestart(); protected void onResume(); protected void onPause(); protected void onStop(); protected void onDestroy();
}

  1、onCreate -- 当Activity第一次创建时会被调用(未被销毁前不会被再次调用)。在这个方法中可以做一些初始化工作,例如对创建新的View、获取并设置View的一些属性、绑定列表的数据等等。如果能捕获到Activity 状态的话,这个方法传递进来的Bundle对象将存放了Activity当前的状态。调用该方法后一般会调用onStart()方法。此时Activity不可见,所以并不是所有的初始化工作都适合在这里做,例如一些动画的开始。

  2、onRestart -- 在Activity被停止后重新启动时会调用该方法。其后续会调用onStart方法。

  3、onStart -- 当Activity对于用户可见前即调用这个方法。如果Activity回到前台则接着调用onResume() ,如果Activity隐藏则调用onStop()。此时Activity可能可见,但即使可见,也无法进行交互操作。

  4、onResume -- 在Activity开始与用户交互前调用该方法。在这时该Activity 处于Activity 栈的顶部,并且接受用户的输入。其后续会调用 onPause() 方法。此时Activity也不一定可见,需要通过onWindowFocusChanged(boolean)来确定Activity是否可见。

  5、onPause -- 在系统开始准备恢复其它Activity时会调用该方法。这个方法中通常用来提交一些还没保存的更改到持久数据中,停止一些动画或其它一些耗CPU的操作等等。无论在该方法里面进行任何操作,都需要较快速完成,因为如果它不返回的话,下一个Activity 将无法恢复出来。如果Activity 返回到前台将会调用onResume(),如果Activity变得对用户不可见了将会调用onStop() 。

  6、onStop -- 在Activity对用户不可见时将调用该方法。可能会因为当前Activity 正在被销毁,或另一个Activity(已经存在的Activity 或新的Activity )已经恢复了正准备覆盖它,而调用该方法。如果Activity 正准备返回与用户交互时后续会调用onRestart ,如果Activity正在被释放则会调用onDestroy 。

  7、onDestroy -- 在Activity被销毁前会调用该方法。这是Activity能接收到的最后一个调用。可能会因为有人调用了finish方法使得当前Activity正在关闭,或系统为了保护内存临时释放这个Activity的实例,而调用该方法。你可以用isFinishing方法来区分这两种不同的情况。

  要注意的是,onPause(),onStop(),onDestory()这3个方法都可能会因为系统内存不足而被系统直接kill。而平常从一个Activity转向/回到另一个Activity时,当新Activity是full screen(弹出窗口,例如AlertDialog是不算的)的时候就会调用前一个Activity的onPause(),然后调用onStop(),而无论onPause或者onStop,都有可能被kill,所以一般在onPause时就应该保存需要持久化的一些数据(例如用户编辑的信息)。

  onCreate、onStart、onResume都不是Activity准确能够交互的点,真正的是onWindowFocusChaned()函数被执行时。

四、Android的进程

  android根据其重要性在内存不足的时候移去重要性最低的进程。重要性由高到低为:

  1、活动/前台进程

    指那些有组件正和用户进行交互的应用程序进程。他们都是android尝试通过回收资源来使其保持响应的进程。这些进程的数量非常少,只用到最后的关头才会终止这些进

程。

    活动进程包括:

      处于“活动”状态的Activity,也就是说,它们位于前台并对用户事件进行响应。
      正在执行onReceive事件处理程序的广播接收器。
      正在执行onCreate()、onStart()或onDestory事件处理程序的服务。
      正在运行,且已被标记为前台运行的服务。
  2、可见进程
    可见,但是非活动的进程是指那些驻留可见活动的进程。顾名思义,可见的活动能被用户看到,但是他们并不是在前台运行或者能对用户事件做出响应,比如,当一个活动Activity被部分遮挡的时候(被一个非全屏或者半透明状态的Activity遮挡时)就会出现这类情况。这类进程的数量很少,只有在资源极度缺乏的环境下,为保证活动进程的继续执行,才会终止这些进程。

  3、服务进程

    已经启动的服务进程。服务支持在没有可见界面的情况下,仍然能继续不间断地进行处理。因为后台服务没有直接和用户进行交互,所以它们的优先级要比可见进程低一些。但是他们仍然被认为是前台进程。除非活动或者可见进程需要资源,否则不会终止它们。

  4、后台进程
        不可见,并且没有任何正在运行的服务的活动的进程,通常会有大量的后台进程。这样的程序拥有一个用户不可见的Activity。这样的程序在系统内存不足时,按照LRU的顺序被结束。

    运行着一个对用户不可见的Activity(调用过onStop() 方法)。这些进程对用户体验没有直接的影响,可以在服务进程、可见进程、前台进程需要内存的时候回收。通常,系统中会有很多不可见进程在运行,他们被保存在LRU (least recently used) 列表中,以便内存不足的时候被第一时间回收。如果一个Activity正确的执行了它的生命周期,关闭这个进程对于用户体验没有太大的影响。
  5、空进程
    这样的进程不包含任何活动的程序部件。系统可能随时关闭这类进程。未运行任何程序组件。运行这些进程的唯一原因是作为一个缓存,缩短下次程序需要重新使用的启动时间。系统经常中止这些进程,这样可以调节程序缓存和系统缓存的平衡。

  Android对进程的重要性评级的时候,选取它最高的级别。另外,当被另外的一个进程依赖的时候,某个进程的级别可能会增高。一个为其他进程服务的进程永远不会比被服务的进程重要级低。因为服务进程比后台Activity进程重要级高,因此一个要进行耗时工作的Activity最好启动一个Service来做这个工作,而不是开启一个子进程――特别是这个操作需要的时间比Activity存在的时间还要长的时候。例如,在后台播放音乐,向网上上传摄像头拍到的图片,使用Service可以使进程最少获取到“服务进程”级别的重要级,而不用考虑Activity目前是什么状态。broadcast receivers做费时的工作的时候,也应该启用一个服务而不是开一个线程。

五、Activity状态的保存

protected void onSaveInstanceState (Bundle outState)
protected void onRestoreInstanceState (Bundle savedInstanceState)

  onSaveInstanceState() 和 onRestoreInstanceState() 并不是生命周期方法。它们并不是总会被调用。例如通过Back造成的销毁Activity时,它就不会被调用。应该只用它来为Activity保存一些临时的状态,而不能用来保存持久性的数据。而是应该用onPause()来达到这个目的。

  onPause()方法是在系统结束应用程序前调用的最后一个安全的方法。无法保证onStop和onDestroy会被调用,所以不能依赖这两个方法来实现关键逻辑。

六、Activity的加载模式

  Activity加载模式(通过在AndroidManifest.xml文件中activity元素的android:launcherMode属性设置) 。请参考文章结尾附带的demo体验Activity的加载模式。

  1、standard(默认)
    测试方式:MainActivity(standard),SecondActivity(standard)
    每次都是创建了新的Activity实例。

  2、singleTop
    测试方式:MainActivity(singTop),MainActivity自己intent自己
    测试方式:MainActivity(singleTop),SecondActivity(standard)
    和standard一样是发送新的实例,但singleTop要求如果创建intent的时候栈顶已经有要创建的Activity实例,则将intent发送给该实例。例如给MainActivity设置singleTop,然后按钮也是intent自己,那么会发现一直都是MainActivity当前这个实例,因为他一直在栈顶,所以不会创建新的。

    如果用A打开B,而B再打开A,如此循环,如果A是设置了singleTop,B是默认,则每次A都是新的,因为每次要打开A时,栈顶都不是A,就要创建新的A实例(和都是 standard没啥区别了)。
    此种模式的应用场景,目前想到就是为了解决自己在栈顶时,自己给自己发送intent可以不创建新的实例。实际中应用的也较少。

  3、singleTask
    测试方式:MainActivity(singleTask),SecondActivity(standard)
    只创建一个实例。如果发现有对应的Activity实例,则是此Activity实例之上的其他Activity实例全部出栈,使此Activity实例成为栈顶对象,显示出来。
  4、singleInstance
    这个模式下的Activity单独在一个task栈中。这个栈只有一个Activity。目的是为了多个Task共享一个Activity。

七、Activity与View的生命周期

  View和Activity一样也有自己的生命周期,具体在View的周期中包含哪些通知函数,参见http://developer.android.com/reference/android/view/View.html。其中onMeasure、onLayout、onDraw最重要,而onMeasure最难理解(之后会单独讨论这个函数及其如何使用)。

八、Activity的注意事项

  1、onConfigurationChanged

    1)不设置Activity的android:configChanges时,屏幕切屏会导致当前Activity被销毁并重新创建。

    2)设置Activity的android:configChanges=“orientation”时,在3.2以前的版本会阻止系统默认的行为,即销毁并重新创建当前Activity。而3.2+的需要另外加上screenSize。
    3)而实际运行中还会有很多系统的配置改变导致Activity被销毁并重新创建,例如键盘模式、全局字体大小发生改变等等(具体有哪些参见http://developer.android.com/guide/topics/manifest/activity-element.html),对于这些配置的改变,不应该盲目使用configChanges配置拦截,理应根据实际需求来决定是否拦截及处理。

    4)当使用onConfigurationChanged自行处理时,必须调用super.onConfigurationChanged(newConfig),不能删除,否则会报调用异常错误。

九、参考文章

  http://blog.csdn.net/liuhe688/article/details/6754323

  http://marshal.easymorse.com/archives/2950

  android:configChanges  

  http://blog.csdn.net/imdxt1986/article/details/7339711

  http://blog.csdn.net/huiguixian/article/details/8071821

  http://bbs.csdn.net/topics/390413976

Activity加载模式测试DEMO

Activity相关知识点总结的更多相关文章

  1. Android开发涉及有点概念&相关知识点(待写)

    前言,承接之前的 IOS开发涉及有点概念&相关知识点,这次归纳的是Android开发相关,好废话不说了.. 先声明下,Android开发涉及概念比IOS杂很多,可能有很多都题不到的.. 首先由 ...

  2. IOS开发涉及有点概念&相关知识点

    前言,IOS是基于UNIX的,用C/C+/OC直通系统底层,不想android有个jvm. 首先还是系统架构的分层架构 1.核心操作系统层 Core OS,就是内存管理.文件系统.电源管理等 2.核心 ...

  3. UITableView相关知识点

    //*****UITableView相关知识点*****// 1 #import "ViewController.h" // step1 要实现UITableViewDataSou ...

  4. IOS之UI--小实例项目--添加商品和商品名(使用xib文件终结版) + xib相关知识点总结

    添加商品和商品名小项目(使用xib文件终结版) 小贴士:博文末尾有项目源码在百度云备份的下载链接. xib相关知识点总结 01-基本使用 一开始使用xib的时候,如果要使用自定义view的代码,就需要 ...

  5. 学习记录013-NFS相关知识点

    一.NFS相关知识点 1.NFS常用的路径/etc/exports NFS服务主配置文件,配置NFS具体共享服务的地点/usr/sbin/exportfs NFS服务的管理命令,exportfs -a ...

  6. TCP/IP 相关知识点与面试题集

    第一部分:TCP/IP相关知识点 对TCP/IP的整体认 链路层知识点 IP层知识点 运输层知识点 应用层知识点 (这些知识点都可以参考:http://www.cnblogs.com/newwy/p/ ...

  7. Python开发一个csv比较功能相关知识点汇总及demo

    Python 2.7 csv.reader(csvfile, dialect='excel', **fmtparams)的一个坑:csvfile被csv.reader生成的iterator,在遍历每二 ...

  8. Caffe学习系列(二)Caffe代码结构梳理,及相关知识点归纳

    前言: 通过检索论文.书籍.博客,继续学习Caffe,千里之行始于足下,继续努力.将自己学到的一些东西记录下来,方便日后的整理. 正文: 1.代码结构梳理 在终端下运行如下命令,可以查看caffe代码 ...

  9. php正则相关知识点

    关于正则,其实简单就是搜索和匹配.php,java,python等都是支持正则的,php正则兼容perl.好多同学觉得正则比较难,比较抽象,其实正则是非常简单的,主要是一个熟悉和反复练习的结果,还有一 ...

随机推荐

  1. Android事件分派机制

    最近一直在学习Android里面的事件分派机制,感觉很奇妙,看了很多博客和分析,才在脑子里形成了一个模糊的概念,对事件分派有了一定的认识. 于是,我画了一个图来简单明了的表述Android中事件的分派 ...

  2. NOIP赛前集训营-提高组(第一场)#B 数数字

    题目描述 小N对于数字的大小一直都有两种看法.第一种看法是,使用字典序的大小(也就是我们常用的判断数字大小的方法,假如比较的数字长度不同,则在较短一个前面补齐前导0,再比较字典序),比如43<3 ...

  3. 批量更新 A表的PK_ID字段

    UPDATE  ASET PK_ID=(SELECT ID FROM  B WHERE A.TAB_NAME=B.TAB_NAME AND B.IS_KEY='1' ) AB表 以TAB_NAME 做 ...

  4. [AT2567] [arc074_c] RGB Sequence

    题目链接 AtCoder:https://arc074.contest.atcoder.jp/tasks/arc074_c 洛谷:https://www.luogu.org/problemnew/sh ...

  5. 洛谷P5283 & LOJ3048:[十二省联考2019]异或粽子——题解

    https://www.luogu.org/problemnew/show/P5283 https://loj.ac/problem/3048 小粽是一个喜欢吃粽子的好孩子.今天她在家里自己做起了粽子 ...

  6. Luogu 3385 负环 | 我有特别的SPFA技巧

    这样似乎跑得快: 初始化所有的dis是0,然后枚举每个点作为起点,用DFS更新所有点的dis: 如果更新到一个栈中节点,那么有负环. #include <cstdio> #include ...

  7. Treat wchar_t as built-in type不一致导致的链接错误

    今天用VS2013新建了一个工程,生成时出现很多怪异的链接错误,比如: error LNK2019: unresolved external symbol "__declspec(dllim ...

  8. [HAOI2011]防线修建

    题目描述 近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了.可是A国上层现在还犹豫不决,到底该把哪些城市作为保护对象呢?又由于 ...

  9. Chapter3 (字符串,向量,数组) --C++Prime笔记

    1.using用法:using namespace ::name;注意事项:一般不在头文件使用using否则很容易导致运用命名空间不对错误. 2.string的方法: ①getline(输入流,str ...

  10. Qt ------ QWidget 自定义子类使用信号与槽(Q_OBJECT)后 stylesheet 失效

    这个应该属于 Qt 的一个bug,Qt assistant 给出相应的解决办法:重写函数“void paintEvent(QPaintEvent *event);”,添加下面截图中的一段代码