四大组件之activity详解
Activity详解
1.activity的定义
activity活动,窗体。四大组件中比较重要的一个,是应用不可缺少的一部分。承载界面的窗体,是用户可视化,可交互的载体。
2.activity的生命周期
上图描述的已经是很直观的了,我想作为一个android开发对这个图应该是深印脑海的。这里只对每一个生命周期做一个描述和特殊场景下生命周期的执行顺序做一个描述:
生命周期的解析:
- onCreate():activity创建,开始初始化view。首次启动时候执行该方法
- onStart():简单理解我可见。就是绘制完成,窗体可见。但仅仅是可见!在这里可以做一些初始化的操作
- onResume():可交互。当执行到这个生命周期后,用户和界面之间才可以交互。
- onPause():暂停,在这个生命周期中,界面可能是可见但不可交互的(比如有弹窗的时候)此时若弹窗消失,生命周期会再次回到onResume();或者是从可见到不可见,有别的窗体过来覆盖的情况。不管是什么情况,在这个生命周期中一般会做一些释放cpu的操作,比如停止动画等。
- onStop():不可见状态,activity完全被别的activity覆盖。
- onRestart():和onStop对应,当activity被停止而没有被销毁的时候,若再回到前台,不会从onCreate()开始执行,而是执行onRestart()-onStart()
- onDestroy():销毁,继不可见之后,将其销毁,也就是从栈中移除。这个activity不存在了。
简单理解生命周期的执行顺序:
首次启动一个activityA的时候,该activity的生命周期是:onCreate()-onStart()-onResume();
息屏:onPause()-onStop();
点亮屏幕:onRestart()-onStart()-onResume();
按返回键:onPause()-onStop()-onDestroy();
再次启动:onCreate()-onStart()-onResume();
Home按键返回桌面:onPause()-onStop();
再次打开应用:onRestart()-onStart()-onResume();
点击事件弹出一个窗体:onPause();
弹窗消失:onResume()
竖屏切换横屏时候的生命周期顺序:onPause()-onStop()-onDestroy()-onCreate()-onStart()-onResume();
生命周期的总结:
理解每一个生命周期的执行特点和执行顺序,可以很好的协助我们开发。
3.启动模式
>
在介绍启动模式之前,我们先来了解应用是如何管理activity的。一个应用是由很多activity组成的,这些activity中有一个入口。这些activity都存放在栈中,是由栈来管理的。具体的结合启动模式来理解。
- standard:默认的,在该模式下,每一次都会创建一个新的实例压入栈中。
- singleTop:栈中允许有多个相同的实例,但是不允许在栈顶叠加。也就是说只要栈顶存在就不会创建新的实例,而是调用onNewIntent来使用它
- singleTask:栈中唯一,也就是栈中只允许存在一个实例,所以只要栈中有,就不会再去创建新的,而是把它上边的activity全部销毁掉来调用它的onNewIntent来复用。
- singleInstance:唯一的栈,唯一的实例。该启动模式下的activity会单独创建一个栈来保存它,这个栈中也不允许有别的实例存在。
4.保存状态值
上边了解了生命周期和启动模式之后,我们知道activity是保存在栈中的。activity的onStop()状态是没有被销毁,还存在内存中,这时候他的成员信息和状态都是活的。所以这时候我们可以对他进行一些状态值的保存,当这个activity再回到前台时还是之前的状态。而这种方式就是通过onSaveInstanceState() 。
或许你会说,我没做任何操作也没有实现 onSaveInstanceState() 方法,activity的状态也是之前的效果。那是因为 Activity 类里面默认实现的 onSaveInstanceState 方法恢复出来。特别是会为布局中的视图( View )默认调用 onSaveInstanceState 方法,并在这个方法中允许每一个视图提供它需要恢复的任何信息。几乎每一个 Android 框架中的 widget 都视情况实现了这个方法,这样的话,这些 UI 的可视变化将会自动保存并在 activity 重建时被恢复。例如,一个 EditText 控件保存用户输入的内容,一个复选按钮保存它是否是被选中。你要做的只是给每一个你需要保存状态的 widget 提供一个唯一的 ID (用 android:id 属性)。如果一个 widget 没有 ID 的话,它将无法保存状态。
尽管默认实现了 onSaveInstanceState 方法来保存 activity UI 中重要的数据,但你也可以自己覆写它来保存一些额外的数据。比如,你可能需要保存一些在 activity 生命周期里更改的一些成员数据(比如一些与恢复 UI 有关、用来保存 UI 数据,但在默认情况下并没有被恢复的成员数据)。
典型案例:
横竖屏切换的时候是activity销毁在创建的过程。这时候我们就可以利用onSaveInstanceState方法来保存我们的替代资源,创建的时候取出展示。注意:这个保存的bundle会在onCreate(Bundle savedInstanceState)方法中返回。
5.安全退出多个activity
为什么要说这个问题呢,因为这是开发中最常见的一个问题,很多同学能理解启动模式,却不能很好的使用。下面举个开发中的场景
比如类似淘宝的一个商城查看商品详情,用户评价等等进入了深层页面,然后想回到首页就要一层一层的返回,用户体验很不好,所以会有一个按钮,直接返回首页,问题是怎么安全的退出这么多个activity
-
通过Intent的Flags来控制堆栈去解决:
android中,每打开一个Activity,便会在栈中加入一个Activity,当该Activity被销毁后,栈中便移除了它,并且栈中的Activity是按照启动的先后顺序依次压入栈的。
Android的窗口类提供了历史栈,我们可以通过stack的原理来巧妙的实现,这里我们在A窗口打开B窗口时在Intent中直接加入标 志 Intent.FLAG_ACTIVITY_CLEAR_TOP,这样开启B时将会清除该进程空间的所有Activity。Intent intent = new Intent(this,TestActivity2.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent); -
通过堆栈管理器,对Stack中存储的Activity进行操作(推入,推出,弹出)
实现一个StackManager 工具类来管理activity,在这个工具类中对栈中的activity进行操作,根据我们的需求来操作。
使用广播机制:通过Activity创建的时候,设置监听广播,在特定情况下,发送广播进行遍历finish()
该方法存在的缺点是浪费资源
总结:分析以上方法,最方便安全的就是第一种。