Activity笔记

一、说明

       笔记主要是《Android开发艺术探索》的阅读笔记和自己的理解,笔记中部分内容引自《Android开发艺术探索》。

       因此需要着重感谢任玉刚先生和他所著的《Android开发艺术探索》;然后感谢任玉刚先生授权我使用小部分《Android开发艺术探索》原文。

       推荐Android开发者购买正版《 Android开发艺术探索》,该书是初级Android开发者进阶的必备良品!

    由于本人水平有限,其中出现的错误或者不合理的地方望各位读者多多包含,并指出其中不合理和错误的地方,以便我来修改正。谢谢!

二、笔记时间

     2018年8月12日

三、简述

     本文主要记录《Android开发艺术探索》中第一章中的重要知识点,其中包含Activity的生命周期、启动模式、IntentFilter匹配规则。

    文中加入了一些个人理解,可能有一些说明不合理或者错误之处,望各位读者指出错误的地方,以便我来修改错误,避免误导读者。谢谢!

四、详情

1、Activity生命周期

1.1、Activity生命周期介绍

Activity笔记_第1张图片
图一 Activity 生命周期

       正常情况下,一个Activity会经历图一所示生命周期。以下对于几个生命周期进行详细说明:

1)onCreate:调用该方法时表示Activity正在被创建,是生命周期中的第一个方法。该方法在两种情况下调用,第一种情况是在初次创建Activity的时候调用;第二种情况是该Activity被Android后台自动销毁或回收后,再次启动Activity的时候调用。调用该方法的时候Activity并没有显示在前台。我们可以在该方法中做一些界面显示前的准备工作,比如调用setContentView加载界面资源、初始化Activity所需数据等。

2)onStart:调用该方法时表示Activity正在启动。该方法同样在两种情况下被调用,第一种情况是Activity被创建完之后调用,这种情况在调用该方法前会先调用onCreate方法;第二种情况是该Activity停止之后但在还没销毁,此时重新启动该Activity的情况下调用,这种情况在调用该方法前会先调用onRestart方法(onRestart详情见第七小点)。调用该方法时Activity已经创建完成,但是此时Activity还是处于后台,由于当前Activity不处于前台,因此此时还不能和用户交换。

3)onResume:调用该方法表示Activity已经可见,且处于前台,此时已经可以正常进行用户交互了。需要强调的是,第一在调用该方法之前Activity一直是处于后台,直到调用该方法Activity才处于前台,比如在调用onStart方法的时候Activity就还是处于后台;第二无论Activity的生命状态如何变化,在Activity正常可见且正常交互之前一定会调用该方法。

4)onPause:调用该方法时表示Activity正在暂停,正常情况下,在这之后会调用onStop方法来停止该Activity。操作够快且凑巧的情况下,可能出现调用该方法之后紧接着调用onResume方法的情况,比如此时快速回到当前Activity。因为新Activity必须在执行完该方法后才会执行新Activity的onResume方法,因此在此方法中只能做一些简单数据存储、动画停止等不太耗时的操作。

5)onStop:调用该方法时表示Activity即将停止。一个Activity需要彻底销毁,一定会先调用该方法,但是调用该方法后不一定就会销毁该Activity,比如在调用该方法时该Activity当中还有未执行完成的线程、在当前界面处于不可见状态(锁屏、熄屏、按home、打开新界面)等。在此方法当中可以做一些稍微重量级的回收工作,但是还是不能太耗时。

6)onDestroy:调用该方法时表示Activity即将被销毁,这是Activity的最后一个生命周期。在该方法中,我们可以做一些回收工作和资源释放等。

7)onRestart:调用该方法时表示Activity正在重新启动。正常情况下当Activity由不可见状态到可见状态都会调用先调用该方法,比如先按home键、打开新Activity,然后回到当前Activity等操作。

1.2、Activity生命周期说明

1)第一次启动Activity:生命周期如下:onCreate->onStart->onResume。

2)正常打开新Activity、按home键等:生命周期如下:onPause->onStop;注:打开新Activity,例如由A Activity跳转到B Activity的生命周期如下:A Activity先调用onPause,然后B Activity调用onCreate->onStart->onResume,最后A Activity才会调用onStop方法。

3)正常销毁Activity、按返回键:生命周期如下:onPause->onStop->onDestroy。

4)熄灭屏幕、锁定屏幕:生命周期如下:onPause->onStop。

5)正常重启Activity、点亮屏幕、解锁屏幕:生命周期如下:onRestart->onStart->onResume。

6)当Activity被系统回收后再次打开:这种情况生命周期和第一次启动Activity是一样的,但是仅限于生命周期,生命周期如下:onCreate->onStart->onResume。

7)当设置为透明主题时,打开新界面不会调用onStop方法,但是会调用onPause方法。比如A Activity设置为了透明主题,现在由A Activity跳转到B Activity,然后再按返回键回到A Activity,由A Activity跳转到B Activity生命周期如下:A Activity先调用onPause,然后B Activity调用onCreate->onStart->onResume;在B Activity按返回键生命周期如下:先B Activity调用onPause方法,然后A Activity调用onResume方法,然后B Activity调用onStop->onDestroy。如果A、B两个Activity都是透明主题,由A Activity跳转到B Activity,然后再按返回键回到A Activity的生命周期和以上只有A Activity为透明主题的生命周期一样。

8)对于整个生命周期来说,onCreate和onDestroy是成对出现的;onStart和onStop也是成对出现;onResume和onPause同样也是成对出现;其中onCreate和onDestroy标志Activity的创建和销毁,并且只会调用一次;但是onStart和onStop、onResume和onPause会随着用户操作和屏幕的点亮与熄灭被多次调用。

9)在Android中需要启动一个新的Activity,一定是先把栈顶的Activity先onPause,然后才启动新的Activity。

10)当资源相关的系统配置改变的时候(异常情况),Activity会先被销毁,然后再重新创建。也就是生命周期是:onPause->onStop->onDestroy->onCreate->onStart->onResume。但是在Activity停止之前(也就是调用onStop之前),系统会先调用onSaveInstanceState(和onPause没有必然关系,可能在onPause之前调用,也可能在onPause之后调用;该方法只在Activity异常终止的情况下才会被调用,正常销毁Activity是不会调用该方法的;系统根据不同View会保存视图结构和部分数据。)来保存当前Activity的一些状态,比如Bundle对象等;在重新创建并启动Activity之后(也就是onStart方法之后),会调用onRestoreInstanceState方法,并且在onSaveInstanceState中保存的Bundle对象会传递给新建Activity的onCreate方法和onRestoreInstanceState方法(系统根据不同的View,默认会恢复视图结构和部分数据)。因此我们也可以在onCreate和onRestoreInstanceState方法中判断Activity是否被重新创建,如果重新创建可以在这两个方法中恢复之前保存的数据。

11)内存不足会导致低优先级的Activity被杀死(异常情况)。Android中Activity优先级排序,正在和用户交换的前台Activity > 可见的后台Activity(弹出对话框会导致Activity可见但处于后台) > 后台Activity。同样这种异常情况导致被杀死的Activity也会调用onSaveInstanceState来保存部分数据,重新创建Activity时在onRestoreInstanceState中来恢复部分数据。注:一些不能没有四大组件而独立运行的后台很容易被系统杀死。最好将一些重要的后台工作放Service中执行,用以保证一定的优先级,防止被系统轻易杀死。

12)我们可以通过配置configChanges来防止在某些情况下重新创建Activity的情况,比如设置“ android:configChanges="orientation" ”来防止屏幕旋转的时候重新创建Activity。当然可以通过“|”来防止多种情况下重新创建Activity,比如设置“ android:configChanges="orientation|locale" ”来防止在屏幕旋转、位置改变(系统语言切换)的情况下重新创建Activity。详情见图二,其中常用的为locale、orientation、keyboardHidden这项,图中当目标设备Android API大于13时,屏幕旋转时会导致screenSize发生改变,因此当API大于13时,为了防止屏幕旋转导致重新创建Activity需要把screenSize也加上。 


图二 configChanges 的项目和含义

2、Activity的启动模式

2.1、Activity的LaunchMode

       Activity在Android中的管理是通过栈来管理的,栈的默认模式是LIFO(后入先出)。如果没有其他模式来辅助管理Activity,启动的新Activity都会添加到栈顶,按返回键就只退出栈顶的Activity,对于Android来说,单一的栈管理无法满足我们的需求,因此分了四个模式来对
栈进行不同的管理。四种模式的详情如下:

1)standard:标准模式,也是Android的默认模式。这种模式就是标准的栈管理模式,每次启动新Activity都会被添加到栈顶(不管栈中是否已经存在该Activity,都会被添加到栈顶。该模式下所有新打开的Activity都会调用Activity新创建的正常生命周期),按返回按键则退出栈顶的Activity。比如:先打开 A Activity,再打开 B Activity,然后再打开一个 A Activity,然后再打开 A Activity,此时按返回键后,再按返回键,再打开 C Activity。这种情况栈的变化是:A -> AB -> ABA -> ABAA -> ABA(按返回键后) -> AB(按返回键后)  -> ABC。

注:如果是 Context来启动新Activity,需加上 FLAG_ACTIVITY_NEW_TASK 这个标志位,这个标志的意义是指定Activity的启动模式为singleTask(在新建的栈中打开该Activity),不然会报错误并崩溃。导致崩溃的原因是standard模式默认会把新启动的Activity放入启动他所属Activity的栈中。例一:在 A Activity中启动B Activity,那么B Activity会放A Activity所在的栈中,栈情况是 AB;例二:通过监听开机广播来启动B Activity,这种情况需要创建一个新的栈,并把B Activity 放入新创建的栈中。

2)singleTop:栈顶复用模式。这种模式是如果该Activity已经处于栈顶,再打开该Activity,那么该Activity不会被重新创建放到栈顶(不调用任何生命周期,因为没有任何改变),但是如果该Activity已经在栈中但是不处于栈顶(新打开的Activity都会走Activity创建的正常生命周期)。例一:打开A Activity,然后打开 B Activity,最后再打开 B Activity,现在栈情况是 AB;例二:打开A Activity,然后打开 B Activity,最后再打开 A Activity,现在栈情况是 ABA。

3)singleTask:栈内复用模式。该模式是如果该Activity已经存在于栈中,就不会重新创建该Activity,但是会调用onNewIntent方法,并把该Activity重新放到栈顶(由于栈是LIFO,因此该Activity回到栈顶的方式是栈顶依次出栈,直到该Activity位于栈顶)。比如:先打开A Activity,然后打开 B Activity,然后打开C Activity,最后再打开A Activity,那么栈的变化情况是:A -> AB -> ABC ->A(再次打开A Activity后)。

4)singleInstance:单实例模式。用该模式标志的Activity都独立存在于一个栈中。比如:A 、B Activity 是standard模式,C、D Activity是singleInstance模式;此时先打开A Activity,然后打开B Activity,然后打开C Activity,最后打开D Activity,此时栈的情况是:AB(栈一)、C(栈二)、D(栈三)。

2.2、Activity的Flags

下面介绍几种常用的Flags:

1)FLAG_ACTIVITY_NEW_TASK:该标志的是把Activity设定为singleTask启动模式。

2)FLAG_ACTIVITY_SINGLE_TOP:该标志的是把Activity设定为singleTop启动模式。

3)FLAG_ACTIVITY_CLEAR_TOP:该标志位表示当该Activity启动时,在同一个栈中所有位于该Activity之上的所有Activity都要出栈。通过该标志位启动的Activity分两种情况。第一种情况是该Activity的启动模式为singleTask模式,这种情况通过这个标志位再次启动该Activity,和singleTask模式再次启动该Activity一样,即退出该Activity之后的所有Activity,使该Activity位于栈顶并调用onNewIntent方法;第二种情况是该Activity的启动模式为standard模式,在这种情况下会连该Activity一起出栈,并重新创建一个新Activity入栈,这样生命周期和新建Activity的生命周期完全一样。

4)FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:该标志位表示该Activity不会出现在历史Activity的列表中。在xml中的属性是 android:excludeFromRecents="true"。

3、IntentFilter的匹配规则

     IntentFilter字面意思就是Intent过滤器,作用就是可以给Intent添加一些过滤规则,可以用于Activity的隐式启动。IntentFilter的内容包含action、category、data三部分,下面将一一介绍:

1)action的匹配规则:action是一个字符串,系统默认定义了一些,同样我们也可以自定义。action的匹配规则是Intent中的action必须和过滤规则中的其中一个action匹配(action的字符串完全一样,大小写也一样)。

2)category的匹配规则:category是一个字符串,系统默认定义了一些,同样我们也可以自定义。category的匹配规则是如果Intent中包含category,那么每一个category都必须和过滤规则中的其中一个相同。也就是说不论Intent有几个category,每个都要和过滤规则中的其中一个相同;当然如果没有category也能够匹配成功。注:在使用startActivity和startActivityForResult时,系统会默认加上"android.intent.category.DEFAULT"这个category,如果需要隐式调用,就必须在intent-filter中添加"android.intent.category.DEFAULT"这个category。

3)data的匹配规则:data的匹配规则和action类似,如果过滤规则中定义了data,那么Intent中必须也要定义可匹配的data,也就是Intent中必须包含data,且data数据能够完全匹配过滤规则中一个data。data分为两部分,mimeType和URI,其中mimeType是指媒体类型,如image/jpeg等,可以表示图片、文本、视频等;URI的结构:://://|,其中scheme表示URI的模式(http、file、content等),host表示URI的主机名,port表示URI的端口号,path表示完整的路径信息,pathPrefix也表示完整的路径信息(它可以包含通配符“*”,和正则表达式一样,“*”表示0-n个任意字符,“\\*”表示字符“*”,“\\\\”表示字符“\”),pathPattern表示路径的前缀信息。例:http://www.baidu.com:80/serach/info

注:如果要为Intent指定完整的data,必须要调用setDataAndType方法,不能先调用setData,再调用setType,因为这两个方法会彼此清除对方的值。

你可能感兴趣的:(Activity笔记)