1.综述
(1)这里说的activity不是一个类(类Activity),而是指一些用户自定义类,这些类都继承了类Activity,他 们具有同样的性质,故我们统称他们为activity。
(2)activity是android应用程序的一个重要的组成部分。一个activity对象就是一个与用户交互的UI界面。在activity上承载了一个或者多个view(即视图),打个最简单的比方就是说,一个聊天界面,就是一个activity,其中聊天窗口,头像窗口等等就是一个个view。
(3)一个应用程序可以是一个activity,也可以有众多的activity。另外一个activity可以充满了整个屏幕,也可以在屏幕的中间部分,即悬浮在屏幕上。
(4)在SDK中有一句关于浮动窗口的话读不太懂,慢慢研究While activities are often presented to the user as full-screen windows, they can also be used in other ways: as floating windows (via a theme with windowIsFloating set) or embedded inside of another activity (using ActivityGroup).
(5)在activity中有两个方法是几乎都要重载的,onCreate(Bundle)和onPause()。
onCreate(Bundle) is where you initialize your activity. Most importantly, here you will usually call setContentView(int) with a layout resource defining your UI, and using findViewById(int) to retrieve the widgets in that UI that you need to interact with programmatically.
onPause() is where you deal with the user leaving your activity. Most importantly, any changes made by the user should at this point be committed (usually to the ContentProvider holding the data).
2.activity生命周期
(1)首先声明一个至关重要的一点,activity的管理是通过系统管理中的一个activity栈来管理的。每次有一个activity进入start状态,它将至于栈的顶端。新的activity总是在栈的最上面,栈可以push和pop,但是栈中activity的顺序不会改变。比如原来有activity A,A没有被kill的情况下又新建了activity B,那么B就在A的上面。如果再回到A的话,A和B的位置不会改变。
(2)下面这个图很好的说明了activity的生命周期
(3)根据这个图来说,activity的状态有3个对应关系,onCreate()和onDestroy(),onStart()和onStop(),onResume()和onPause(),这3个关系把activity的生命周期分为了3个部分:entire lifetime,visible lifetime,foreground lifetime。列表如下:
生命周期 | 函数 | 描述 |
entire lifetime | onCreate() onDestroy() | 进程的生命周期,只要进程还在,这个生命就没有死亡,进程启动时onCreate()函数被调用,onDestory()进程结束。 |
visible lifetime | onStart() onStop() | 可见的生命周期,顾名思义,在用户界面上显示该activity时,onStart()被调用,该activity从用户界面消失时,onStop()被调用。 |
foreground lifetime | onResume() onPause() | 前台的生命周期,当该activity在所有activity最前面,即栈顶时,onResume()被调用,当activity被其他activity覆盖,onPause()被调用。 |
(4)在activity的生命周期中有几个关键的动作:
A将该activity退出foreground
这个时候该activity进入onPause()状态。
B将该activity不再visible
这个时候该activity进入onStop()状态。
C其他activity需要内存空间
这个时候由系统决定新activity需要调用哪些内存空间,如果需要将用到该activity用到的空间,则不管该activity在onPause()或者是onStop(),都要将该activity的进程kill掉以释放内存。
D将该activity重新打开
根据原先该activity的状态来确定现在的操作,如果原来的进程被kill掉了,就要重新create,如果原先已经stop,就要进行restart,如果原先已经pause,就要进行resume。
(5)生命周期总结
Activity的生命周期可以类比于一个电影播放器,首先打开一部电影(onCreate()),接着开始播放(onStart()),电影就可以播放了,如果有其他事情要做,就可以将电影暂停(onPause()),做完事回来,继续播放(onResume()),电影播放完毕以后(onStop()),如果要再看这部电影需要重新播放(onRestart())。这个过程有一点是如果暂停播放(onPause())或者是播放结束(onStop()),我需要做的其他事需要播放器的空间,就要将播放器给关掉(kill掉这个activity的进程)。
造成这种生命周期的原因是,操作系统在回收一个进程的资源的时间是不确定的。一个进程,如果它的activity不在屏幕的前前端时,就有可能性被kill掉以释放资源给新的activity。所以onStop()和onPause()状态都是killable的。
(6)activity的进程被kill的顺序
Activity进程被kill的顺序有个优先级,数字越大,优先级越大,越容易被kill掉。
<1>foreground activity 也就是呈现在屏幕最前端的activity。这些activity的进程被kill掉的情况只有一个,就是当这个activity要求的资源比设备提供的资源还要多。
<2> visible activity 可见的activity。这些activity的进程被kill的情况是为了保持foreground activity的运行。
<3> background activity 不可见的activity,并且已经暂停了。当这些activity要被kill的时候,要进行状态的保存,当下次打开这个activity的时候,就会重新create,并恢复暂停前的状态。
<4> empty process 没有任何组件的进程。这些进程是很容易被kill掉的。所以当需要进行一个没有activity的进程(比如,上传照片等)时,最好开一个service的组件以降低被kill的优先级。
3.保存activity的状态
根据activity的生命周期来看,一个activity一旦不可见以后,它的进程很容易就被kill掉,这样就要求我们保存activity的状态。
(1)从哪里保存状态
首先我们要了解,什么时候我们的activity可能被kill掉,答案是pause以后。一个很好的想法就是我们把状态在onPause()这个函数中保存起来,但是有个问题就是如果这样的话,那么每次pause,无论有没有被kill掉,都会进行保存,这样就进行了很多重复操作。
另一个方法就是我们可以通过重载一个叫做onSaveInstanceState(Bundle)的函数,这个函数是当一个进程要被kill之前调用的,以便重新create的时候能够恢复原状。让我们来看看这个函数的具体情况:
<1> onSaveInstanceState(Bundle)是Activity类的一个成员函数,它在默认情况下会调用该activity下每个view的onSaveInstanceState()来保存所有的视图信息。
<2> onSaveInstanceState(Bundle)被调用的情形有些不清晰。reference中提到If called, this method will occur before onStop(). There are no guarantees about whether it will occur before or after onPause().但是在dev guide中提到的却是 Android calls this method before making the activity vulnerable to being destroyed — that is, before onPause() is called.所以到底这个方法在什么时候被调用还不好说。
<3>用这个方法来保存状态有个很大的问题是它不是activity生命周期的一部分,所以它不一定会执行。比如说,A正在运行,然后运行B将A覆盖,用户按返回键返回A,这时B处于Pause状态,但它不会被kill,这样,onSaveInstanceState(Bundle)方法将不会执行,状态将不会被保存,再次打开这个activity时,它是重新create的。
最后在SDK中得出结论:
onSaveInstanceState(Bundle)用于保存图形界面等瞬时的数据。而onPause()保存持久性的数据。
我对这个结论是这样理解的,持久性数据相对于瞬时数据更加重要而且不能丢失,通过onPause()可以很好的做到这一点。而瞬时数据(如view的图形数据)相对较大,不适合在onPause中保存,所以通过onSaveInstanceState(Bundle)的默认实现来保存。
(2)怎样保存数据
既然onSaveInstanceState(Bundle)大多是情况下使用默认实现,那么只要考虑onPause()方法的实现。未完……