活動(dòng):Activity
從今天開始將會(huì)學(xué)習(xí)一個(gè)非常重要的概念——Android 四大組件,在 Android 中幾乎所有的功能都和四大組件密不可分,而 Activity 是其中出場率最高的組件,也是對(duì)用戶感知度最高的組件,當(dāng)然也可以說是四大組件中最重要的一個(gè)組件。我們前面的絕大部分邏輯代碼也都是在 Activity 中實(shí)現(xiàn)的,接下來詳細(xì)介紹一下第一大組件——Activity。
1. Activity 的基本定義
An activity is a single, focused thing that the user can do. Almost all activities interact with the user, so the Activity class takes care of creating a window for you in which you can place your UI with setContentView. While activities are often presented to the user as full-screen windows, they can also be used in other ways: as floating windows (via a theme with android.R.attr.windowIsFloating set) or embedded inside of another activity (using ActivityGroup).
以上是摘自官方文檔中對(duì) Activity 的部分解釋,用我不太流利的英語給大家翻譯一下, 英語不太好的同學(xué)可以將就著看看:
Activity 提供給用戶一個(gè)單一的、獨(dú)立操作的用戶界面,幾乎所有的 Activity 都可以和用戶進(jìn)行交互,所以 Activity 類的主要功能是創(chuàng)建一個(gè)窗口來承載我們通過
setContentView
設(shè)置的 UI 界面,從而展示給用戶。大部分場景下,Activity 會(huì)以全屏的形式占滿手機(jī)屏幕,但是也支持浮窗或者內(nèi)嵌的形式。
其實(shí)簡而言之,Activity 就是一個(gè)用戶界面,類似 Windows 系統(tǒng)里的窗口的概念,而第一個(gè)啟動(dòng)的 Activity,我們稱之為主 Activity。
2. Activity 的生命周期
如果你學(xué)習(xí)過 C/C++ 或者 Java 開發(fā)應(yīng)該很熟悉main()
函數(shù),沒錯(cuò),一切代碼都是從main()
函數(shù)開始的。在 Android 中也有類似的概念,每個(gè) Android 應(yīng)用程序都有一個(gè)主 Activity(啟動(dòng) Activity),而其中的onCreate()
方法就是所有代碼的起點(diǎn)。
2.1 生命周期的各個(gè)流程
Android 系統(tǒng)為每個(gè) Activity 設(shè)計(jì)了完備的生命周期,在各個(gè)不同的生命周期我們都可以做不同的工作,Activity 生命周期流程圖如下:
上圖中的每一個(gè)矩形框代表一個(gè)生命周期方法,Activity 一共有 7 個(gè)生命周期。當(dāng)然我們?cè)趯?shí)際開發(fā)中并不需要全部都實(shí)現(xiàn),只需根據(jù)具體需求在合適的時(shí)機(jī)去實(shí)現(xiàn)相應(yīng)的生命周期方法即可,這就要求開發(fā)者對(duì)每個(gè)生命周期回調(diào)的時(shí)機(jī)和意義比較了解,下面我們來解讀一下每個(gè)生命周期的調(diào)用時(shí)機(jī):
- onCreate():
在 Activity 被創(chuàng)建的時(shí)候回調(diào),也是 Activity 的第一個(gè)生命周期方法,在整個(gè)生命周期中只會(huì)執(zhí)行一次。通常會(huì)在這里執(zhí)行頁面的初始化邏輯,大部分的 Activity 相關(guān)的代碼都會(huì)在這里執(zhí)行 - onStart():
當(dāng) Activity 對(duì)用戶可見的時(shí)候回調(diào),注意此時(shí)可能還不能交互,可以用來統(tǒng)計(jì)頁面曝光 - onResume():
當(dāng) Activity 獲取系統(tǒng)焦點(diǎn)的時(shí)候回調(diào),此時(shí)已經(jīng)可以和用戶交互 - onPause():
當(dāng) Activity 暫停的時(shí)候回調(diào),此時(shí)用戶已經(jīng)不能交互,并且暫停執(zhí)行正常業(yè)務(wù)代碼。通常這時(shí)候會(huì)回調(diào)下一個(gè)或者上一個(gè) Activity 的onResume()
- onStop():
當(dāng) Activity 不可見的時(shí)候回調(diào),此時(shí)結(jié)束曝光 - onRestart():
在“Stop”之后,再次回到 Activity 時(shí)觸發(fā)此方法 - onDestroy():
此生命周期觸發(fā)標(biāo)志著 Activity 銷毀,是最后一個(gè)生命周期,和onCreate()
一樣,只會(huì)調(diào)用一次,接著系統(tǒng)就會(huì)回收掉這部分資源
這 7 個(gè)生命周期不是單純的線性運(yùn)動(dòng),從上圖可以看出除了第一個(gè)和最后一個(gè):onCreate()
、onDestroy()
之外,其他的都是可以反復(fù)循環(huán)的。
2.2 生命周期常見問題及誤區(qū)
**另外要特別注意的,也是面試中非常容易被問到的一個(gè)經(jīng)典問題:**從 Activity A 啟動(dòng)到 Activity B,再從 B 退回到 A,所經(jīng)歷的生命周期方法依次是哪幾個(gè)?
大家可以先根據(jù)生命周期流轉(zhuǎn)圖及各生命周期的定義自行思考一下,分割線后給出答案。
我們來分析一下這個(gè)問題,首先是 Activity A 的啟動(dòng):
A onCreate -> A onStart() -> A onResume()
到這里 A 就啟動(dòng)完畢了,接下來啟動(dòng) Activity B,此時(shí)系統(tǒng)會(huì)將焦點(diǎn)移動(dòng)到 B 上,故 A 的 onPause() 會(huì)被調(diào)用,接著創(chuàng)建 Activity B,那么流程是這樣的:
A onPause() -> B onCreate() -> B onStart() -> B onResume()
此時(shí) B 已經(jīng)啟動(dòng)完畢,大家注意到 A 的onStop()
自始至終還未執(zhí)行,我們?cè)俅位貞浺幌?code>onStop()的定義:“當(dāng) Activity 不可見的時(shí)候回調(diào)”。所以此時(shí)要分兩種情況,如果 Activity B 是全屏的類型,那么在 B 啟動(dòng)之后系統(tǒng)會(huì)回調(diào) Activity A 的 onStop();但是前面提到過,Activity可以是浮窗類型,此時(shí) A 的onStop()
則不會(huì)被回調(diào),這是一個(gè)關(guān)鍵點(diǎn),大家一定要記?。?!
所以從 Activity A 跳轉(zhuǎn) Activity B 的生命周期觸發(fā)順序如下:
A onCreate -> A onStart() -> A onResume() -> 跳轉(zhuǎn) B -> A onPause() -> B onCreate() -> B onStart() -> B onResume() -> if (B is full screen) { A onStop() }
此時(shí)如果從 B 在返回到 A 的話,按照以上原理不難理解:
B onPause() -> A onRestart() -> A onStart() -> A onResume() -> B onStop() -> B onDestroy()
由于從 B 返回 A 需要銷毀 B,所以此時(shí)不論 A 是否是全屏類型都會(huì)在 A 恢復(fù)之后依次調(diào)用 B 的onStop()
和onDestroy()
。這個(gè)是面試必考題,大家務(wù)必掌握!
3. Activity 示例
關(guān)于 Activity 的使用其實(shí)從本教程的最開始就一直在用,我們通常都是將核心邏輯放在了onCreate()
之中,比如setContentView
設(shè)置布局樣式,findViewById()
獲取布局中的控件實(shí)例,綁定監(jiān)聽器等等,所以 Activity 的用法相信大家并不陌生,這里主要是希望大家對(duì)除了 onCreate()
方法之外的其他生命周期時(shí)機(jī)有所了解。我們將在 7 個(gè)生命周期中加入 Log 日志,觀察一下各個(gè)生命周期的回調(diào)時(shí)機(jī),編寫 Activity 代碼如下:
package com.emercy.myapplication;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends Activity {
String TAG = "Android Lifecycle";
// 第一個(gè)被調(diào)用的方法,當(dāng) Activity 被創(chuàng)建時(shí)調(diào)用
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "The onCreate() event");
}
// Activity 可見
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, "The onStart() event");
}
// Activity 獲取焦點(diǎn),可交互
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "The onResume() event");
}
// Activity 失焦
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, "The onPause() event");
}
// Activity 停止,不可見
@Override
protected void onStop() {
super.onStop();
Log.d(TAG, "The onStop() event");
}
// Activity 銷毀
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "The onDestroy() event");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(TAG, "The onRestart() event");
}
}
編譯運(yùn)行,系統(tǒng)自動(dòng)啟動(dòng) MainActivity,此時(shí)觀察 Logcat 輸出:
接著點(diǎn)擊“Home”退出 Activity,然后切換回來,觀察 Logcat 如下:
最后點(diǎn)擊 back 退出 App,再次觀察 Logcat:
通過 Logcat 可以觀察到生命周期的跳轉(zhuǎn)符合預(yù)期。
4. 小結(jié)
本節(jié)介紹了 Android 四大組件中的第一大組件,也是用的最多、責(zé)任最大的組件,其中最關(guān)鍵的是要掌握各個(gè)生命周期的調(diào)用時(shí)機(jī)及含義。
首先分析了 Activity 7 個(gè)生命周期的流轉(zhuǎn),以及各個(gè)生命周期的意義,接著通過一個(gè)示例配合具體的用戶行為通過 Logcat 的形式打印了生命周期的變化,理論結(jié)合實(shí)際相信你會(huì)對(duì) Activity 的生命周期有了更深的理解。中間還分享了一個(gè)關(guān)鍵點(diǎn),也是面試中經(jīng)常遇到的問題,希望大家牢牢掌握!