Activityn 生命周期
前言
Activity 生命周期,虽然开发android 程序有几年了,但是很多基本东西还是经常遗忘模糊,在此笔记白纸黑字记录,下次记忆模糊的时候温故知新。网上一搜索一大把,但是多是一大堆各种日志搅来搅去比较模糊难懂,有个别的文章就是一知半解比较片面,这个看似简单但是又说清道不明,为了更加简单快速的理解并做笔记,我使用的是官方的示例ActivityLifecycle运行结果作为记录依据
Activity生命周期重要性
activity生命周期是应用程序井井有条运行的根本,也许不需要实现所有的生命周期方法。但了解每一个方法的回调时机并在其中填充相应功能,使得确保app能够像用户期望的那样执行是很有必要的。比如使用app的时候,不会因为有来电通话或者切换到其他app而导致程序crash。 用户没有激活某个组件时不会消耗宝贵的系统资源。 离开app并且一段时间后返回,不会丢失用户的使用进度。 设备发生屏幕旋转时不会crash或者丢失用户的使用进度,这些情况都是要建立在充分的理解activity的生命周期。所以我们需要学会如何去管理
activity
的生命周期
生命周期图 四条流程线路
流程一
启动程序进入到activity A 界面 然后退出该程序
流程二
启动程序进入到activity A 界面,点击Dialog按钮弹出对话框,然后关闭对话框
流程三
启动程序进入到activity A 界面然后点击home键回到桌面,然后再次点击该程序再次回到activityA 的时候
流程四
流程四不好演示,总之内存紧张的时候,比如MainActivity处于onPause和onStop状态时,当更高优先级的apps需要内存,而此时系统内存不够了,那么android系统就会将MainActivity所在的进程给杀了以释放资源。当被杀了之后又想重生,那必须得从头开始创建。onCreate ---> onStart() ---> onResume()
最后
最后当我们在第一个 activityA中按back键,退出时,最终就会走到onDestory,或者在代码中调用finish()的时候也会走到onDestroy()这一步,从而关闭Activity或者退出程序。
Activity 生命周期之我见
(1)记得刚开始接触android的时候,觉得生命周期总是搅来搅去的,模模糊糊的,网上也有很多文章就是组合各种情况打印各种日志一大堆,看到头大,总觉得里面的东西规则摸不准,其实他们很多都是把简单问题复杂化了,我刚接触android的时候也深受其害
(2)当我们以不同的参照对象分别开来进行分析的时候(比如只看Activity A ),发现每一个对象走的生命周期流程无非就是上面那四流程中的一种
(3)对象多了,当我们从把所有对象当成整来看待的时候,个他们之之间的生命周期的好像就是交错在一起(比如A启动B时候A 调用了 onPause,然后B启动完成了,A又调用了onStope),各种情况记不到也说不清楚,网上就是很多这么干得
(4)其实我们不应该把他们当成整体来看,这种观念会让自己陷入困境的,如果项目中(多个对象(Activity)生命周期交错)真的需要确定多个对象生命周期各个方法执行的先后顺序的时候,那个时候来打印下日志就一目了然,当具体到项目实际需要的时候再去细致化处理比较合适,举一个简单的例子如下面的复合情况
复合情况(对于不同的参考对象来看生命周期)
启动程序进入到activity A,点击Activity B,然后关闭Activity B
分析:整个过程我们需要分开来看 :
(1)对于activity A来说生命周期是流程三
(2)对于Activity B 来说生命周期是流程一
分析复合情况
复合情况是在开发中经常遇到的,万变不离宗,分开来看就可以了,就这么简单,无他,但是要特别注意 Activity的四种启动模式(standard、singleTop、singleTask、singleInstance),我现在所列举的都是默认模式。
(1)比如正在Activity-A界面,突然打电话过来的时候或者接收短信,这个时候弹出一个框提示,可以理解启动了另外一个界面,当然看Activity-A界面是否覆盖全屏,如果不覆盖全屏该界面,那么Activity-A界面就调用onPause(),(我的手机是弹出一个小Dialog)如果下一步取消接电话或者取消看短信回到Activity-A界面时候就调用Activity-A的onResume(),如果接电话那么就被全屏覆盖当那个接电话界面启动的完成的时候Activity-A的onStop()方法,接电话结束回到Activity-A界面就会调用 onRestart()(不是生命周期方法) ——>onStart()——>onResume()
分析生命中期中三种静态
activity生命周期只有三个状态是静态的,这三个状态下activity可以存在一段比较长的时间,而其它几个状态会很快就切换掉,停留的时间比较短暂。
(1)Resumed:该状态下,activity处在前台,用户可以与它进行交互。(通常也被理解为”running” 状态)
(2)Paused:该状态下,此时
Activity
程序失去了焦点,一般情况
activity的部分被另外一个activity所遮盖:另外的activity来到前台,但是半透明的,不会覆盖整个屏幕。被暂停的activity不再接受用户的输入且不再执行任何代码
(3)Stopped:该状态下, activity完全被隐藏,对用户不可见。可以认为是在后台。当stopped, activity实例与它的所有状态信息(如成员变量等)都会被保留,但activity不能执行任何代码,如果其他地方需要内存,系统会销毁这个
activity。
分析其他状态
其它状态 (Created与Started)都是短暂的
(1)一旦onCreate 操作完成,系统会迅速调用onStart() 与onResume()方法,我们的activity不会在Created或者Started状态停留,系统快速的执行那些回调函数并通过执行下一阶段的回调函数移动到下一个状态
(2)也就是说,在系统调用 onCreate(), 之后会迅速调用onStart(), 之后再迅速执行onResume()。activity在onStart()被调用后开始被用户可见,但是 onResume()会迅速被执行使得activity停留在Resumed状态,直到一些因素发生变化才会改变这个状态。例如接收到一个来电,用户切换到另外一个activity,或者是设备屏幕关闭,以上就是基本的activity生命周期。
生命周期在项目开发中注意事项
activity暂停
当系统调用activity中的onPause() ——>准备离开这个activity ——> 马上会进入Stopped state.
(1)通常应该在onPause()回调方法里面做以下事情,停止动画或者是其他正在运行的操作,那些都会导致CPU的浪费. 提交在用户离开时期待保存的内容(例如邮件草稿). 释放系统资源,例如broadcast receivers, sensors (比如GPS), 或者是其他任何会影响到电量的资源。
(2)不应该使用onPause()来保存用户改变的数据到永久存储(File或者DB)上,我们应该避免在onPause()时执行CPU intensive的shut-down的工作,例如写数据到DB,因为它会导致切换到下一个activity变得缓慢,应该放到onStop(),反正尽量减少在onPause()里面耗时的工作量
(3)尽管onPause()方法是在onStop()之前调用,我们应该使用onStop()来执行那些CPU intensive的shut-down操作
activity恢复
Activity从Paused()状态恢复时 ——>调用onResume()方法
(1)应该实现onResume()来初始化那些在onPause方法里面释放掉的组件,并执行那些activity每次进入Resumed state都需要的初始化动作 (例如开始动画与初始化那些只有在获取用户焦点时才需要的组件)
activity停止
当activity调用onStop()方法, activity不再可见
(1)应该释放那些不再需要的所有资源。一旦activity停止了,系统会在需要内存空间时摧毁它的实例(和栈结构有关,通常 back操作会导致前一个activity被销毁)。极端情况下,系统会直接杀死我们的app进程,并不执行activity的onDestroy()回调方法, 因此我们需要使用onStop()来释放资源,从而避免内存泄漏。(这点需要注意)
(2)activity已经停止后,Activity对象会保存在内存中,并在activity resume时被重新调用。我们不需要在恢复到Resumed state状态前重新初始化那些被保存在内存中的组件。系统同样保存了每一个在布局中的视图的当前状态,如果用户在EditText组件中输入了 text,它会被保存,因此不需要保存与恢复它。
重启activity
当activity从Stopped状态回到前台时,它会调用onRestart(),系统再调用onStart()方法
(1)onStart()方法会在每次activity可见时都会被调用。onRestart()方法则是只在activity从stopped状态恢复时才会被调用,因此我们可以使用它来执行一些特殊的恢复(restoration)工作,请注意之前是被stopped而不是destrory。
(2)应该使用onStart()作为onStop()所对应方法。因为系统会在创建activity与从停止状态重启activity时都会调用onStart()。也就是说,我们在onStop里面做了哪些清除的操作,就该在 onStart里面重新把那些清除掉的资源重新创建出来。
(3)因为我们会在onStop方法里面做释放资源的操作,那么onDestory方法则是我们最后去清除那些可能导致内存泄漏的地方。因此需要确保那些线程都被destroyed并且所有的操作都被停止
-------------------------------------------------------------------------------------------------------------------------------------------------------------
Activity 数据保存
(1)如果因为系统资源紧张而导致Activity的Destory或者旋转屏幕时被destroyed与Recreated, 系统会在用户回到这个Activity时有这个Activity存在过的记录,系统会使用那些保存的记录数据(instance state)它是一些存放在Bundle对象中的key-value pairs,系统默认使用 Bundle保存信息
(2)为了可以保存额外更多的数据到instance state,要重写写这个回调函数onSaveInstanceState(Bundle outState),系统会在Activity被异常Destory时传递Bundle对象,这样我们就可以增加额外的信息到Bundle中并保存到系统中。若系统在Activity被Destory之后想重新创建这个Activity实例时,之前的Bundle对象会(系统)被传递到你我们activity的
(3)Activity开始stop,系统会调用 onSaveInstanceState(Bundle outState) ,Activity可以用键值对的集合来保存状态信息。这个方法会默认保存Activity视图的状态信息,如在 EditText组件中的文本或 ListView 的滑动位置
Activity 数据恢复
(1)当Activity从Destory中重建,我们可以从系统传递的Activity的Bundle中恢复保存的状态。 onCreate() 与 onRestoreInstanceState() 回调方法都接收到了同样的Bundle,里面包含了同样的实例状态信息。
(2)由于 onCreate() 方法会在第一次创建新的Activity实例与重新创建之前被Destory的实例时都被调用,我们必须在尝试读取 Bundle 对象前检测它是否为null。如果它为null,系统则是创建一个新的Activity实例,而不是恢复之前被Destory的Activity。
(3)也可以选择实现 onRestoreInstanceState() ,而不是在onCreate方法里面恢复数据。 onRestoreInstanceState()方法会在 onStart() 方法之后执行. 系统仅仅会在存在需要恢复的状态信息时才会调用 onRestoreInstanceState() ,因此不需要检查 Bundle 是否为null。