一篇就够了系列之Activity全解析

前言:

Activity作为Android四大组件之一Google官方文档,是Android开发中最基本最常用的东西,那么,Activity的定义到底是什么呢?
从下面几个方面介绍下Activity:

  1. 生命周期
  2. 任务栈
  3. 启动模式
  4. scheme跳转协议

生命周期

这其实是一个老生常谈的东西,更是每一个Android开发人员熟记于心的东西,直接上图:
这里写图片描述

每个状态的特点大致为:

  • onCreate:初始化操作,不可见,不可触摸
  • onStart:创建完成,可见,不可触摸
  • onResume:运行状态,可见,可触摸
  • onPause:暂定状态,可见,不可触摸
  • onStop:停止状态,不可见,不可触摸
  • onDestory:销毁状态

下面五个循环状态需要注意:

  1. onCreate->onStart->onResume->onPause->onStop->onDestory(Activity创建到销毁)
  2. onResume->onPause->onResume此时Activity一直是可见状态,比如此时弹出了一个Diglog,生命周期就是该流程
  3. onStart->onResume->onPause->onStop->onRestart->onStart Activity A被Activity B所覆盖,然后B销毁,A重新出现在屏幕上,此时就是该生命周期的流程,这个和将App直接按Home建退到后台是一样的流程
  4. onCreate->onStart->onResume->onPause->onStop->APP process killed->onCreate 这个流程主要是Activity在后台,内存不足时被系统给回收销毁,然后再重新打开了。
  5. 屏幕在进行旋转后,生命周期是:销毁->创建,同时,会增加两个方法:onSaveInstanceStateonRestoreInstanceState,此时完整的生命周期是:onCreate->onStart->onResume->onPause->onSaveInstanceState->onStop->onDestory->onCreate->onStart->onRestoreInstanceState->onResume->Running状态 ,利用那两个方法,可以在销毁之前进行信息保存,创建的时候再直接去除,比如代码:
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.i("wy","oncreate");
        if(savedInstanceState!=null){
            String str=savedInstanceState.getString("wy");
        }
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);

        Log.i("wy","onRestoreInstanceState");
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("wy","wy");
        Log.i("wy","onSaveInstanceState");
    }

一般的视屏播放都是这样进行屏幕旋转状态保存的。

任务栈

定义:任务是指在执行特定作业时与用户交互的一系列 Activity。 这些 Activity 按照各自的打开顺序排列在堆栈(即返回栈)中。
这里写图片描述
这张图片说明了Activity 1,2,3在同一个栈中创建及销毁的示意图。很明显,一般情况下,新创建的Activity实例会在栈的顶部,Running状态,销毁后,下面的Activity会出现在栈顶,此时该Activity就是Running状态,实际上,一个应用,可以有多个任务栈同时存在,这就涉及到Activity的启动模式了。

启动模式

在清单文件中声明 Activity 时,您可以使用 元素的 launchMode 属性指定 Activity 应该如何与任务关联。
launchMode 属性指定有关应如何将 Activity 启动到任务中的指令。您可以分配给 launchMode 属性的启动模式共有四种:

“standard”(默认模式)

默认。系统在启动 Activity 的任务中创建 Activity 的新实例并向其传送 Intent。Activity 可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例。

“singleTop”

如果当前任务的顶部已存在 Activity 的一个实例,则系统会通过调用该实例的 onNewIntent() 方法向其传送 Intent,而不是创建 Activity 的新实例。Activity 可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例(但前提是位于返回栈顶部的 Activity 并不是 Activity 的现有实例)。
例如,假设任务的返回栈包含根 Activity A 以及 Activity B、C 和位于顶部的 D(堆栈是 A-B-C-D;D 位于顶部)。收到针对 D 类 Activity 的 Intent。如果 D 具有默认的 “standard” 启动模式,则会启动该类的新实例,且堆栈会变成 A-B-C-D-D。但是,如果 D 的启动模式是 “singleTop”,则 D 的现有实例会通过 onNewIntent() 接收 Intent,因为它位于堆栈的顶部;而堆栈仍为 A-B-C-D。但是,如果收到针对 B 类 Activity 的 Intent,则会向堆栈添加 B 的新实例,即便其启动模式为 “singleTop” 也是如此。

注:为某个 Activity 创建新实例时,用户可以按“返回”按钮返回到前一个 Activity。 但是,当 Activity 的现有实例处理新 Intent 时,则在新 Intent 到达 onNewIntent() 之前,用户无法按“返回”按钮返回到 Activity 的状态。

“singleTask”

系统创建新任务并实例化位于新任务底部的 Activity。但是,如果该 Activity 的一个实例已存在于一个单独的任务中,则系统会通过调用现有实例的 onNewIntent() 方法向其传送 Intent,而不是创建新实例。一次只能存在 Activity 的一个实例。
注:尽管 Activity 在新任务中启动,但是用户按“返回”按钮仍会返回到前一个 Activity。

“singleInstance”.

与 “singleTask” 相同,只是系统不会将任何其他 Activity 启动到包含实例的任务中。该 Activity 始终是其任务唯一仅有的成员;由此 Activity 启动的任何 Activity 均在单独的任务中打开。

说到Manifest中的注册文件,关于Activity的一共有以下:

<activity android:allowEmbedded=["true" | "false"]
          android:allowTaskReparenting=["true" | "false"]
          android:alwaysRetainTaskState=["true" | "false"]
          android:autoRemoveFromRecents=["true" | "false"]
          android:banner="drawable resource"
          android:clearTaskOnLaunch=["true" | "false"]
          android:configChanges=["mcc", "mnc", "locale",
                                 "touchscreen", "keyboard", "keyboardHidden",
                                 "navigation", "screenLayout", "fontScale",
                                 "uiMode", "orientation", "screenSize",
                                 "smallestScreenSize"]
          android:documentLaunchMode=["intoExisting" | "always" |
                                  "none" | "never"]
          android:enabled=["true" | "false"]
          android:excludeFromRecents=["true" | "false"]
          android:exported=["true" | "false"]
          android:finishOnTaskLaunch=["true" | "false"]
          android:hardwareAccelerated=["true" | "false"]
          android:icon="drawable resource"
          android:label="string resource"
          android:launchMode=["standard" | "singleTop" |
                              "singleTask" | "singleInstance"]
          android:maxRecents="integer"
          android:multiprocess=["true" | "false"]
          android:name="string"
          android:noHistory=["true" | "false"]  
          android:parentActivityName="string" 
          android:permission="string"
          android:process="string"
          android:relinquishTaskIdentity=["true" | "false"]
          android:resizeableActivity=["true" | "false"]
          android:screenOrientation=["unspecified" | "behind" |
                                     "landscape" | "portrait" |
                                     "reverseLandscape" | "reversePortrait" |
                                     "sensorLandscape" | "sensorPortrait" |
                                     "userLandscape" | "userPortrait" |
                                     "sensor" | "fullSensor" | "nosensor" |
                                     "user" | "fullUser" | "locked"]
          android:stateNotNeeded=["true" | "false"]
          android:supportsPictureInPicture=["true" | "false"]
          android:taskAffinity="string"
          android:theme="resource or theme"
          android:uiOptions=["none" | "splitActionBarWhenNarrow"]
          android:windowSoftInputMode=["stateUnspecified",
                                       "stateUnchanged", "stateHidden",
                                       "stateAlwaysHidden", "stateVisible",
                                       "stateAlwaysVisible", "adjustUnspecified",
                                       "adjustResize", "adjustPan"] >   
    . . .
</activity>

具体意义可以参照:Google官方文档

scheme跳转协议

这里的scheme是一种页面内跳转协议,主要用于支持一下几种场景:

  • 服务器下发跳转路径,客户端根据服务器下发跳转路径跳转相应的页面;

  • H5页面点击锚点,根据锚点具体跳转路径App端跳转具体的页面;

  • 从一个App跳转到另一个App的页面

    首先,我们需要知道URI的概念:
    URI:通用资源标识符(Universal Resource Identifier),URI主要分三个部分:scheme, authority and path。其中authority又分为host和port。格式如下:
    scheme://host:port/path, 比如:wy://myproject:8080/data/src/name,
    就安卓手机本身而言,比如手机联系人的信息,都是通过这样的格式进行提供,并且其scheme一般是“content”。

1.请求到服务器的请求数据后,可以前后端进行一个URI格式的定义,然后跳转相应的页面。比如
详情页:wy://myproject:8080/info
订单页:wy://myproject:8080/order
相应的Activity的manifest中的注册时这样的:

        <activity
            android:name=".InfoActivity"
            android:label="@string/title_info"
            android:theme="@style/AppTheme.NoActionBar">

            <intent-filter>

                <action android:name="android.intent.action.VIEW"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
                <category android:name="android.intent.category.BROWSABLE"></category>
                <data
                    android:scheme="wy"
                    android:host="myproject"
                    android:port="8080"
                    android:path="/info">
                </data>
            </intent-filter>
        </activity>

                <activity
            android:name=".OrderActivity"
            android:label="@string/title_Order"
            android:theme="@style/AppTheme.NoActionBar">

            <intent-filter>

                <action android:name="android.intent.action.VIEW"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
                <category android:name="android.intent.category.BROWSABLE"></category>
                <data
                    android:scheme="wy"
                    android:host="myproject"
                    android:port="8080"
                    android:path="/order">
                </data>
            </intent-filter>
        </activity>

注意:

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

上面两句一定不能少,

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

这句是想用js事件的,最好加上

                <data
                    android:scheme="wy"
                    android:host="myproject"
                    android:port="8080"
                    android:path="/order">
                </data>

这里面四个属性关系是一次下降,即scheme如果没有设置,下面三个设置的属性都会失效。

网页链接跳转为:

 tv.setText(Html.fromHtml("<a href='wy://myproject:8080/info'>点我一下</a>"));

注意:Java代码中的链接格式数据一定要**大于等于**manifest中注册的格式,比如针对以上的data格式,如果

tv.setText(Html.fromHtml("<a href='wy://myproject:8080'>点我一下</a>"));
tv.setText(Html.fromHtml("<a href='wy://myproject'>点我一下</a>"));
tv.setText(Html.fromHtml("<a href='wy://'>点我一下</a>"));

都是不行的,但是如果,manifest中data格式是:

                <data
                    android:scheme="wy"
                </data>

那么以上几种都是可以跳转的。主要就是上面要注意的几点问题,不然无法进行跳转。

App内部隐式跳转:

                Intent intent = new Intent();
                intent.setAction(Intent.ACTION_VIEW);
                intent.setData(Uri.parse("wy://myproject:8080/info"));
                startActivity(intent);

从一个App跳转到另一个App也是类似。

以上,主要就是Activity在开发中使用到的设计知识点。欢迎大家留言评论交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值