美文网首页
2020-06-21

2020-06-21

作者: 释空屹 | 来源:发表于2020-06-21 15:43 被阅读0次

    [TOC]

    # Activity生命周期

    ![](https://user-gold-cdn.xitu.io/2020/6/16/172bb94e227f8791?w=513&h=663&f=png&s=45666)

    - 1. Launcher 启动 Activity

    ![](https://user-gold-cdn.xitu.io/2020/6/9/172979a080948e6d?w=504&h=681&f=png&s=32810)

    - 2. Activity A 启动 B

    ![](https://user-gold-cdn.xitu.io/2020/6/10/1729dee8bfb67f4d?w=583&h=541&f=png&s=33560)

    如果Activity_B是透明的,则Activity_A不会执行onStop方法,Activity_B返回时,Activity_A直接调用onResume,回到前台。

    如果Activity_B不是是透明的,Activity_A设置了属性:android:noHistory="true",则Activity_A不会执行onStop方法,Activity_B返回时,Activity_A直接调用onStop->onDestroy。

    设置Activity为透明

    ```

        <style name="TransparentTheme" parent="Theme.AppCompat.NoActionBar">

            <!--不设置activity进入和退出动画样式-->

            <item name="android:windowAnimationStyle">@null</item>

            <!--设置窗口的背景为透明,设置透明背景必须要设置此项-->

            <item name="android:windowBackground">@android:color/transparent</item>

            <!--设置窗口的背景是否为半透明,设置透明背景必须要设置此项-->

            <item name="android:windowIsTranslucent">true</item>

            <!--设置状态栏的背景为半透明-->

            <item name="android:windowTranslucentStatus">true</item>

        </style>

    ```

    # 启动模式与属性

    - 1. Activity栈简介

    一个ActivityRecord对应一个Activity,一个Activity可能对应多个ActivityRecord,这与Activity的启动模式有关。

    ![](https://user-gold-cdn.xitu.io/2020/6/15/172b66984c61dc9b?w=172&h=278&f=png&s=9825)

    使用adb shell dumpsys activity activities查看Activity栈信息

    ```

    Stack #42: type=standard mode=fullscreen

        * TaskRecord{ee49cfc #50 A=com.android.activitydemonstration U=0 StackId=42 sz=2}

          affinity=com.android.activitydemonstration

          intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.activitydemonstration/.ActivityA}

          Activities=[ActivityRecord{2e0e9ef u0 com.android.activitydemonstration/.ActivityA t50}, ActivityRecord{305057 u0 com.android.activitydemonstration/.ActivityB t50}]

          stackId=42

          * Hist #1: ActivityRecord{305057 u0 com.android.activitydemonstration/.ActivityB t50}

              Intent { cmp=com.android.activitydemonstration/.ActivityB }

              taskAffinity=com.android.activitydemonstration

              state=RESUMED stopped=false delayedResume=false finishing=false

          * Hist #0: ActivityRecord{2e0e9ef u0 com.android.activitydemonstration/.ActivityA t50}

              packageName=com.android.activitydemonstration processName=com.android.activitydemonstration

              launchedFromUid=10068 launchedFromPackage=com.huawei.android.launcher userId=0

              app=ProcessRecord{2c0a3f5 1590:com.android.activitydemonstration/u0a155}

              Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.activitydemonstration/.ActivityA bnds=[798,1694][1050,2008] }

              taskAffinity=com.android.activitydemonstration

          TaskRecord{ee49cfc #50 A=com.android.activitydemonstration U=0 StackId=42 sz=2}

            Run #1: ActivityRecord{305057 u0 com.android.activitydemonstration/.ActivityB t50}

            Run #0: ActivityRecord{2e0e9ef u0 com.android.activitydemonstration/.ActivityA t50}

        mResumedActivity: ActivityRecord{305057 u0 com.android.activitydemonstration/.ActivityB t50}

        mLastPausedActivity: ActivityRecord{2e0e9ef u0 com.android.activitydemonstration/.ActivityA t50}

    ```

    - 2. Activity属性

    |属性|取值|说明|

    |:-|:-|:-|

    |taskAffinity|包名格式的字符串(如:.xxx)|activity的亲属关系, 默认为APP的包名|

    |launchMode|standard|默认启动模式;A启动B,每次启动都会在A的Task中新建一个B。|

    ||singleTop|A启动B,B的启动模式为singleTop,启动流程如下所示。![](https://user-gold-cdn.xitu.io/2020/6/16/172bb97452cb2356?w=485&h=505&f=png&s=31886)复用B时,B在onResume前执行noNewIntent。|

    ||singleTask|Activity A启动Activity B ,B的启动模式为singleTask,如果B的taskAffinity与A的不同,则寻找与B的taskAffinity相同的Task启动B;如果相同则在A的Task中启动B。流程图如下所示。![](https://user-gold-cdn.xitu.io/2020/6/16/172bb9914f8167c1?w=490&h=441&f=png&s=32238)如果B设置了新的taskAffinity,则这个栈会加到最近启动列表中。|

    ||singleInstance|A启动Activity B ,B的启动模式为singleInstance,新建一个与B的taskAffinity相同的Task启动B,而且这个Task中有且只有B这一个Activity。重复启动B则复用B,复用B时,B在onResume前执行noNewIntent。|

    | clearTaskOnLaunch | true/false|A启动B, 然后返回Home, 从新启动 B,如果A设置了这个属性为true,则不显示B,否则显示B |

    |configChanges|mcc|国际移动用户识别码所属国家代号是改变了,sim被侦测到了,去更新mcc    MCC是移动用户所属国家代号|

    ||mnc|国际移动用户识别码的移动网号码是改变了, sim被侦测到了,去更新mnc MNC是移动网号码,最多由两位数字组成,用于识别移动用户所归属的移动通信网|

    ||locale|用户所在区域发生变化,一般是用户切换了语言时,切换后的语言会显示出来|

    ||touchscreen|触摸屏改变了(通常是不会发生的)|

    ||keyboard|键盘发生了改变(例如用户用了外部的键盘)|

    ||keyboardHidden|键盘的可用性发生了改变|

    ||navigation|导航发生了变化(通常不会发生)|

    ||orientation|屏幕方向改变了(横竖屏切换)|

    ||fontScale|字体比例发生了变化(选择了不同的全局字体)|

    ||screenSize|屏幕大小改变了|

    ||screenLayout|屏幕的显示发生了变化(不同的显示被激活)|

    |||注:Android 4.0之前,设置"orientation keyboardHidden"起作用,Android 4.0之后,除了设置"orientation",还必须设置"keyboardHidden orientation screenSize"|

    |enabled|true/false|activity 是否可以被实例化|       

    |excludeFromRecents|true/false|是否可被显示在最近打开的activity列表里(true不显示,false显示,只有栈的根Activity设置该属性才生效)。|   

    |exported|true/false|是否允许activity被其它程序调用|       

    |permission|权限名称|设置启动这个Activity所需要的权限。|

    |process|进程名称|一个activity运行时所在的进程名。|

    |screenOrientation|unspecified|默认值,由系统决定,不同手机可能不一致|

    ||landscape|强制横屏显示|

    ||portrait|强制竖屏显|

    ||behind|与前一个activity方向相同|

    ||sensor|根据物理传感器方向转动,用户90度、180度、270度旋转手机方向,activity都更着变化|

    ||sensorLandscape|横屏旋转,一般横屏游戏会这样设置|

    ||sensorPortrait|竖屏旋转|

    ||nosensor|旋转设备时候,界面不会跟着旋转。初始化界面方向由系统控制|

    ||user|用户当前设置的方向|   

    |theme|"resource or theme "|activity的样式主题, 如果没有设置,则activity的主题样式从属于应用程序, 参见<application>元素的theme属性|       

    - 3. Intent的FLAG

    Intent中定义了很多个FLAG,其中有几个FLAG也可以设定Activity的启动方式,如果Launch Mode设定和FLAG设定的Activity的启动方式有冲突,则以FLAG设定的为准。

    |FLAG|说明|

    |:-|:-|

    |FLAG_ACTIVITY_SINGLE_TOP|和Launch Mode中的singleTop效果是一样的。|

    |FLAG_ACTIVITY_NEW_TASK|寻找和Activity关联(taskAffinity相同)的task,启动Activity;如果没有则新建task,启动Activity|

    |FLAG_ACTIVITY_CLEAR_TOP|LaunchMode中没有与此对应的模式,如果要启动的Activity已经存在于栈中,则将所有位于它上面的Activity(包括它自己)出栈,然后启动新的Activity。与FLAG_ACTIVITY_NEW_TASK合用,可打到类似singleTask的效果,但是不会复用Activity。|

    |FLAG_ACTIVITY_NO_HISTORY|Activity一旦退出,就不会存在于栈中。同样的,也可以在AndroidManifest.xml中设置“android:noHistory”。|

    |FLAG_ACTIVITY_MULTIPLE_TASK|需要和FLAG_ACTIVITY_NEW_TASK一同使用才有效果,系统会启动一个新的栈来容纳新启动的Activity。等同于singleInstance。|

    |FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS|Activity不会被放入到“最近启动的Activity”列表中。只有栈的根Activity设置这个FLAG才生效。|

    |FLAG_ACTIVITY_CLEAR_TASK|需要和FLAG_ACTIVITY_NEW_TASK一同使用才有效果,用于清除与启动的Activity相关栈的所有Activity。|

    # Activity启动方式

    - 1. 显示启动

    ```java

    从Activity启动

    Intent intent = new Intent(this, ActivityB.class);

    startActivity(intent);

    从Context启动

    Intent intent = new Intent(this, ActivityC.class);

    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    getApplicationContext().startActivity(intent);

    ```

    - 2. 隐式启动

    ```

            <activity

                android:name=".ActivityC">

                <intent-filter>

                    <action android:name="android.intent.action.VIEW"/>

                    <data android:scheme="app"/>

                    <data android:host="detail_view"/>

                    <category android:name="android.intent.category.DEFAULT"/>

                </intent-filter>

            </activity>

            从Activity启动

            Intent intent = new Intent();

            intent.setData(Uri.parse("app://detail_view"));

            startActivity(intent);

            从Context启动

            Intent intent = new Intent();

            intent.setData(Uri.parse("app://detail_view"));

            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            getApplicationContext().startActivity(intent);

    ```

    ```

            <activity

                android:name=".ActivityB">

                <intent-filter>

                    <category android:name="android.intent.category.DEFAULT"/>

                    <action android:name="com.activity.B"/>

                </intent-filter>

            </activity>

            从Activity启动

            Intent intent = new Intent();

            intent.setAction("com.activity.B");

            startActivity(intent);

            从Context启动

            Intent intent = new Intent();

            intent.setAction("com.activity.B");

            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            getApplicationContext().startActivity(intent);

    ```

    相关文章

      网友评论

          本文标题:2020-06-21

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