《Android开发艺术探索》读书笔记之Activity的生命周期与启动模式

来源:互联网 发布:淘宝比较好的灯饰店 编辑:程序博客网 时间:2024/05/16 09:56

1.1 Activity的生命周期分析

1.1.1 典型情况下的生命周期


分为如下几种情况:
1. Activity第一次启动时的回调为:onCreate->onStart->onResume;
2. 当前Activity被其他Activity覆盖或者Home键切换到桌面时,回调如下: onPause->onStop。如果其他Activity采用了透明主题,那么当前Activity不会回调onStop;
3. 当用户再次回到原Activity时,回调如下:onRestart->onStart->onResume;
4. 当用户按back键回退时,回调如下:onPause->onStop->onDestroy;
5. Activity被系统回收后再次打开,生命周期方法回调过程和1一样,注意只是生命周期方法一样,不代表所有过程都一样;
6. onCreate和onDestroy配对,标识Activity的创建和销毁,只能有一次调用;从Activity可见性来说,onStart和onStop配对,例如屏幕的点亮和熄灭,这两个方法可能被调用多次;从Activity是否在前台来说,onResume和onPause配对,伴随用户操作也可能被调用多次。

1.1.2 异常情况下的生命周期

情况1:资源相关的系统配置发生改变导致Activity被杀死并重新创建
例如Activity的横竖屏切换,由于系统配置发生了改变,Activity就会被销毁并重新创建。
在异常状态发生的时候,在界面销毁前会调用onSaveInstanceState()(onStop之前执行)保存当前Activity的状态,如文本框内的数据,ListView滚动的位置等。在重建后会调用onRestoreInstanceState()(onStart之后执行)进行数据恢复。
关于某个特定View的数据保存与恢复:首先Activity被意外终止时,Activity会调用onSaveInstanceState去保存数据,然后Activity会委托Window去保存数据,接着Window再委托它上面的顶级容器(可能是DecorView)去保存数据。最后顶层容器再去一一通知它的子元素来保存数据,这样整个数据保存过程就完成了。我们通过EditText来说明View的数据保存与恢复过程。
自定义MyEditText并继承EditText:

public class MyEditText extends EditText {    public MyEditText(Context context, AttributeSet attrs) {        super(context, attrs);    }    public MyEditText(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @Override    public Parcelable onSaveInstanceState() {        Parcelable parcelable = super.onSaveInstanceState();        return parcelable;    }    @Override    public void onRestoreInstanceState(Parcelable state) {        super.onRestoreInstanceState(state);    }}
布局文件如下:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    android:gravity="center">    <com.android.android_art.ui.MyEditText        android:id="@+id/myEditText"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:textSize="25sp"        android:text="这是测试文本"/></LinearLayout>

运行程序,我们选中MyEditText中的文字,如下图所示:


我们旋转屏幕,通过设置断点查看EditText如何保存自身信息状态:


观察程序25行代码将父类(TextView)保存的自身状态:parcelable变量:

parcelable.selStart=2表示选中文字的起始位置为2,即"测"字,结束位置为4,即“文”字,但并不包含在选中文字范围内。

旋转屏幕后


旋转过程中,通过回调onRestoreInstanceState()恢复数据,设置断点,如下所示:


可以看出通过回调onRestoreInstanceState(Parcelable state),其中state与onSaveInstanceState()中的parcelable变量中的状态一样,从而达到恢复数据状态的作用。。。

情况2:资源内存不足导致低优先级的Activity被杀死
Activity按照优先级从高到低依次为:前台Activity->可见但非前台Activity->后台Activity。当系统内存不足时,系统就会按照上述优先级杀死目标Activity所在进程。所以后台工作不适合独立运行,应该放入Service从而保证有一定的优先级,这样不会被轻易杀死。

1.2 Activity的启动模式分析

Activity有如下四种启动模式:

一、 standard:标准模式。每次启动一个Activity都会重新创建一个新的实例,典型的多实例实现,它运行在启动它的那个Activity所在的栈中。
二、singleTop:栈顶复用模式。如果新Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,onNewIntent也会被回调。
三、singleTask:栈内复用模式。只要Activity在一个栈中存在,那么多次启动此Activity都不会重新创建实例,由于该模式具有clearTop的效果,所以该Activity上面的所有Activity都会被出栈。
四、singleInstance:栈内单例模式。该Activity启动后,系统会为它创建一个新的任务栈,并独自拥有这个任务栈。

IntentFilter的匹配规则

Activity的启动分为显式调用和隐式调用。其中隐式调用需要Intent能够匹配目标组件的IntentFilter中所设置的过滤信息,如果不匹配将无法启动目标Activity。
IntentFilter中的过滤信息有action、category、data,一个Activity可以有多个IntentFilter,只要intent能匹配任意一组intent-filter即可启动成功。
关于每一项的具体匹配规则
  • action: 本身是字符串. Intent匹配中存在action且必须和过滤规则中的其中一个action相同,那么action就算匹配ok. xml中必须有一个action声明.
  • category: 本身是字符串.Intent匹配中intent可以不存在category,但是如果添加了category那么必须要和定义的intent-filter中的category一致,否则失败. 如果我们在Intent不添加的时候,那么系统会自动为我们添加一个预定义的属性android.intent.category.DEFAULTxml中需添加这个默认的category属性.
  • dataxml过滤规则中可以不声明,如果声明只要匹配了一个就可以.一般情况下data有两部分组成mimeType和URI. 





阅读全文
0 0
原创粉丝点击