Day11-activity

生命周期

  • onCreate();
  • onStart(); 可見,
  • onResume(); 可操作,在前臺
  • onPause();
  • onStop();
  • onDestroy();
    • onRestart(); 返回前activity, 讓他重新啟動
  • 當Activity只執行onPause方法時(透明Activity),這時候如果App設置的targetVersion大于11則不會執行onSaveInstanceState方法

處理廣播, 在onStart和onStop, onResume和onPause易觸發并且可能只是暫時不能執行(被透明activity擋住)

跳轉B前操作數據庫, 并且B需要數據庫, 在onPause,

onPause
onCreate--B
onStart--B
onResume--B
onStop

所以得確保B沒出來的時候數據加載完畢, 但是如果B是半透明的, 則不會執行onStop
B返回A

onPause -B
onRestart
onStart
onResume
onStop --B
onDestroy --B

黑屏/按home/按任務列表生命周期:

onPause
onStop
onRestart
onStart
onResume

橫豎屏切換生命周期,此時開 alertDialog.Builder 格式的dialog, 生命周期不影響

onPause
onStop
onDestroy
onCreate
onStart
onResume

Activity 是否運行

(activity == null || activity.isDestroyed() || activity.isFinishing())
原因: isFinishing 根據 mFinished, mFinished只在finish時改變, 無法確定finish一定會執行, 且 finish 執行后, 無法保證立馬走到 onDestroy

public boolean isFinishing() {
       return mFinished;
   }

根據Google源碼中的Dialer應用的源碼Link, 添加 isDestroyed 判斷

@Override
    protected void onPostExecute(Void result) {
        final Activity activity = progressDialog.getOwnerActivity();

        if (activity == null || activity.isDestroyed() || activity.isFinishing()) {
            return;
        }

        if (progressDialog != null && progressDialog.isShowing()) {
            progressDialog.dismiss();
        }
    }

onUserLeaveHint 和 onUserInteraction

  • onUserLeaveHint
    當用戶的操作導致activity即將進入后臺的時候, 此方法會被調用, 但在來電時不被調用
  • onUserInteraction
    activity 在分發各種事件之前會調用, 但啟動另一個activity會被調用兩次, 一次是 activity 補貨到事件時, 一次是調用activity.onUserLeaveHint之前會調用onUserInteraction

臨時狀態保存 -- onSaveInstanceState 和 onRestoreInstanceState

是用來臨時存儲數據, 長期的還是需要數據庫

前提是view必須有ID

保存狀態

  • onSaveInstanceState(Bundle savedInstanceState)
    執行在 onStop 之前

    • 只有back不會觸發
      ===================
    • home觸發
    • 任務列表鍵會觸發
    • 跳轉 Activity 會觸發
    • 旋轉屏幕會觸發
    • 黑屏會觸發

    Activity 創建時有一個 bundle 對象, 該對象是上次被系統銷毀時在 onSaveInstanceState 保存的參數,
    ```java
    static final String STATE_SCORE = "playerScore";
    static final String STATE_LEVEL = "playerLevel";

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        // Save the user's current game state
        savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
        savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
    
        // Always call the superclass so it can save the view hierarchy state
        super.onSaveInstanceState(savedInstanceState);
    }
    ```
    **注意,自定義的部分在super之前**
    

    使用onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState), 則onSaveInstanceState不會被調用

  • onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState)
    API21 后添加的屬性, 能在關機重啟后擁有數據恢復的功能, 需要在 manifest 中給 acticity 添加屬性

    android:persistableMode="persistAcrossReboots"
    

    • 重寫 onCreate(Bundle savedInstanceState, PersistableBundle persistentState),
    • 并不用普通的 onCreate 和 onSaveInstanceState

    重寫此onSaveInstanceState會導致 onSaveInstanceState 不執行

恢復狀態

  • onRestoreInstanceState
    執行在 onStart 之后, 只有有savedInstanceState時才會調用, 無需判空

    public void onRestoreInstanceState(Bundle savedInstanceState) {
        // Always call the superclass so it can restore the view hierarchy
        super.onRestoreInstanceState(savedInstanceState);
    
        // Restore state members from saved instance
        mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
        mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
    }
    
  • onCreate中恢復, 需判空

     @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState); // Always call the superclass first
    
        // Check whether we're recreating a previously destroyed instance
        if (savedInstanceState != null) {
            // Restore value of members from saved state
            mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
            mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
        } else {
            // Probably initialize members with default values for a new instance
        }
        ...
    }
    

透明activity(繼承AppCompatActivity)

  1. 透明color
<?xml version="1.0" encoding="UTF-8"?>  
<resources>  

    <color name="transparent">#0000</color>  

</resources>  
  1. style設置background, style的parent不加會報錯: You need to use a Theme.AppCompat theme (or descendant) with this activity.
<style name="myTransParent" parent="Theme.AppCompat.Light.NoActionBar">
    <item name ="android:windowBackground">@color/transParent</item>
    <item name ="android:windowNoTitle">true</item>
    <item name ="android:windowIsTranslucent">true</item>
    <item name ="android:colorBackgroundCacheHint">@null</item>
    <item name ="android:windowAnimationStyle">@android:style/Animation.Translucent</item>
    <item name ="android:statusBarColor">@color/transParent</item>
</style>
  1. 清單設置 activity 的 theme
android:theme="@style/myTransparent"

ActivityA 打開透明ActivityB

onPause
onCreate --B
onStart --B
onResume --B

透明ActivityB返回ActivityA

onPause --B
onResume
onStop --B
onDestroy --B

啟動模式

A組件運行在A應用, A組件調用系統的照相組件, 雖然不在一個應用, 但是安卓運行跨應用組件, 雖然兩者不在一個進程, 但是可以通過Task來實現, Task可以理解為實現一個功能而負責管理所有用到的 Activity實例的棧

standard

默認, 先進后出

singleTop

棧頂不重復, 唯一
如果要開啟的 activity 已經在棧頂存在, 就不會創建新的實例, 而去調用 onNewIntent().
如果棧頂沒有, 則創建新的實例
比如 通知欄的通知點擊打開activity, 用singleTop可以避免重復創建
快速點擊不能只依賴這個, 不靠譜, 第一個棧實例可能還沒入棧,就創建了第二個然后和第一個一起入棧了, 建議對快速點擊另作判斷

singleTask

棧內不重復, 干掉頭上的其他activity
如果要開啟的activity已經在棧內存在, 就不會創建新的棧和新的實例, 而去調用 onNewIntent(), 并且清空它上面的所有activity
比如 主界面, 保證主界面上面沒有activity

singleInstance

單一實例, 單一棧, 棧里只有自己
謹慎使用
如果要開啟的activity已經在進程中存在, 就不會創建新的實例, 而去調用 onNewIntent().
比如 呼叫來電界面

指定啟動模式

  • manifest指定
<activity android:name=".SecondActivity"
            android:launchMode="singleTask"/>
  • 代碼指定
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
               //通過 intent.addFlags 設置
               intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
               startActivity(intent);
  • 對比

    • 代碼指定優先于 manifest
    • manifest無法設定singleInstance模式
  • Intent.FLAG_:

    • FLAG_ACTIVITY_NEW_TASK = 開新棧, 多用在service和Application, 因為他倆沒有棧
    • FLAG_ACTIVITY_SINGLE_TOP = singleTop
    • FLAG_ACTIVITY_CLEAR_TOP = singleTask
    • FLAG_ACTIVITY_NO_HISTORY 啟動完其他的后, 自己消失
  • StartActivityForResult 5.0 分水嶺

    • 5.0 之前可能不回調
    • 5.0 后全部有回調
  • adb 查看任務棧

    1. 運行

      adb shell dumpsys activity
      
    2. 搜 Recent tasks 查看已經存在的任務棧

      Recent tasks:
         * Recent #0: TaskRecord{5bd8fdd #749 A=com.taskaffinity U=0 sz=1}
         * Recent #1: TaskRecord{a972e43 #748 A=com.activityfull U=0 sz=1}
         * Recent #2: TaskRecord{7a2180c #664 I=com.android.launcher3/.Launcher U=0 sz=1}
      
    3. 搜 Running activities (most recent first)查看activity

      Running activities (most recent first):
         TaskRecord{25d22cd #684 A=com.activityfull U=0 sz=2}
           Run #1: ActivityRecord{8e55d0b u0 com.activityfull/.SecondActivity t684}
           Run #0: ActivityRecord{d26b857 u0 com.activityfull/.MainActivity t684}
      

    棧的唯一標號是#682, sz 表示棧內有幾個組件, 棧頂的是 SecondActivity,

    1. Recent tasks查看手機程序的任務棧, != 應用數(一個應用可能包含多個棧), 更不是進程數
      任務棧數 = 手機任務列表里顯示的數量 + com.android.launcher + com.android.systemui
      ACTIVITY MANAGER RECENT TASKS (dumpsys activity recents)
        Recent tasks:
        * Recent #0: TaskRecord{42a273f #682 A=com.activityfull U=0 sz=1}
        * Recent #1: TaskRecord{7a2180c #664 I=com.android.launcher3/.Launcher U=0 sz=1}
        * Recent #2: TaskRecord{8a01555 #667 A=com.android.systemui U=0 sz=1}
      
android:exported="true"

允許其他app打開這個activity

taskAffinity + allowTaskReparenting

  • taskAffinity
    設置activity進入指定完整棧名的棧,一般和singleTask一起使用
    • Application中設置(推薦activity設置), 不設定則默認包名, 設定了內部activity和Application一致
    • Activity中設置, 如果指定的任務棧不存在, 那么會自己新開一個指定包名的任務棧
  • allowTaskReparenting
    是否依附與開啟這個activity的任務棧
  • 舉例:
    • APP1內有activity1, activity2; APP2內有activity3和activity4, 當APP1 的 activity1 在 APP1 內打開這個 APP2 的 activity4 時,

      <activity android:name=".FourActivity"
               android:exported="true"
               />
      

      a. 只有 APP1 的任務棧打開, 存放的是 activity1 和 activity4;
      b. 按home, 點開 APP1 看到的是 activity4, 按back, 看到activity1, 按back, 退出
      c. 按home, 點開 APP2 看到的是 activity3, 按back, 退出

      <activity android:name=".FourActivity"
                 android:exported="true"
                 android:allowTaskReparenting="true"
                 />
      

      a. 只有 APP1 的任務棧打開, 存放的是 activity1 和 activity4;
      b. 按home, 點開 APP1 看到的是 activity1,
      c. 按home, 點開 APP2 看到的是 activity4, 按back, 看到activity3, 按back, 退出

      <activity android:name=".FourActivity"
                 android:exported="true"
                 android:allowTaskReparenting="true"
                 android:launchMode="singleTask"
                 />
      

      a. APP1 任務棧存放 activity1, APP2 的任務棧存放activity4
      b. 按home, 點開APP1 看到的是 activity1
      c. 按home, 點開APP2 看到的是 activity4, 按back退出

參考

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,428評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,024評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,285評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,548評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,328評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,878評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,971評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,098評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,616評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,554評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,725評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,243評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,971評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,361評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,613評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,339評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,695評論 2 370

推薦閱讀更多精彩內容