2020-06-21

2020-06-21  本文已影响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);

```

上一篇下一篇

猜你喜欢

热点阅读