Activity详解

一、Activity(活动):
1、定义:实现应用程序的可视化用户界面。所有Activity都必须在manifest文件(清单文件)中用activity标签生命。任何未经声明的Activity系统都会视而不见,且不会运行。
2、作用:它上面可以显示一些控件也可以监听并处理用户的事件做出响应

二、Activity的生命周期:
Activity类中定义了七个回调方法,覆盖了活动(activity)生命周期的每一个环节(依次是:)
1、onCreate():每个活动中都重写了这个方法,它会在activity第一次被创建的时候调用,因此,应该在这个方法里完成活动的初始化,比如:加载布局,绑定事件。
2、onRestart():在活动由停止状态变为运行状态之前被调用,也就是说活动被重新启动。(注:活动本身就存在栈中,没有调用onCreate()方法)
3、onStart():在活动由不可见变为可见的时候调用。
4、onResume():在活动准备好和用户进行交互的时候调用,此时的活动一定位于返回栈的栈顶,并处于运行状态。调用该方法后,界面可以和用户进行交互。
5、onPause():在系统准备去启动或恢复另一个activity的时候调用,通常会在这个方法中将一些消耗CPU的资源释放掉,以及保存一些相关数据,但是这个方法的执行速度一定要快,不然会影响到新的栈顶活动的使用。
6、onStop:在活动完全不可视的时候调用,它和onPause()方法的主要区别在于:onPause失去了焦点(不可点击),但仍处于可见的状态,而onStop()是失去焦点并处于不可见的状态,例如:启动的新活动是一个对话框的形式,就会执行onPuase(),而不会执行onStop()
7、onDestroy():在活动被销毁之前调用,之后活动的状态将变为销毁状态。在该方法中释放资源。
由上面的几个方法,我们对以下几种例子,来得出主界面调用了哪些方法:
1)、打开主界面,后退键退出
onCreate()->onStart()->onResume()->onPause()->onStop()->onDestroy()
2)、打开主界面,进入第二个页面,再按返回键返回
onCreate()->onStart()->onResume()->onPause()->onStop()->onRestart()->onStart()->onResume()
官方给出的一张Activity的生命周期图:
这里写图片描述
七个生命周期的组合:
onCreate、onStart、onResume:启动应用程序
onPause、onStop:失去焦点
onRestart、onStart、onResume:重新获得焦点
onPause、onStop、onDestroy:退出应用程序

定义生命周期的作用:
①当用户接一个电话或切换到另一个程序不会崩溃
②当用户后台运行程序时不会销毁有价值的系统资源
③当用户离开再返回你的应用时不会丢失用户的进程
④当手机屏幕进行横竖屏切换的时候不会崩溃或者丢掉用户的进程

三、任务和回退栈:
(一)任务Task:
1、概念:一个任务(task)就是在执行某项工作时与用户进行交互的Activity集合。这些Activity按照被打开的顺序依次被安排在一个堆栈中(回退栈)。
2、主屏页面:
设备的主屏是大多数任务的启动位置,当用户触摸一个应用程序启动器图标(或者app快捷图标),应用程序的任务就会在前台显示。如果相关应用程序的任务不存在,那么就会有一个新的任务被创建,并且应用程序打开的”主”Activity会作为任务中的根Activity。
(二)、回退栈:
1、概念:在当前的Activity启动了另一个Activity时,这个新的Activity被放到了堆栈的顶部,并且带有焦点。前一个Activity并没有消失,而是保存在
回退栈中,此时它处于停止状态。
当用户按下回退按钮时,当前的Activity会被从回退栈的顶部弹出(这个Activity被销毁),而前一个Activity被恢复。堆栈中的Activity不会被重新排列。因此,回退栈的操作跟后进先出的对象结构是一样的
在用户按下回退按钮的时,当前的Activity被销毁,并且前一个Activity被恢复。如果用户继续按回退键,那么回退栈中的每个Activity会被一次弹出,前一个Activity会被显示,直到用户返回主屏(或者返回到任务开始时运行的那个Activity)。当所有的Activity从回退栈中被删除时,这个任务就不再存在。
图:
这里写图片描述
注意:后台中可以拥有多个任务,但是如果用户同时运行了很多后台任务,系统为了回收内存可能销毁一些后台的Activity,从而导致Activity的状态丢失。

四、启动模式
在Android中Activity的启动模式决定了Activity的启动运行方式。
1、Activity的启动模式分为四种:
(1)standard(系统默认的启动模式)
标准启动模式,每次激活Activity时都会创建Activity,并放入任务栈中。每个窗体的getTastId()保持不变,但this.hashCode()会发生改变。
(2)singleTop:
如果在任务的栈顶正好存在该Activity的实例,就重用该实例,而不会创建新的Activity对象,不过它会调用onNewIntent()方法。如果栈顶不存在就会创建新的实例并放入栈顶(即使栈中已经存在该Activity实例,只要不再栈顶,都会创建实例),会回调onNewIntent()
(3)singleTask
如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的onNewIntent())。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移除栈。如果栈中不存在该实例,将会创建新的实例放入栈中。
和singleTop在名字上即可看出区别,即singleTop每次只检测当前栈顶的Activity是否是我们需要请求创建的,而singleTask则会检测栈中全部的Activity对象,从上向下,如果检测到是我们所请求的则会消灭此Activity对象上面的对象,直接把检测到的我们需要的Activity置为栈顶。
(4)singleInstance
与singleTask模式的区别是存放singleInstance模式窗口对象的回退栈不能有其他任何窗口对象。因此如果该窗口不存在,则要新建任务来存放该singleInstance模式窗口。也就是说getTaskId()会发现任务id发生了变化。
此启动模式和我们使用的浏览器工作原理类似,在多个程序中访问浏览器时,如果当前浏览器没有打开,则打开浏览器,否则会在当前打开的浏览器中访问。此模式会节省大量的系统资源,因为他能保证要请求的Activity对象在当前的栈中只存在一个。
总之,在开发Android项目时,巧妙设置Activity的启动模式会节省系统开销和提高程序运行效率。

五、Activity常见问题:
1、Activity返回时,如何返回数据?
(1)、在Activity1中用startActivityForResult()来启动另一个Activity2,
在Activity1中复写onActivityResult()方法,回调拿到返回的数据
(2)、在Activity2中利用setResult()方法返回数据给Activity1

2、异常情况下保存临时数据的方法:
在onSaveInstanceState()方法中保存数据
//读取数据的方法
方法1:onRestoreInstanceState(),该方法执行在onStart()方法之后
方法2:在onCreate方法中的入参,就是保存的数据,直接从中取出数据
注意:取出数据之前,一定要判断是否为空。

3、横竖屏切换的问题:
竖屏—>横屏:先杀死一个Activity,再创建一个Activity
横屏—>竖屏:先杀死一个Activity,再创建一个Activity
再杀死一个Activity,再创建一个Activity
原因:android的键盘导致的
可以设置清单文件中:
android:configChanges=”keyboardHidden|orientation|screenSize”
来保证横竖屏切换的时候,不改变Activity的生命周期
当横竖屏切换的时候,会触发:
public void onConfigurationChanged(Configuration newConfig);
横竖屏切换的时候可以在这个方法中做一些任务