Activity基礎

Activty

作為一個Android開發(fā)者跪解,每天都在寫Activity炉旷,但是优烧,但是真的讓我講講我這個每天的玩伴套腹,好像我并不能系統(tǒng)的講出來很多很多。所以端考,我要做一下整理图仓,把常用的罐盔,或者我認為我需要知道的,都整理一下救崔。

本篇文章將按主要講解以下內容

  1. 簡介:Activity是什么惶看?
  2. 如何創(chuàng)建一個Activity?
  3. 如何啟動和關閉一個Activity帚豪?
  4. 管理Activity的生命周期碳竟?
  5. 如何保存Activity狀態(tài)草丧?

1. 簡介:Activity是什么狸臣?

Activity 是一個應用組件,用戶可與其提供的屏幕進行交互昌执,以執(zhí)行撥打電話烛亦、拍攝照片、發(fā)送電子郵件或查看地圖等操作懂拾。 每個 Activity 都會獲得一個用于繪制其用戶界面的窗口煤禽。窗口通常會充滿屏幕,但也可小于屏幕并浮動在其他窗口之上岖赋。
一個應用通常由多個彼此松散聯系的 Activity 組成檬果。 一般會指定應用中的某個 Activity 為“主”Activity,即首次啟動應用時呈現給用戶的那個 Activity。 而且每個 Activity 均可啟動另一個 Activity选脊,以便執(zhí)行不同的操作杭抠。 每次新 Activity 啟動時,前一 Activity 便會停止恳啥,但系統(tǒng)會在堆棧(“返回椘樱”)中保留該 Activity。 當新 Activity 啟動時钝的,系統(tǒng)會將其推送到返回棧上翁垂,并取得用戶焦點。 返回棧遵循基本的“后進先出”堆棧機制硝桩,因此沿猜,當用戶完成當前 Activity 并按“返回”按鈕時,系統(tǒng)會從堆棧中將其彈出(并銷毀)亿柑,然后恢復前一 Activity邢疙。 (任務和返回棧文檔中對返回棧有更詳細的闡述。)
當一個 Activity 因某個新 Activity 啟動而停止時望薄,系統(tǒng)會通過該 Activity 的生命周期回調方法通知其這一狀態(tài)變化疟游。Activity 因狀態(tài)變化—系統(tǒng)是創(chuàng)建 Activity、停止 Activity痕支、恢復 Activity 還是銷毀 Activity— 而收到的回調方法可能有若干種颁虐,每一種回調都會為您提供執(zhí)行與該狀態(tài)變化相應的特定操作的機會。 例如卧须,停止時另绩,您的 Activity 應釋放任何大型對象,例如網絡或數據庫連接花嘶。 當 Activity 恢復時笋籽,您可以重新獲取所需資源,并恢復執(zhí)行中斷的操作椭员。 這些狀態(tài)轉變都是 Activity 生命周期的一部分车海。
本文的其余部分闡述有關如何創(chuàng)建和使用 Activity 的基礎知識(包括對 Activity 生命周期工作方式的全面闡述),以便您正確管理各種 Activity 狀態(tài)之間的轉變隘击。

2. 如何創(chuàng)建一個Activity侍芝?

要創(chuàng)建 Activity,您必須創(chuàng)建 Activity 的子類埋同。您需要在子類中實現 Activity 在其生命周期的各種狀態(tài)之間轉變時(例如創(chuàng)建 Activity州叠、停止 Activity、恢復 Activity 或銷毀 Activity 時)系統(tǒng)調用的回調方法凶赁。 兩個最重要的回調方法是:
onCreate():
您必須實現此方法咧栗。系統(tǒng)會在創(chuàng)建您的 Activity 時調用此方法逆甜。您應該在實現內初始化 Activity 的必需組件。 最重要的是致板,您必須在此方法內調用 setContentView()忆绰,以定義 Activity 用戶界面的布局。
onPause():
系統(tǒng)將此方法作為用戶離開 Activity 的第一個信號(但并不總是意味著 Activity 會被銷毀)進行調用可岂。 您通常應該在此方法內確認在當前用戶會話結束后仍然有效的任何更改(因為用戶可能不會返回)
在安卓中错敢,我們大多數情況下都使用xml布局來實現我們需要的用戶界面,使用XML建造用戶界面的一個好處就是我們將布局和Activity的邏輯代碼分開缕粹,并以此提高代碼可讀性以及代碼的可維護性稚茅。當然,你也可以在Activity中創(chuàng)建布局文件平斩,然后將布局文件的根布局通過setcontentview設置給Activity亚享。
要使用我們創(chuàng)建的Activity 我們還必須在清單文件中申明。

3. 如何啟動和關閉一個Activity绘面?

通常情況下欺税,啟動一個Activity的方式有兩種,即顯式啟動和隱式啟動揭璃。
Android中晚凿,四大組件的啟動都是通過intent來啟動的。
顯式啟動:在intent中顯式指定Activity的名字瘦馍,如startActivity(new Intent(mContext,MainActivity.class))
隱式啟動: 在Intent中指定Activity的Action歼秽,指定了Action后由系統(tǒng)進行篩選,如果只有一個符合的就直接啟動情组,有多個就全部展示出來燥筷,給用戶選擇。這種方式也正是intent強大的原因院崇,啟動一個外部Activity肆氓,比如選擇照片,打電話底瓣,發(fā)短信谢揪,發(fā)郵件等等,我們不必記住每一個Activity的名字濒持,我們只要知道他們所屬的Action键耕,然后交給系統(tǒng)去識別寺滚。即便有好幾個郵件客戶端柑营,也一樣不影響,交給用戶選擇他想使用的郵件客戶端就可以了村视。如startActivity(new Intent("ActionName"))
關閉Activity: 直接調用Activity.finish()方法官套。

4. 管理Activity的生命周期?

Activity生命周期
先看一張圖:

生命周期

名為“是否能事后終止?”的列表示系統(tǒng)是否能在不執(zhí)行另一行 Activity 代碼的情況下奶赔,在方法返回后隨時終止承載 Activity 的進程惋嚎。 有三個方法帶有“是”標記:(onPause()、onStop() 和 onDestroy())站刑。由于 onPause() 是這三個方法中的第一個另伍,因此 Activity 創(chuàng)建后,onPause() 必定成為最后調用的方法绞旅,然后才能終止進程 — 如果系統(tǒng)在緊急情況下必須恢復內存摆尝,則可能不會調用 onStop() 和 onDestroy()。因此因悲,您應該使用 onPause() 向存儲設備寫入至關重要的持久性數據(例如用戶編輯)堕汞。不過,您應該對 onPause() 調用期間必須保留的信息有所選擇晃琳,因為該方法中的任何阻止過程都會妨礙向下一個 Activity 的轉變并拖慢用戶體驗讯检。

在是否能在事后終止?列中標記為“否”的方法可從系統(tǒng)調用它們的一刻起防止承載 Activity 的進程被終止卫旱。 因此人灼,在從 onPause() 返回的時間到 onResume() 被調用的時間,系統(tǒng)可以終止 Activity顾翼。在 onPause() 被再次調用并返回前挡毅,將無法再次終止 Activity。

注:根據圖 1 中的定義屬于技術上無法“終止”的 Activity 仍可能被系統(tǒng)終止 — 但這種情況只有在無任何其他資源的極端情況下才會發(fā)生暴构。進程和線程處理文檔對可能會終止 Activity 的情況做了更詳盡的闡述跪呈。

5. 如何保存Activity狀態(tài)?

管理 Activity 生命周期的引言部分簡要提及取逾,當 Activity 暫秃穆蹋或停止時,Activity 的狀態(tài)會得到保留砾隅。 確實如此误阻,因為當 Activity 暫停或停止時晴埂,Activity 對象仍保留在內存中 — 有關其成員和當前狀態(tài)的所有信息仍處于活動狀態(tài)究反。 因此,用戶在 Activity 內所做的任何更改都會得到保留儒洛,這樣一來精耐,當 Activity 返回前臺(當它“繼續(xù)”)時,這些更改仍然存在琅锻。

不過卦停,當系統(tǒng)為了恢復內存而銷毀某項 Activity 時向胡,Activity 對象也會被銷毀,因此系統(tǒng)在繼續(xù) Activity 時根本無法讓其狀態(tài)保持完好惊完,而是必須在用戶返回 Activity 時重建 Activity 對象僵芹。但用戶并不知道系統(tǒng)銷毀 Activity 后又對其進行了重建,因此他們很可能認為 Activity 狀態(tài)毫無變化小槐。 在這種情況下拇派,您可以實現另一個回調方法對有關 Activity 狀態(tài)的信息進行保存,以確保有關 Activity 狀態(tài)的重要信息得到保留:onSaveInstanceState()凿跳。

系統(tǒng)會先調用 onSaveInstanceState()攀痊,然后再使 Activity 變得易于銷毀。系統(tǒng)會向該方法傳遞一個 Bundle拄显,您可以在其中使用 putString() 和 putInt() 等方法以名稱-值對形式保存有關 Activity 狀態(tài)的信息苟径。然后,如果系統(tǒng)終止您的應用進程躬审,并且用戶返回您的 Activity棘街,則系統(tǒng)會重建該 Activity,并將 Bundle 同時傳遞給 onCreate() 和 onRestoreInstanceState()承边。您可以使用上述任一方法從 Bundle 提取您保存的狀態(tài)并恢復該 Activity 狀態(tài)遭殉。如果沒有狀態(tài)信息需要恢復,則傳遞給您的 Bundle 是空值(如果是首次創(chuàng)建該 Activity博助,就會出現這種情況)险污。

注:無法保證系統(tǒng)會在銷毀您的 Activity 前調用 onSaveInstanceState(),因為存在不需要保存狀態(tài)的情況(例如用戶使用“返回”按鈕離開您的 Activity 時富岳,因為用戶的行為是在顯式關閉 Activity)蛔糯。 如果系統(tǒng)調用 onSaveInstanceState(),它會在調用 onStop() 之前窖式,并且可能會在調用 onPause() 之前進行調用蚁飒。

不過,即使您什么都不做萝喘,也不實現 onSaveInstanceState()淮逻,Activity 類的 onSaveInstanceState() 默認實現也會恢復部分 Activity 狀態(tài)。具體地講阁簸,默認實現會為布局中的每個 View 調用相應的 onSaveInstanceState() 方法爬早,讓每個視圖都能提供有關自身的應保存信息。Android 框架中幾乎每個小部件都會根據需要實現此方法启妹,以便在重建 Activity 時自動保存和恢復對 UI 所做的任何可見更改筛严。例如,EditText 小部件保存用戶輸入的任何文本翅溺,CheckBox 小部件保存復選框的選中或未選中狀態(tài)脑漫。您只需為想要保存其狀態(tài)的每個小部件提供一個唯一的 ID(通過 android:id 屬性)。如果小部件沒有 ID咙崎,則系統(tǒng)無法保存其狀態(tài)优幸。

您還可以通過將 android:saveEnabled 屬性設置為 "false" 或通過調用 setSaveEnabled() 方法顯式阻止布局內的視圖保存其狀態(tài)。您通常不應將該屬性停用褪猛,但如果您想以不同方式恢復 Activity UI 的狀態(tài)网杆,就可能需要這樣做。
盡管 onSaveInstanceState() 的默認實現會保存有關您的Activity UI 的有用信息伊滋,您可能仍需替換它以保存更多信息碳却。例如,您可能需要保存在 Activity 生命周期內發(fā)生了變化的成員值(它們可能與 UI 中恢復的值有關聯笑旺,但默認情況下系統(tǒng)不會恢復儲存這些 UI 值的成員)昼浦。

由于 onSaveInstanceState() 的默認實現有助于保存 UI 的狀態(tài),因此如果您為了保存更多狀態(tài)信息而替換該方法筒主,應始終先調用 onSaveInstanceState() 的超類實現关噪,然后再執(zhí)行任何操作。 同樣乌妙,如果您替換 onRestoreInstanceState() 方法使兔,也應調用它的超類實現,以便默認實現能夠恢復視圖狀態(tài)藤韵。

注:由于無法保證系統(tǒng)會調用 onSaveInstanceState()虐沥,因此您只應利用它來記錄 Activity 的瞬態(tài)(UI 的狀態(tài))— 切勿使用它來存儲持久性數據,而應使用 onPause() 在用戶離開 Activity 后存儲持久性數據(例如應保存到數據庫的數據)泽艘。

您只需旋轉設備欲险,讓屏幕方向發(fā)生變化,就能有效地測試您的應用的狀態(tài)恢復能力匹涮。 當屏幕方向變化時盯荤,系統(tǒng)會銷毀并重建 Activity,以便應用可供新屏幕配置使用的備用資源焕盟。 單憑這一理由秋秤,您的 Activity 在重建時能否完全恢復其狀態(tài)就顯得非常重要,因為用戶在使用應用時經常需要旋轉屏幕脚翘。(對于大多數應用灼卢,我們都是設置不可旋轉屏幕的)

6.Activity的啟動模式和onNewIntent方法

  • Standard
  • SingleTop
  • SingleTask
  • SingleInstance

1. Standard

標準模式下,每次啟動Activity都會新建一個Activity實例并往Activity棧中放入来农。如果所有的Activity均為標準模式可能存在這樣的情況鞋真。
A->B->A->C->B->A->A->A....

2.SingleTop

在Activity棧的棧頂只會存在一個Activity實例,如果棧頂就是當前要創(chuàng)建Activity的實例沃于,不創(chuàng)建當前實例涩咖,調用該Activity實例的onNewInstance方法海诲;如果棧頂不是該對象的實例,則創(chuàng)建該對象的實例加入Activity棧的棧頂檩互。
因此會存在棧中存在多個某Activity的實例特幔,但是不會連續(xù)出現兩個。如:
A->B->A->C->B->A->B->C->B->A->C....

3.SingleTask

在Activity棧中只存在一個Activity的實例闸昨,如果棧中存在要創(chuàng)建的Activity的實例蚯斯,則不會新創(chuàng)建Activity,并且會將該Activity上的其他Activity清除掉饵较,同時會調用onNewIntent方法拍嵌。如原來棧中元素為:A->B->C,如果A的啟動模式為singleTask,則再次啟動A后,B和C會被清除,棧中元素變成了A;復用上面的例子循诉,如果要啟動的是B并且B為SingleTask,再次啟動B后棧中元素變成了AB.

4.SingleInstance

會創(chuàng)建一個新的Activity棧横辆,并且在新的Activity棧中加入該Activity實例,同時該棧中實例會被其他應用共享茄猫,這個沒有實際用過龄糊。

5.onNewIntent方法

在谷歌的原檔中只提到了該方法會在啟動模式設為SingleTop的時候調用,但是實際上似乎設為SingleTask時也同樣會觸發(fā)該方法募疮。
下面是谷歌文檔中的原話:

void onNewIntent (Intent intent)
This is called for activities that set launchMode to "singleTop" in their package, or if a client used the FLAG_ACTIVITY_SINGLE_TOP flag when calling startActivity(Intent). In either case, when the activity is re-launched while at the top of the activity stack instead of a new instance of the activity being started, onNewIntent() will be called on the existing instance with the Intent that was used to re-launch it.
An activity will always be paused before receiving a new intent, so you can count on onResume() being called after this method.
Note that getIntent() still returns the original Intent. You can use setIntent(Intent) to update it to this new Intent.

谷歌爸爸是說在清單文件或者啟動Activity時設置了SingleTop,在棧頂重新啟動時會調用onNewIntent方法炫惩。然后呢,要注意的一點時是接收新的Intent之前Activity會先進入onPause狀態(tài)阿浓,還有一點是這個時候需要手動調用setIntent方法他嚷,將參數中傳遞的Intent保存下來,否則下次調用getIntent方法的時候芭毙,拿到的還是第一次的那個Intent筋蓖。嗯,就醬退敦。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末粘咖,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子侈百,更是在濱河造成了極大的恐慌瓮下,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钝域,死亡現場離奇詭異讽坏,居然都是意外死亡,警方通過查閱死者的電腦和手機例证,發(fā)現死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門路呜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事胀葱∧铮” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵抵屿,是天一觀的道長庆锦。 經常有香客問我,道長晌该,這世上最難降的妖魔是什么肥荔? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任绿渣,我火速辦了婚禮朝群,結果婚禮上,老公的妹妹穿的比我還像新娘中符。我一直安慰自己姜胖,他們只是感情好,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布淀散。 她就那樣靜靜地躺著右莱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪档插。 梳的紋絲不亂的頭發(fā)上慢蜓,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音郭膛,去河邊找鬼晨抡。 笑死,一個胖子當著我的面吹牛则剃,可吹牛的內容都是我干的耘柱。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼棍现,長吁一口氣:“原來是場噩夢啊……” “哼调煎!你這毒婦竟也來了?” 一聲冷哼從身側響起己肮,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤士袄,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后谎僻,有當地人在樹林里發(fā)現了一具尸體窖剑,經...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年戈稿,在試婚紗的時候發(fā)現自己被綠了西土。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡鞍盗,死狀恐怖需了,靈堂內的尸體忽然破棺而出跳昼,到底是詐尸還是另有隱情,我是刑警寧澤肋乍,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布鹅颊,位于F島的核電站,受9級特大地震影響墓造,放射性物質發(fā)生泄漏堪伍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一觅闽、第九天 我趴在偏房一處隱蔽的房頂上張望帝雇。 院中可真熱鬧,春花似錦蛉拙、人聲如沸尸闸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽吮廉。三九已至,卻和暖如春畸肆,著一層夾襖步出監(jiān)牢的瞬間宦芦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工轴脐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留调卑,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓豁辉,卻偏偏與公主長得像令野,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子徽级,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內容

  • 【Android Activity】 什么是 Activity? 四大組件之一,通常一個用戶交互界面對應一個 ac...
    Rtia閱讀 3,800評論 3 18
  • Activity生命周期 Activity的生命周期包括onCreate(),onRestart(),onStar...
    星泉毅閱讀 620評論 0 0
  • Activity是一個應用組件气破,用戶可與其提供的屏幕進行交互,以執(zhí)行撥打電話餐抢、拍攝照片现使、發(fā)送電子郵件或查看地圖等操...
    進攻的螞蟻閱讀 1,154評論 0 0
  • Activity 一、四種形態(tài) 運行狀態(tài): 當 Activity 處于棧的頂層旷痕,可見碳锈,并可與用戶進行交互 onRe...
    任教主來也閱讀 1,647評論 1 10
  • 早晨起來姐弟倆個看著雪景高興壞了,上學快遲到了欺抗,趕緊踩了兩腳去上學了 明天是周六了售碳,晚上早早的把倆個寶貝接了回來,...
    楊紫寒閱讀 140評論 0 4