Android開發(fā)由淺入深-Activity

前言

作為Android的四大組件之一,Activity占據(jù)著非常重要的作用。本文將圍繞Android的生命周期、啟動模式、基本配置等方面進行介紹。本文知識來源于各類技術(shù)書籍以及博客,文章末尾已經(jīng)列出。

簡介

應(yīng)用程序的每一個界面都是一個Activity,所以也有人稱其為視圖界面。從字面的意思去理解,Activity具有活動的意思,我們在應(yīng)用中進行的操作都是集中在Activity上面完成,例如撥號、拍照、發(fā)送email、看地圖。每一個activity被給設(shè)置到一個窗口,在上面可以繪制交互界面。窗口通常充滿屏幕,也可以小于屏幕而浮于其它窗口之上,如浮動圓角對話框Activity

一個應(yīng)用程序通常由多個activities組成,他們通常是松耦合關(guān)系,通常一個應(yīng)用程序包含有一個主Activity,即點擊桌面圖標的時候首先進入的Activity。

Android創(chuàng)建與啟動

以一個簡單的Activity的創(chuàng)建與使用示說明:

創(chuàng)建
public class MainActivity extends Activity {
    Button mButton;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mButton = (Button) findViewById(R.id.button1);
    }
}

通過集成Activity類完成新建Activity,并且至少需要重寫onCreate方法。在onCreate中,通過setContentView為Activity設(shè)置布局。

注冊Activity

在manifest中注冊Activity

    <activity
        android:name=".activity.MainActivity"
        android:configChanges="orientation|screenSize"
        android:label="@string/app_name"
        android:launchMode="standard" >
        <intent-filter>        
                 <action android:name="myaction2"/>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />    
        </intent-filter>
    </activity>

Activity必須在AndroidManifest.xml注冊,如果沒有注冊,這個Activity就不能正常運行。
其中如果在<intent-filter>中指定

    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" /> 

表明這個Activity是主Activity,在Android系統(tǒng)點擊應(yīng)用圖標首先進入主Activity。

啟動Activity

Activity是通過Intent用來在應(yīng)用程序的Activity間啟動、停止和傳輸。
啟動Activity的三種方法:
1、顯示啟動
在當(dāng)前Activity啟動Activity2

    Intent intent = new Intent(this , Activity2.class);
    startActivity(intent);

2、隱式啟動
若Activity2在AndroidManifest.xml文件中配置intent-filter的action和category、data,如下:

<intent-filter>
    <action android:name="myaction2"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <category android:name="mycategory" />
</intent-filter>

那么可以通過如下方式啟動Activity2:

Intent intent = new Intent("myaction2");
startActivity(intent);

這樣就可以啟動Activity2

注:在使用intent隱式調(diào)用Activity時會遇到多個Activity的intent-filter中的action和category相同時,這時android會先彈出一個選擇界面的窗口,顯式要啟動的Activity列表,根據(jù)用戶的選擇來啟動Activity,如Activity2和Activity3的action和category相同
3、默認啟動
通過桌面圖標點擊應(yīng)用圖標進入程序的第一個Activity,因其啟動方式有別上述兩個方式,將其劃分為第三類的啟動方式。
若Activity在AndroidManifest.xml文件的intent-filter的action和category,如下:

<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

那么,點擊桌面的應(yīng)用圖標即可啟動Activity。
注:如果在N個Activity中都配置上述的action和category,那么桌面會有N個應(yīng)用的圖標,點擊不同的圖標會進入對應(yīng)的Activity。

Activity切換動畫
Android的生命周期

接下來給各位介紹Activity的生命周期,如下圖

圖 1 Activity的基本生命周期

我覺得上面這張圖更加讓人理解Android的生命周期,大家不妨對比著看。
詳細的生命周期可以點此查看
(1) onCreate
表示Activity正在被創(chuàng)建,這是第一個執(zhí)行的方法,在Activity的生命周期中只執(zhí)行一次。在這個方法中做一些初始化工作,比如調(diào)用setContentView去加載界面布局,初始化Activity所需要的數(shù)據(jù)等。后續(xù)的方法是onStart
(2) onRestart
表示Activity正在重新啟動,一般情況下,當(dāng)前的Activity從不可見的狀態(tài)變?yōu)榭梢姞顟B(tài)時,onRestart就會被調(diào)用。這種情形一般是用戶操作出現(xiàn)所致,比如用戶按Home鍵回到桌面或者用戶打開了一個新的Activity,這時候Activity就會暫停,接著用戶又回到該Activity。后續(xù)方法是onStart
(2) onStart
表示Activity正在被啟動,即將開始。這個時候Activity是可見的,但是還沒有出現(xiàn)在前臺,不能和用戶進行交互。這個時候可以理解為Activity已經(jīng)顯示出來,但是我們還看不到。后續(xù)的方法是onResume
(4) onResume
表示Activity可見,并且已經(jīng)出現(xiàn)在前臺并開始活動,能和用戶正常進行交互。需要注意的是onStart和onResume的區(qū)別,二者都是Activity可見,但是onStart時Activity還在后臺,而onResume時Activity到了前臺了,這時候可以開啟動畫或者獲取獨占性設(shè)備的操作如打開相機、獲取麥克風(fēng)等。
(5) onPause
表示Activity由前臺轉(zhuǎn)到后臺,正常情況下,緊接著onStop就會被調(diào)用。這時仍然可見。如果這時候快速地回到當(dāng)前Activity,那么onResume會被調(diào)用,這類情況屬于極端情況,用戶操作很難重現(xiàn)這一場景。此時可以做一些存儲數(shù)據(jù),停止動畫等操作,但是注意不能太耗時,如果太耗時會影響到新的Activity的顯示。onPause是先執(zhí)行完,新的Activity的onCreate才會執(zhí)行。onResume和onPause相對應(yīng)。
(6) onStop
表示Activity即將停止,當(dāng)前的Activity對用戶不在可見。可稍微做些重量級的回收操作。后續(xù)的操作可能是onRestart或者onDestroy或者一直保持這個狀態(tài)。
(7) onDestory
表示Activity正在被銷毀,是生命周期的最后一個回調(diào),也是只調(diào)用一次。發(fā)生的條件是Activity本身已經(jīng)執(zhí)行完畢,或者系統(tǒng)資源不足需要回收資源將Activity銷毀。

我們考慮如下幾類情況:
1、當(dāng)一個Toast彈出的時候,會發(fā)生回調(diào)么?
No
2、當(dāng)一個AlertDialog彈出的時候,會發(fā)生回調(diào)么?
No, 如果AlertDialog獲取焦點,Activity會觸發(fā)onWindowFocusChanged回調(diào)
3、當(dāng)一個PopWindow彈出的時候,會發(fā)生回調(diào)么?
No, 如果PopWindow獲取焦點,如mPopupWindow.setFocusable(true),Activity會觸發(fā)onWindowFocusChanged回調(diào)。
4.橫豎屏切換時,會造成Activity被銷毀然后重新創(chuàng)建。若在Activity配置android:configChanges="orientation",橫豎屏切換時,只觸發(fā)onConfigurationChanged( )回調(diào),Activity不會被重新創(chuàng)建。

啟動模式

Activity有四種不同的啟動模式,不同的模式,對應(yīng)著Activity對象創(chuàng)建與復(fù)用策略各有特點,可以在Manifest中配置啟動模式

<activity android:name="cn.iterlog.xmimagepicker.videoplay.VideoActivity"
    android:theme="@style/ImageTheme"
    android:launchMode="singleInstance"
    >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

首先先了解兩個概念Task和Back Stack。

Task和Back Stack

Task:用于提供給用戶操作完成一項任務(wù)的Activity集合,注意Activity可以來自不同的App,同一個App的Activity也可能在不同的Task重
Back Stack(回退棧): 管理著Task中所有的Activity的Stack(棧), 遵循后進先出原則。
處于Back Stack的最低部的Activity被稱作根Activity。
一般情況下,當(dāng)前Activity A啟動新的Activity B的時候,B會入棧,處于回退棧最頂端,并獲取焦點。A位于棧中,處于stop的狀態(tài)。如果用戶點擊后退鍵或者B調(diào)用finish()方法,那么B被出棧,B的onDestroy被調(diào)用,整體銷毀。A重新獲取焦點,進入前臺。
Task里面的Activity嚴格按照"后進先出"的方式進行管理,他們的順序不會發(fā)生改變。下圖展示了Activity的新建和退出時,回退棧的變化。


圖 2 回退棧

如果Task的棧頂Activity處于前臺狀態(tài),Task也是處于前臺狀態(tài)。
如果Task的棧頂Activity處于后臺狀態(tài),Task也處于后臺狀態(tài)。
用戶在使用應(yīng)用的時候點擊Home鍵,Task則由前臺轉(zhuǎn)入后臺,用戶之后點擊桌面啟動圖標,再次啟動應(yīng)用,那么此時Task由后臺轉(zhuǎn)入前臺頁面。


圖 3 Task的前臺和后臺狀態(tài)
四種啟動模式

正常情況下,啟動多個相同Activity的時候會默認新建多個對象,并將他們?nèi)霔!F鋵嵤菦]有必要為Activity創(chuàng)建這么多相同的對象的,Android在設(shè)計的時候也考慮到這個問題,所以提供了四種啟動模式。

standard

系統(tǒng)默認模式,每次啟動一個Activity都會重新創(chuàng)建一個新的實例,而不管Activity是否已經(jīng)創(chuàng)建了一個實例。

singleTop

棧頂復(fù)用模式,系統(tǒng)啟動時,系統(tǒng)會啟動當(dāng)前棧頂Activity是不是要啟動的Activity,如果是則不需要創(chuàng)建新的Activity而直接引用這個Activity,如果不是那么創(chuàng)建新的Activity。系統(tǒng)會回調(diào)onNewIntent的方法。

singleTask

棧內(nèi)復(fù)用模式,如果棧內(nèi)已經(jīng)存在了一個Activity的實例,那么Activity不會被重新創(chuàng)建,同時他的onNewIntent方法會被回調(diào),并將該Activity實例置于棧頂,原先處于該實例頂部的Activity實例會被出棧銷毀。如果是其他程序啟動Activity,那么它會重新創(chuàng)建一個任務(wù)棧。

singleInstance

單實例模式,是singleTask的加強版,具有singleTask所有特點,并且此種模式下Activity只有一個實例,并且只能單獨的存在一個任務(wù)棧中。
通過Intent啟動Activity的時候,可以通過添加標志位的啟動方式。

 Intent intent = new Intent(this, SecondActivity.class);
 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 startActivity(intent);

Intent.FLAG_ACTIVITY_NEW_TASK
使用一個新的Task來啟動Activity,但每個Activity都將在一個新的Task中。該Flag通常使用在Service重啟動Activity的場景。
Intent.FLAG_ACTIVITY_SINGLE_TOP
使用singleTop模式來啟動一個Activity
Intent.FLAG_ACTIVITY_CLEAR_TOP
使用singleTask模式來啟動一個Activity
Intent.FLAG_ACTIVITY_NO_HISTORY
使用singleTask模式來啟動一個Activity
使用這種方式啟動Activity,當(dāng)Activity啟動其他Activity的時候,該Activity會被銷毀,不入棧。

資料來源

[1].https://developer.android.com/guide/components/activities.html
[2].http://www.cnblogs.com/tekkaman/archive/2011/06/07/2074211.html
[3].http://blog.csdn.net/guxiao1201/article/details/41517567
[4].安卓群英傳.徐宜生.電子工業(yè)出版社.2015
[5].安卓開發(fā)藝術(shù)探索.任玉剛.電子工業(yè)出版社.2015
[6].http://www.lxweimin.com/p/d4d677727a0a

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,106評論 6 542
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,441評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,211評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,736評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,475評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,834評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,829評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,009評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,559評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,306評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,516評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,038評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,728評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,132評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,443評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,249評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,484評論 2 379

推薦閱讀更多精彩內(nèi)容