Android基础知识回顾之Activity

开篇废话

最近公司忙着搬迁,没有太多的精力去分享一些比较耗时间分析的知识点,随之就跟着之前的计划,开始回顾一下Android相关的基础知识。

今天我们一起来回顾一下我们接触最多,相对来说最熟悉的四大组件之一,Activity。

其实,当我在想什么是Activity的时候,确实有那么一会儿懵逼的感觉,因为不知道该如何组织语言去表达。

在这里,我大概说一下我的理解,到时候与别人交谈的时候,可以用这个思路来表达:

在我们日常应用中,Android是与用户交互的接口,它提供了一个界面让用户进行点击、各种滑动操作,这就是Activity的意义


技术详情

这次的内容比较简单,看起来会比较轻松,我主要分四个角度来进行讲述:

1. Activity的生命周期

2. Android系统中的任务栈

3. Activity的启动模式

4. scheme跳转协议

1. Activity的生命周期

1.1 Activity的四种状态

running:
表明activity处于活动状态,用户点击屏幕,屏幕可以作出响应,它是一个处于activity栈顶的状态

paused:
表明activity失去焦点的时候,也许是被一个非全屏的activity占据,或者被一个透明的activity放置在activity栈顶,这种情况下,就处于paused状态,用户操作对它不会有响应,但并不代表它被销毁了,这时候,他所有的状态信息和成员变量都还在,除非系统内存非常紧张的时候,就有可能被销毁掉。

stopped:

当activity被另一个Activity完全覆盖的时候,被覆盖的那个activity就会处于stopped状态,当内存不紧张的时候,状态信息和成员变量也是还在的。

killed:

表明activity已经被系统回收掉了,状态信息和成员变量都已经不存在了。

1.2 Activity的生命周期分析

首先,我们都需要看懂下面这张图:

Activity生命周期

大概分析几个场景的调用流程:

1.Activity启动 -->  onCreate() --> onStart() --> onResume()

2.点击Home键回到系统主界面的时候 --> onPause() --> onStop()

3.当我们再次回到原来的那个Activity的时候 --> onRestart() --> onStart() --> onResume()

4.退出当前的Activity的时候 --> onPause() --> onStop() --> onDestory()

5.A Activity 调用弹出B Activity的时候(完全覆盖) --> A onPause() --> B onCreate() --> B onStart() --> B onResume --> A onStop()

6.Activity异常退出的时候 --> onPause() --> onSaveInstanceState() --> onStop() --> onDestory(),
需要注意的是onSaveInstanceState() 方法与onPause并没有严格的先后关系,有可能在onPause之前,也有可能在其后面调用,但会在onStop()方法之前调用

7.异常退出后又重新启动该Activity --> onCreate() --> onStart() --> onRestoreInstanceState() --> onResume()

1.3 Android中的进程优先级

Android系统中,主要有这样五个进程优先级(按优先级高到低排列):

1. 前台进程:一般情况下处于与用户进行交互的Activity或者与前台Activity绑定的Service

2. 可见进程:如果一个Activity处于可见但是不是处于前台,就是用户不能点击的情况下就是可见进程

3. 服务进程:就是在后台开启了一个Service服务,这就是服务进程

4. 后台进程:假设我们当前的Activity是前台进程,然后我们按下Home键,前台进程就变成了后台进程

5. 空进程:五个进程里面,优先级是最低的,如果我们的进程不属于上面四个进程的进程,那就是空进程,空进程系统可以随时杀死

2. Android系统中的任务栈

我们的Android系统为了记录用户开启了哪些Activity,记录这些Activity开启的先后顺序,所以引入了任务栈(Task Stack)的概念,可以增强用户的体验。

任务栈

任务栈与下面讲的启动模式其实密切相关,关于任务栈相关的知识点如下:

1. 任务栈,Task Stack,别名Back Stack(后退栈),记录存放用户开启的Activity

2. 我们的App开启的时候,Android系统就给这个App分配了一个任务栈,当所有的Activity都退出的时候,任务栈就清空了

3. 我们的App的任务栈并不是唯一的,可能不止一个任务栈,一个Activity也可以独享一个任务栈

4. 清空了任务栈,我们的App的进程并不会销毁,还是会保留

5. 任务栈可以移动到后台,并且保留了每一个Activity的状态信息和成员变量

6. 只有在栈顶的Activity才能与用户进行交互

3. Activity的启动模式

Android系统中Activity的启动模式主要有四种:

1. standard

2. singleTop

3. singleTask

4. singleInstance

3.1 standard

这个模式,我们平时开发中使用得比较多,属于默认模式,可以指定,也可以不用配置。

在这个模式下,都会默认创建一个新的实例。也就意味着在一个任务栈中,可能存在多个相同的实例,也可以多个相同的Activity进行叠加

可以在清单文件里面进行指定该启动模式:

当前栈内顺序是A B C D,这个时候,在栈顶的D Activity启动A Activity,由于是A是Standard模式,那么就会在当前任务栈重新创建一个新的实例A,那么任务栈就变成了A B C D A。

standard

3.2 singleTop

我们一般都称此模式为栈顶复用,表明与Standard不同的是,并不是每次都无脑的进行重新创建一个实例,需要进行判断。当被启动的Activity已经处于栈顶,就不会进行创建新的实例,而是调用栈顶Activity的onNewIntent方法,当然,如果栈顶的Activity并不是被启动的但是同一个任务栈的,依然会重新创建一个实例

singleTop_1
singleTop_2

3.3 singleTask

这个模式,我们中文称作栈内复用,与栈顶复用差不太多,只是,判断的是当前Activity处于的整个任务栈。如果在整个任务栈中,已经有当前Activity的实例,那就是调用该Activity的onNewIntent方法,而不会重新创建实例。

这个模式值得注意的是,当需要复用当前任务栈中的某一个Activity实例的时候,会直接把该实例上面的Activity进行出栈进行销毁,从而将该Activity实例放于栈顶。

singleTask_1
singleTask_2

3.3 singleInstance

这个模式比较特殊,当使用该模式的时候,会创建一个新的任务栈,而且,这个任务栈有且仅有这一个Activity实例。

如果再一次调用这个Activity实例,就会发生发用,调用它的onNewIntent方法,反正不会再重新创建一个了。

值得注意的是,按返回退出的时候,是一个任务栈都出栈完了之后,再操作另一个任务栈。

singleInstance

4. scheme跳转协议

Android中的scheme是一种页面内跳转协议,是一种非常好的实现机制,通过定义自己的scheme协议,可以非常方便跳转到我们App中的各个页面;

通过scheme协议,服务器也可以定制化告诉App跳转到那个页面,可以通过通知栏消息定制化跳转页面,也可以通过H5页面跳转到页面等。

下面简单讲一下scheme的使用。

第一步,将满足scheme协议的Activity在清单文件里面进行注册:

<activity
    android:name=".SecondActivity"
    android:launchMode="singleTask">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />

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

        <data android:scheme="senduo" />
    </intent-filter>
</activity>

第二步,在需要调用的地方,定义URI格式(也就是我们自定义的协议),其中格式URI格式如下:

[scheme:][//domain][path][?query][#fragment]

代码举例说明如下:

tvDomain = (TextView) findViewById(R.id.tvDomain);
tvDomainWithParams = (TextView) findViewById(R.id.tvDomainWithParams);

tvDomain.setText(Html.fromHtml("<a href='senduo://domain/path?params'>无参示例</a>"));
tvDomain.setMovementMethod(LinkMovementMethod.getInstance());


tvDomainWithParams.setText(Html.fromHtml("<a href='senduo://second_activity?id=123456&name=senduo'>有参示例</a>"));
tvDomainWithParams.setMovementMethod(LinkMovementMethod.getInstance());

第三步,在onCreate方法或者onNewIntent方法中进行URI的解析,根据实际的业务逻辑进行处理

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    Uri uri = intent.getData();
    if (uri != null) {
        dispatchUri(uri);
    } else {
        Log.e(TAG, "Uri is null");
    }
}



//URI的解析
private void dispatchUri(Uri uri) {
    try {
        final String domain = uri.getAuthority();
        if (TextUtils.equals(SECOND_DOMAIN, domain)) {
            final int id = Integer.valueOf(uri.getQueryParameter("id"));
            final String name = uri.getQueryParameter("name");
            Toast.makeText(this, id + "  " + name, Toast.LENGTH_SHORT).show();
        }
    } catch (Exception e) {
        Log.e(TAG, "Uri Parse Error");
    }
}

关于scheme的调用,可以根据具体的实际业务场景进行自行设计,像通知栏的跳转,网页的跳转啥的,具体的内容可以查看相关博客进行更深一步的学习。


干货总结

以上,是这一次关于Activity知识的一个整理,其实,Activity的知识点可以讲的很简单,也可以深入Framework层进行分析,那样理解起来会比较吃力,但收获也将不少。奈何最近各种需要干苦力,这些分析就留到Android源码分析的时候再深入了解吧。

我们作为一个Android开发人员来讲,Activity是四大组件中离我们最近,接触得最多的一个,需要对它的一些原理,机制有一定的了解,希望通过这一篇文章,能够提供一个清晰的思路来回顾Activity,能够回答以下问题:

1. 什么是Activity

2. activity有哪些状态

3. 手绘Activity的生命周期图

4. Android系统中的进程优先级

5. Activity的四种启动模式简述

6. scheme跳转协议是什么
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,391评论 25 707
  • Task和BackStack的基本概念 Task的理解 Task是多个Activity的集合,用户进行操作时将与这...
    Reathin阅读 2,051评论 1 4
  • 一、概述 Activity 作为与用户交互的一个窗口,是使用非常频繁的一个基本组件。Android系统是通过Act...
    三也视界阅读 2,224评论 3 11
  • 我有话要说和我无话可说,每次话到嘴边说出来的确是不一样的感觉,是我不够自信了,还是更多的生怕暴露自己的缺点了,想的...
    南韵阿宝阅读 193评论 0 0
  • 昨日晚间,天空不知为何戴上一张极狰狞的面具,苍白。俶尔天色渐暗,又如泥土一般的混浊。人们张望妄自猜测气象,旋即暴雨...
    馔疬阅读 209评论 0 2