Android 开发艺术探索读书笔记(一)

发布日期:2019-10-01

之前断断续续地学了一些 Android 开发基础,也写过几个简单的 app,但都是特别简单的那种,还有很多知识学完了没有用过,现在已经忘得差不多了。最近找到一本书叫 Android 开发艺术探索(作者叫任玉刚,据说是百度的大牛),2015 年出版的,看完第一章后感觉不错,很适合我这种有点基础的人看,于是决定写个读书笔记,记录自己从书中学习到的知识。

第一章

本章主要介绍了 Activity 相关的一些内容。

1.1 Activity 的生命周期

正常情况下 Activity 的生命周期如下:

// 1.表示 Activity 正在被创建@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);}// 2.表示 Activity 正在重新启动,当用户切换已经打开过的 Activity 时才会调用这个方法@Overrideprotected void onRestart() { super.onRestart();}// 3.表示 Activity 正在被启动@Overrideprotected void onStart() { super.onStart();}// 4.表示 Activity 已经可见@Overrideprotected void onResume() { super.onResume();}// 5.表示 Activity 正在暂停@Overrideprotected void onPause() { super.onPause();}// 6.表示 Activity 正在停止@Overrideprotected void onStop() { super.onStop();}// 7.表示 Activity 正在销毁@Overrideprotected void onDestroy() { super.onDestroy();}

在某些特殊情况下,Activity 的生命周期可能会发生变化,比如屏幕旋转、内存不足等等,此时 Activity 会被销毁并重新创建,这种情况下会多出两个方法:

// 在 onStop() 方法之前被调用// 用来保存相关数据@Overrideprotected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt("test", 123);}// 在 onStart() 方法后被调用// 用来恢复数据,也可以在 onCreate() 方法中恢复,但要判断 savedInstanceState 是否为 null,这里就不需要@Overrideprotected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); int value = savedInstanceState.getInt("test");}

 如果我们不想系统重新创建 Activity,可以在 AndroidManifest.xml 中为 Activity 配置 configChanges 属性,此属性可以指定多个值(哎呀,无法插入 xml 代码好蛋疼):

<activity android:name=".MainActivity" android:configChanges="orientation|locale|keyboard|keyboardHidden|screenSize"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter></activity>

常用的就这么几个,分别表示屏幕旋转、本地设置改变(如切换语言)、键盘改变(如外接键盘)、键盘可访问性改变(显示或隐藏键盘)、屏幕尺寸改变(通常是因为屏幕旋转)。

同时,如果指定了 configChanges 属性,当相关事件发生时,系统会调用 Activity 的如下生命周期方法:

// 表示配置改变,可以根据需要做一些特殊处理@Overridepublic void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); Log.d("TEST", "onConfigurationChanged: " + newConfig.orientation);}

 1.2 Activity 的启动模式

Android 系统有一个 Activity 任务栈的概念,栈是一种后进先出的数据结构,那么任务栈中存放的 Activity 自然也是后进先出的。任务栈是 Android 系统管理 Activity 的方式,至于它的工作原理,这里暂时不做说明,我们主要关注的是 Activity 的启动模式。

Activity 有四种启动模式,分别为:

standard:标准模式,也是系统默认的启动模式,每次启动 Activity 都会创建一个实例,并执行相应的生命周期方法,每个 Activity 也都会被放入任务栈中;

singleTop:栈顶复用模式,如果要启动的 Activity 已经位于栈顶,则复用它,此时就不会调用 onCreate() 和 onStart() 方法,取而代之的是调用 onNewIntent() 方法;

singleTask:栈内复用模式,如果要启动的 Activity 在栈中存在,则复用它,生命周期方法同上,但此时系统会清空在任务栈中此 Activity 上面的所有其他 Activity(重点,拿小本本记下来);

singleInstance:单一实例模式,此种情况下,系统会为 Activity 创建一个单独的、独享的任务栈,如果要启动的 Activity 已经存在,则复用它,生命周期方法同上。

说了这么多,那么如何为 Activity 指定启动模式呢?

作者说了,有两种方法,第一种方法是在 AndroidManifest.xml 中配置:

<activity android:name=".MainActivity" android:configChanges="orientation|locale|keyboard|keyboardHidden|screenSize" android:launchMode="singleTop"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter></activity>

第二种方法是通过代码指定:

private void testLaunchMode(){ Intent intent = new Intent(this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); startActivity(intent);}

 两种方法都可以指定 Activity 的启动模式,不过第一种方法不能设置 FLAG_ACTIVITY_CLEAR_TOP 标识,第二种方法不能指定 singleInstance 模式,但第二种方式的优先级要高于第一种,实际使用中应该根据需要灵活选择。

上面的代码中提到了 FLAG_ACTIVITY_SINGLE_TOP 和 FLAG_ACTIVITY_CLEAR_TOP,这是 Android 系统预定义的两个常量,是 Activity 的 Flags。系统预定义了很多这样的标识位常量,下面介绍几个常用的标识位:

FLAG_ACTIVITY_NEW_TASK:为 Activity 指定 singleTask 模式,效果和在 AndroidManifest.xml 中指定该模式相同;

FLAG_ACTIVITY_SINGLE_TOP:为 Activity 指定 singleTop 模式,除此之外同上;

FLAG_ACTIVITY_CLEAR_TOP:启动具有此标识位的 Activity,系统会清除与此 Activity 在同一栈中,且在其上面的所有 Activity,通常与 FLAG_ACTIVITY_NEW_TASK 配合使用;

FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:表示要启动的 Activity 不在系统的最近任务列表中显示,效果同在 AndroidManifest.xml 中指定 android:excludeFromRecents="true"。

1.3 节主要讲的是  IntentFilter 的匹配规则,内容也不少,下次再写吧。