《Android開發藝術探索》筆記(1)


一、Activity的生命週期

1、正常的生命週期

  • onCreate():

    表示Activity正在被創建,是生命週期中的第一個方法,可以在這個方法中做一些初始化工作,如調用setContentView()去加載佈局資源,初始化Activity所需的數據,當然如果加載的數據比較多或者比較耗時的操作建議採用異步加載的方式,加快界面的出現,待異步加載完成再去設置view的屬性。

  • onRestart():

    表示Activity正在被重新創建,一般情況下當Activity由stop狀態重新變爲可見時,onRestart被調用。

  • onStart():

    表示Activity正在啓動,即將開始,這個時候Activity已經可見,只是還沒出現在前臺,所以看不見。可見與看見還是有區別的。

  • onResume():

    表示Activity已經可見,獲取焦點(在前臺)可與用戶交互了。

  • onPause():

    表示Activity正在失去焦點。應用場景:遊戲暫停時在該方法保存遊戲數據,在onResume中恢復。

  • onStop():

    表示Activity正在被停止,這個時候可以做一些稍重量級的操作,同樣不能太耗時。

  • onDestroy():

    表示Activity即將銷燬,是生命週期中最後的一個回調方法,我們可以在這裏做一些回收工作和最終的資源釋放。

  • 完整的生命週期

    onCreate()–>onStart()–>onResume()–>onPause()–>onStop()–>onDestroy()

  • 可見週期:

    onStart()–>onResume()–>onPause()–>onStop()期間

  • 前臺(獲得焦點)週期:

    onResume()–>onPause()期間

  • 有一個比較特殊的方法onRestart()會在Activity有不可見變爲可見是調用,即當一個Activity處於stop狀態時,再次變爲可見時:onRestart()–>onStart()–>onResume()

  • 當前Activity onPause()之後啓動的Activity才能onResume,所以不要再在onPause方法做一些重量級的操作。

2、異常情況下的生命週期

到底什麼情況下會出現異常?

  • ①資源相關的系統配置發生變化導致Activity被銷燬重建,如橫豎屏切換(在不處理的情況下會銷燬重建);
  • ②系統資源內存不足,導致較低優先級的Activity被暫時回收;

  • 這種情況下的生命週期爲:

    onSaveInstanceState()–>onDestroy()
    onCreate()–>onRestoreInstanceState()

當Activity被異常終止的情況下,在onStop()之前會調用onSaveInstanceState()來保存數據,這些數據會以Bundle的形式傳到onCreate()和onRestoreInstanceState(),onRestoreInstanceState()的調用時機在onStart()之後。當Activity被異常終止的時候系統會自動保存一些數據,當然我們有時也需要自己保存一些數據,具體系統會自動保存和恢復哪些數據,這要看看具體的View的onSaveInstanceState()和onRestoreInstanceState()。

  • 既然在重建時onCreate()和onRestoreInstanceState()都能接受到參數,有什麼區別?
    區別是在onCreate(Bundle saveInstanceState)需要判斷saveInstanceState是否爲null,而onRestoreInstanceState(Bundle saveInstanceState)一旦被調用saveInstanceState就不爲null,當然,官方推薦在onRestoreInstanceState()中恢復數據。

二、Activity啓動模式

1、standard

默認的標準模式,每次啓動都會創建一個新的實例並置於棧頂,任務棧中可存在多個實例;新啓動的Activity屬於啓動它的Activity所在的任務棧,這就意味着必須通過Activity的Context來啓動standard模式的Activity,假設通過ApplicationContext來啓動則會拋出異常,因爲ApplicationContext並沒有所屬的任務棧,這個時候可以通過FLAG_ACTIVITY_NEW_TASK標記位來解決這個問題,但是這樣實際就是以singleTask模式來啓動了。

2、singleTop

棧頂服用模式,當棧頂的實例是要啓動的Activity的實例時,不會重新初建,但是onNewIntent方法會被調用,可以通過這個方法的參數獲得當前請求的信息。

3、singleTask

棧內複用模式,這是一種單實例模式,當請求啓動一個該模式的Activity時,①如果所需要的任務棧不存在,創建任務棧,新建實例入棧;②如果任務在存在但無該Activity實例,新建實例入棧;③如果任務棧存在,實例也存在,clearTop,將該實例之上的實例全部出棧,讓該實例暴露在棧頂。

4、singleInstance

單實例模式,是加強的singleTask,除了棧內複用,在啓動singleInstance模式的Activity時會新創建一個任務棧,並且這個任務棧中只有該實例,後續都不會再創建該Activity的實例,除非這個任務棧由於某種原因被回收了。

  • 以上幾種模式,在發出新的啓動請求時,如果不創建新的實例,都會調用onNewIntent方法,可以通過這個回調方法的參數來獲取每次請求的參數。

三、IntentFilter的匹配規則

隱式調用需要Intent匹配目標組件IntentFilter所設置的過濾信息,IntentFilter中包含的過濾信息有:action、category、data,Intent匹配過程需要同時匹配這三個過濾信息,否則就會匹配失敗。這三種過濾信息的匹配規則是有差異的。

1、action的匹配規則

action是一個字符串,目標組件中的action可以有多個,隱式Intent中指定的action必須和目標組件的action列表中的其中一個完全相同(區分大小寫),否則匹配失敗,另外Intent中是必須指定action的。

2、catetory匹配規則

category是一個字符串,在寫隱式Intent時可以不包含category,如果有一個或者多個,那麼所有的都需要和目標組件中的category列表中的任意一個相同,否則匹配失敗。在調用startActivity()或者startActivityForResult()時Intent會默認添加上android.intent.category.DEFAULT,這就是爲什麼在寫隱式Inent時可以不包含category的原因,但是這也就意味着我們在定義IntentFilter時如果沒有加上
<category android.name="android.intent.category.DEFAULT"
這個過濾信息,這個組件就不能被隱式Intent匹配。

3、data匹配規則

data的語法是相對複雜的。data的匹配規則和action的匹配規則類似,Intent中必須包含data,並且要和過濾器中的其中一個data相同。

excample:

activity android:name=".ShareActivity">
    <intent-filter>
        <action android:name="com.test.action1"/>
        <action android:name="com.test.action2"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="com.test.category1"/>
        <category android:name="com.test.category2"/>
        <data android:mimeType="text/plain"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="video/*"/>
    </intent-filter>
</activity>

可以匹配的兩個隱式Intent

Intent intent = new Intent();
intent.setAction("com.test.action1");
intent.addCategory("com.test.category1");
intent.setType("text/plain");
startActivity(intent);
Intent intent = new Intent();
intent.setAction("com.test.action1");
intent.setType("text/plain");
intent.setType("image/*");
startActivity(intent);

上面這個Intent會默認添加

intent.addCategory("android.intent.category.DEFAULT");

若去掉IntentFilter中的
<category android:name="android.intent.category.DEFAULT"/>
任何隱式Intent都不能匹配這個組件,原因已在category匹配規則說明。

發佈了22 篇原創文章 · 獲贊 9 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章