Activity生命周期
Android中的Activity是可以相互层叠的。我们每启动一个新的Activity,就会覆盖在原来Activity之上。Back键会销毁最上面的Activity
返回栈的概念:在Android系统中,我们是通过任务task来管理ACtivity的,一个任务就是一组存放在栈里面的ACtivity。展示总是最顶层的Activity展示,销毁也是。
Activity的状态
1.运行状态
Activity处于栈顶的位置时候,就是运行状态
2.暂停状态
一个Activity不处于栈顶了仍然可见。
3.停止状态
不处于栈顶,并且完全不可见。系统仍然会为处于停止状态的Activity保留资源
4.销毁状态
Activity从返回移除后就变成了销毁状态,系统倾向于回收处于这种状态的Activity
各种状态被系统回收的优先级:
销毁状态 > 停止状态 > 暂停状态 > 运行状态
Activity的生存期
Activity类中定义了7个回调方法,覆盖了Activity生命周期的每一个环节
我们又可以将上面的7中方法,按照状态来分成两两相对。将Activity分成三种生存期
1.完整生存期:onCreate方法和onDestroy方法之间经理的就是完整生存期。一个onCreate就是一个Activity出生,onDestroy就是一个ACtivity死亡。
2.可见生存期:Activity在onStart方法和onStop方法之间所经历的就是可见生存期,当前Activity不一定能和用户进行交互,但是一定是可见的。我们可以在onStart中加载自选,onstop中释放资源
3.前台生存期:Activity在OnResume()方法和onPause之间经历的就是前台生存期,Activity总是处于运行状态,此时的Activity是可以和用户进行交互的。
图示如下:
通过代码体验Activity的生命周期:
首先创建一个新的项目,在layout里面创建两个样式,一个normal_layout.xml一个dialog_layout.xml项目,
两个部分文件里面编写的样式一样,自己定义。文件变一下就行,
最重要的是在AndroidMainfest.xml里面配置主题样式
最后我们在MainAActivity里面编写代码:
启动程序之后:
可以看到首先打印出日志
来到当前的主Activity上
当点击
NormalActivit的按钮,会看到日志打印
Activity页面跳转,说明当前的主Activity不可见了。但是还没有被销毁
我们点击back之后,回到主Activity
日志打印:说明主Activity被重新启动,来到运行状态。
当我们点击第二个按钮的时候:
打印日志:由于我们设置Dialog是对话框的主题,所以我们的主Activity仍然对我们是可见的。
同样我们点击back之后,回到主页面,日志打印
最后我们点击back退出app之后日志打印
Activity被回收了怎么保证数据不丢失
场景:当我们的Activity进入了停止状态,由于系统对资源的分配策略。我们的Activity有可能被回收掉。
当我们启动了Activity1,我们再Activity1上面启动了Activity2,Activity1就进入了停止状态,此时如果不慎被系统回收了。那么我们留在Activity1中的数据怎么能保证不丢失。
解决:Activity提供了一个onSaveInstanceState()方法,该方法会在当前Activity回收之前被调用。
我们在onCreate取数据
重点:发现Bundle和我们Intent类似,Intent也可以结合Bundle一起用于传递数据,我们将数据保存在Bundle中,然后再将Bundle放在Intent里面。
注意:当我们手机屏幕发生旋转的时候,也会进行Activity的创建和销毁。
Activity启动模式
Activity启动模式有四种,分贝是standard,singleTop,singleTask和singleInstance
我们在AndroidMainfest.xml中通过
standard
Activity默认启动模式,在不进行显示指定的情况下,所有Activity都会自动使用这种启动模式。
特点:每启动一个都会位于栈顶,不会考虑栈是是否存在当前的Activity。
代码测试:
日志信息:
singleTop
该模式的特点是,当发现栈顶已经是当前Activity了,就不需要再启动新的Activity,认为可以直接使用它
首先在AndroidMainfest.xml中修改OneActivity的启动模式
MianActivit的代码还有上一个的,多次点击Button,查看日志信息,可以看到只会创建一次实例
如果当前Activity不在栈顶的位置,该模式下还是会创建Activity
修改代码:
在SecondActivity中
然后项目运行起来,点击button,查看日志
由于点击之后,OneActivity仍然在栈中,但是并不在顶层,所以会重复创建Activity
singleTask
每次启动Activity的时候,系统首先会在返回栈中检查是否存在该Activity实例,如果发现已经存在则直接,使用该实例,并把在这个Activity之上所有其他的Activity统统出栈,,如果没有则再创建一个新的Activity实例
编写代码:
首先在OneActivity里面重写Restart(目的是标识OneActivity重启之后,能够体现出来)
在SecondACtivity中添加onDestory()
运行之后,打印日志
通过日志打印可以看出:创建的时候,发现栈中已经有了需要的Activity,地址值为一致的。
singleInstance
指定为singleInstance模式忽的Activity会启用一个新的返回栈来管理这个Activity,相当于解决了Avtivity共享的问题,见名知意,可以类比单例来理解,只不过ACtivity是个需要使用task来承载。所以会新开一个,供全局使用。
代码实现:
首先在AndroidMainfest.xml文件中,将SecondActivity设置为singleInstance
然后改写OneActivity中的代码:
修改SeconACtivity中的代码:
最后编写ThirdActivity中的代码:
最后运行项目:查看日志
图解示意:
Activity实践技巧
1.获取当前Activity
如何根据当前界面判断当前处在哪一个Activity里面呢?
我们使用面向对象的继承特性,在子类中重写方法时会先调用父类的方法,我们先编写一个BaseActivity类,并让其变得可继承(Kotlin中的特性)
我们项目中其他结构的Activity直接继承BaseActivity,由于BaseActivity又是继承AppCompatActivity,本来的功能不受影响
这样我们可以查看日志得出结果:
2.退出程序
问题:键退出程序,我们不需要back,back,bakc退出。直接一键就退出
修改BaseActivity中的代码
在ThirdActivity中编写退出的逻辑。
3.启动Activity的最佳写法。
问题:我们再启动一个Activity是,不清楚需要传送那些数据,需要翻看别人写的代码,这样比较麻烦。我们通过一下方式进行改造,提高开发效率
比如在FirstActivity,要启动SecondActivity代码,首先在SecondActivity中编写
启动: