Activity

作者: 珞神 | 来源:发表于2017-10-10 14:19 被阅读0次

    前言

    • 参考书:Android 开发艺术探索

    • 本篇主要介绍 Activity 的生命周期、启动模式和 Intentfliter 的匹配规则

    正文

    一、Activity 的生命周期

    分两种: 正常情况下和异常情况下的生命周期

    1.1 正常情况下的生命周期,从上到下
    • onCreate(): 表示 Activity 正在创建,可以做一些初始化工作。

    • onStart(): 表示 Activity 正在启动,这时 Acticity 已经创建出来了,只是没有出现在前台,用户看不到

    • onResume(): 表示 Activity 已经可见,可以与用户进行交互

    • onPause(): 表示 Acticity 正在停止,此时可以做一些停止动画、存储数据等操作,但是注意不能耗时,因为只有这个方法执行完毕,新的 Activity 的 onResume 才会执行

    • onStop(): 表示 Activity 即将停止,可以做一些重量级的回收工作,但是不能耗时

    • onDestroy(): 表示 Activity 即将被销毁,可以做一些回收工作和资源释放

    还有一个 onRestart() 方法,此方法表示 Activity 正在重新启动,一般情况下在 Activity 从不可见到可见状态的时候,会调用此方法,比如说 A 跳转到 B 然后再返回 A

    1.2 异常情况下的生命周期
    1.2.1 资源相关的系统配置发生改变导致 Activity 被杀死并重新创建

    比如说,横竖屏切换的时候,显示的图片资源及布局文件等系统配置发生改变,默认情况下,Activity 会被销毁并重新创建,其生命周期方法如下:

    • 首先会调用 onSaveInstanceState() 方法,做数据保存工作,系统默认为我们保存当前 Activity 的视图结构,并在 Activity 重启后,为我们恢复这些数据,比如 文本框中用户输入的数据,ListView 滚动的位置等,但是如果针对于某个 View 来说,能恢复什么数据,可以看 View 的源码来分析,因为 View 和 Activity 一样,都有 onSaveInstanceState() 方法来保存数据,保存的数据在其参数 Bundle 中

    • 其次,调用 onPause() 、onStop()、onDestory() 方法,注意 onSaveInstanceState() 方法可能在 onPause() 之前调用,也可能在其之后调用。

    • 然后,调用 onCreat() 方法,然后继续调用 onRestoreInstanceState() 方法来为其恢复状态和数据,我们可以根据这两个方法中的参数 Bundle 来判断此 Activity 是否被重建

    1.2.2 资源内存不足,导致低优先级的 Activity 被杀死

    这种方式与上边的第一种情况保存和恢复数据的方法一致,这里说下 Activity 的优先级,从高到低,如下所示:

    • 前台 Activity ,正在与用户交互,优先级最高

    • 可见,但并非前台 Activity ,比如 Activity 中弹出一个对话框,导致 Activity 可见,但是无法与用户交互

    • 后台 Activity ,已经被暂停的 Activity ,比如执行了 onStop() 方法,优先级最低

    另外注意,如果一个进程中没有四大组件运行,那么这个进程将会很快被杀死!

    1.2.3 阻止 Activity 重新创建

    在 AndroidMenifest.xml 中为 Activity 添加一条 configChanges 属性 :

     android:configChanges="orientation"
    

    常用属性值的含义:

    • locale :设备的本地位置发生了改变,一般指切换了系统语言

    • orientation :设备屏幕发生改变,比如旋转屏幕

    • keyboardHidden :键盘的可访问性发生了改变,比如用户调出了键盘

    • screenSize :屏幕尺寸信息发生改变,常用于旋转屏幕导致的 尺寸信息改变,一般和 orientation 配合使用

    • smallestScreenSize :表示设备的物理屏幕尺寸发生改变,注意指的是物理设备,跟旋转屏幕没关系,比如用户切换到了外部的显示设备,这个不常用。

    二、Activity 的启动模式

    2.1 四种启动模式
    • standard :标准模式,也是系统的默认模式,每次启动一个 Activity 都会创建一个新实例,不管这个实例是否存在,会一一放入任务栈中,然后按回退键的时候,会按照先进后出的原则,一一退栈!

    • singleTop :栈顶复用模式,如果新创建的 Activity 已经位于任务栈的栈顶了,那么此 Activity 不会被重建,注意这个 Activity 的 onCreat()、onstart() 方法不会被调用,因为它并没有发生改变,但是会回调 onNewIntent(Intent intent) 方法,从而获取 intent 信息。

    • singleTask :栈内复用模式,这是一种单实例模式,只要 Activity 在一个栈中存在,那么多次启动 Activity 都不会重新创建实例,和 singleTop 一样,也会回调其 onNewIntent(Intent intent) 方法,但是需要注意一点,如果栈中有的话,该模式,会把所需要的 Activity 之上的所有 Activity 弹出栈,将需要的这个 Activity 放于栈顶!

    • singleInstance : 它是一种加强版的 singleTask ,它除了具有 singleTask 的所有特性之外,还加强了一点,就是只能单独的位于一个栈中!一个栈只能有一个 Activity

    2.2 为 Activity 指定启动模式
    • 第一种,通过 AndroidMenifest.xml 文件中,为其添加属性
    android:launchMode="singleTop"
    
    • 第二种,通过在 Intent 中设置标志位 Flags 来为 Activity 指定模式
    Intent intent = new Intent(this,TextActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
    
    • 两种方式的区别:
    1. 优先级,第二种要高于第一种,两种都存在的话,以第二种为准;
    2. 限定范围不同,第一种无法为 Activity 指定 FLAG_ACTIVITY_CLEAR_TOP 标识,第二种无法为 Activity 指定 singleInstance 模式!
    2.3 Activity 的 Flags

    Activity 的 Flags 有很多,作用也很多,有些可以设定 Activity 的启动模式,有些可以影响 Acticity 的运行状态,这里记录些比较常用的 Flags

    • FLAG_ACTIVITY_NEW_TASK ,指定 Activity 的启动模式为 singleTask

    • FLAG_ACTIVITY_SINGLE_TOP ,指定 Activity 的启动模式为 singleTop

    • FLAG_ACTIVITY_CLEAR_TOP ,当 Activity 启动时,与其在同一个任务栈并在其上边的所有 Activity 全部出栈,一般和 singleTask 启动模式一块出现

    • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS ,在某些情况下,我们不希望用户通过历史列表回到我们的 Activity 的时候,使用这个标记,等同于 xml 文件中的属性: android:excludeFromRecents="true"

    三、Activity 中 IntentFilter 匹配规则

    • Activity 的启动方式有两种,显式启动和隐式启动,如果两者都存在那么以显示为主,显式启动很简单,主要记录下隐式启动

    • 隐式启动需要 Intent 能够匹配目标组件的 IntentFilter 中的过滤信息,过滤信息有三个,分别是 action 、 category 、 data,下边针对这三个过滤信息做介绍

    3.1 action 的匹配规则
    • action 只是一个字符串,区分大小写,系统中有预定义的一些 action 我们也可以自定义自己所需要的 action, action 可以有多个,但是我们只要匹配成功一个即可匹配成功,需要注意的是,只要是隐式启动,那么 Intent 中必须要有 action
    3.2 category 的匹配规则
    • category 也是一个字符串,category 也可以有多个,但是必须要每个都匹配成功才行,另外,如果需要隐式启动,那么必须添加 android.intent.category.DEFAULT 这个 category ,因为我们调用 startActivity 方法的时候,系统会默认为我们添加这个一个 category ,所以必须要添加
    3.3 data 的匹配规则
    • data 相对复杂一点,结构如下
    <data android:scheme="aaa"
     android:host="aaa"
     android:port="aaa"
     android:path="aaa"
     android:pathPattern="aaa"
     android:pathPrefix="aaa"
     android:mimeType="aaa"/>
    

    主要是有两部分组成 mimeType 和 Uri

    1. mimeType 指媒体类型 例如: image/jpeg vided/* ...
    2. Uri 的结构如下:
    <scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]
    

    Uri 的属性介绍如下:

    scheme:整个URI的模式,如常见的http,file等,注意如果URI中没有指定的scheme,那么整个uri无效
    host:URI的域名,比如我们常见的www.mi.com,www.baidu.com,与scheme一样,一旦没有host那么整个URI也毫无意义;
    port:端口号,比如80,很容易理解,只有在URI中指定了scheme和host之后端口号才是有意义的;
    path,pathPattern,pathPrefix包含路径信息,path表示完整的路径,pathPattern在此基础上可以包含通配符,pathPrefix表示路径的前缀信息;
    
    • 只匹配 scheme 的例子如下:
            <activity android:name=".TextActivity">
    
                <intent-filter>
                    <action android:name="111"></action>
                    <category android:name="android.intent.category.DEFAULT"></category>
                    <data android:scheme="222"></data>
                </intent-filter>
    
            </activity>
    
            Intent intent = new Intent();
            intent.setAction("111");
            // scheme:// 固定写法,后边的 111 是自己随便写的
            intent.setData(Uri.parse("222://111"));
    
            startActivity(intent);
    
    • 只匹配 mimeType 的例子如下
            <activity android:name=".TextActivity">
    
                <intent-filter>
                    <action android:name="111"></action>
                    <category android:name="android.intent.category.DEFAULT"></category>
                    <data android:mimeType="image/*"></data>
                </intent-filter>
    
            </activity>
    
            Intent intent = new Intent();
            intent.setAction("111");
            // 这种情况,scheme 默认为 content ,亲测 file 会报错
            //注意此处是 setDataAndType 
            intent.setDataAndType(Uri.parse("content://111"),"image/png");
            startActivity(intent);
    
    • 注意,data,不是必须要添加的,也就是说如果只有 action 和 category 也能匹配成功
    • 还有一点,如果我们要启动系统的页面,如打电话页面,需要找到其匹配规则,进行匹配,然后启动

    • 另外,IntentFilter 可以有多对,只要匹配其中一对即可成功。

    相关文章

      网友评论

          本文标题:Activity

          本文链接:https://www.haomeiwen.com/subject/oovvyxtx.html