簡體   English   中英

最簡單的 Android Activity 生命周期

[英]Simplest Android Activity Lifecycle

我注意到自從我啟動我的應用程序以來,Android Developers Activity 部分已經更新,但我仍然不清楚最簡單的 Activity Lifecycle 是什么。

據我所知:

onCreate、onResume 和 onPause 是必不可少的。

活動可能會在 onPause 之后的任何時間被刪除,所以我應該將我的整個應用程序狀態保存到一個文件 onPause 而不是依賴於 onStop 或 onDestroy。 此外,onSaveInstanceState 不會在每次 onPause 之前調用,因此並不值得使用。

與其嘗試編寫大量代碼來處理所有場景,為什么不在 onPause 結束時銷毀 Activity?

Lifecycle 將在處於活動狀態之前 onCreate 和 onResume,然后在變為非活動狀態時 onPause。 不需要其他方法。

我會使用 onCreate 來調用 setContentView 並設置視圖偵聽器,但其他所有內容都將放在 onResume 中,包括從文件加載恢復的狀態? 如前所述,onPause 會將狀態保存到文件並銷毀活動。

據我所知,唯一的缺點可能是當屏幕上出現彈出窗口時,活動將被刪除,並且必須在彈出窗口關閉時重新創建,這意味着該活動在彈出窗口后面不可見(盡管我沒有測試過這個)

重新啟動活動可能需要更長的時間,但由於系統可能會在沒有任何通知的情況下刪除活動,因此您無論如何都必須保存整個狀態。

有什么想法嗎?

更新:我想我在想的是“首頁”活動在哪里調用游戲活動。 當玩家點擊“播放”時,首頁活動將調用游戲活動

游戲活動將在 onCreate 中設置其視圖和偵聽器等,並在 onResume 中加載包含游戲狀態的文件,如果不存在文件,則啟動新游戲。

onPause 游戲,它將游戲狀態寫入文件,然后無論游戲活動發生什么(什么都沒有,或者被停止/破壞,或者其他) onResume 方法總是會再次從文件中重新加載所有數據。

這就是我的想法,如果這有意義嗎?

更新 2:如果有人感興趣,我已經設計了一個簡單的解決方案,我已經記錄在下面的答案中!

它不支持 Android Activity Lifecycle 'Paused' 和 'Stopped' 狀態。 一旦它不再顯示,它就會自行殺死並且必須手動重新啟動,但它確實會從您停止的地方繼續運行!

你在找這個嗎?

活動生命周期

為了進一步回答您的問題,是的,您可以從上圖中清楚地看出,“最簡單”(即最少的方法調用次數)生命周期確實是onCreate(); onStart(); onResume(); onPause(); onCreate(); onStart(); onResume(); onPause(); .

您還應該了解onSaveInstanceState()onRetainNonConfigurationInstance() 這些不是生命周期方法。

所有這些方法都有很好的文檔記錄。 請仔細閱讀本文檔。

為了進一步澄清事情,這里有幾個現實生活場景:

  1. 活動正在運行,其他活動在其之上, onPause被調用。 系統內存不足,調用onSaveInstanceState ,終止活動。 用戶按下幾次后,必須重新實例化活動(最好使用保存在onSaveInstanceState的數據)。
  2. 活動正在運行,用戶按回。 此時onPause->onDestroy被調用,而不調用onSaveInstanceState

您應該了解onPauseonSaveInstanceState之間的本質區別。 前者總是被調用,而后者僅在活動實例將來可能被重新實例化時被調用。 按照這個思路,您的用戶會期待兩件事:

  1. 當他們離開您的 Activity 並稍后返回時,他們希望它與離開它的實例完全相同(這將使用onSaveInstanceState實現)。 如果他們退出您的活動,他們不會期望。 然而:
  2. 他們希望他們輸入的數據將被持久化(這將在onPause完成)。 例如,如果他們開始撰寫消息,他們希望在下次回來時將其視為草稿,即使他們退出了活動。

您應該明白這些方法應該如何才能被用來獲取你的用戶的期望。 您如何實際使用它們取決於您、您的需求和您的應用程序的性質。

Android 系統正在處理生命周期:即實例化活動和調用生命周期方法。 所以我不知道你所說的“破壞活動”是什么意思。 您作為開發人員,沒有這種能力。

其次,活動生命周期流程有時會令人困惑(我知道我一開始就遇到了困難)。 因此,只需實現所有生命周期方法並將日志記錄語句放入其中即可。 然后嘗試所有實際用例(包括在應用程序使用期間接收調用)以查看生命周期方法是如何調用的。

我正在研究活動生命周期以及當您開始任何活動時所發生的完整過程,從onCreate開始。 這是一個 UML 圖來幫助你。

單擊此鏈接可查看高分辨率版本。

在此處輸入圖片說明

答案就像生命周期一樣簡單。 僅當您需要處理其中的內容時才覆蓋回調。

除非在某些情況下,Android 將始終按照預期的方式調用每個回調。

僅僅因為某些回調不能保證被調用並不意味着它們是無用的。 只是不要嘗試在此類回調方法中處理合理的內容。

我個人認為開發人員應該將工作划分為不同的活動狀態。 在這種情況下,必須保留工作的順序,我認為更重要的是,這就是為什么 Android 無法在單個線程中處理長時間的 UI 處理,並且它給出了錯誤,即 Android 有“太多工作要做”這個引用有時可能會導致崩潰 所以我們應該防止在一個部分中編寫整個代碼。 代碼將被寫入不同的函數或類,我們可以根據需要派生這些函數。 謝謝。

Android 應用中有 7 種管理活動生命周期的方法:

  1. 在創建()
  2. 開始()
  3. onResume()
  4. 重啟()
  5. 暫停()
  6. 停止()
  7. 銷毀()

我在我的博客上更深入地寫了這些方法

根據@Felix 提供的答案,成熟的、功能齊全的、功能齊全的 Android 應用程序被轉換(狀態 = 時間函數)。

但是,如果您只想創建一個甚至沒有 GUI 的應用程序呢? 你想要最簡單的生命周期,那么我有下面的答案。

你可能會覺得這個答案很有趣。 Android 系統在閱讀 AndroidManifest.xml 后知道哪個是入口點。 無論哪個活動都有這個

<activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

將是系統開始的起點或入口點。 在此之后,您的應用程序進程獲得了可以自行啟動的內存。

您的主要流程創建是Android系統的任務。 當一個應用程序組件啟動並且該應用程序沒有任何其他組件在運行時,Android 系統會啟動一個新的 Linux 進程。 在進程調用onCreate() 之后,它創建主線程。 這就是您必須調用onCreate()的原因,因為主線程隨后被初始化,主線程是您未來所有操作的觸發器。

在 onCreate() 上,您獲得了主線程。 在那之后,這完全取決於你,你想調用什么回調。 沒有任何規則必須在 onCreate() 之后調用 onStart()。

只有一種生命周期方法 onCreate() 保證是您組件的生命周期返回。

此外,為了了解每個生命周期方法在其中做什么,請放置以下代碼。

//add the log line
        Log.i(this.getClass().getCanonicalName(), "##############");
        int count = 0;
        for (StackTraceElement stackTraceElement:  Thread.currentThread().getStackTrace()) {
            count++;
            Log.i(this.getClass().getCanonicalName(), "\""+Thread.currentThread().getStackTrace()[2].getMethodName()+"\" "+count+" "+stackTraceElement.getMethodName());
        }; //end of log line

因此,始終添加上面相同的代碼以在 log cat 控制台中查看日志。

當您的應用程序啟動 GUI 時,它會調用 onStart()。 如果不在回調中調用 super() 方法, android 系統會顯示管道損壞錯誤,並且無法進行進一步的處理和調試。

在此處輸入圖片說明

但是,您可以在每個回調方法中實現自己的邏輯。 例如,您可以在 onStart() 上對兩個數字求和。

因此,所有 android 回調方法都是部分實現的方法。 它們不是純粹的抽象方法,因為您應該在它們內部調用 super() 方法

附圖說明:應用程序主進程調用onCreate(),它將其職責委托給主線程(UI線程),主線程調用其他16個回調。

在此處輸入圖片說明

此外,如果您想在特定時間查看所有方法,請將其放在代碼下方。

//to see all the methods (including super methods) at this time, you call use the java reflection as below
    Log.i(this.getClass().getCanonicalName(), "##############");
    int count1 = 0;
    for (Method method:  this.getClass().getMethods()) {
        count1++;
        count++;
        Log.i(this.getClass().getCanonicalName(), count1+" "+method);
    }; //end of log line

    //At another time, after you add some other methods or android using GC removes some methods, you see your changed state (Bundle Snapshot) of your class
    //Because your bundle (i.e, the state of your class/activity) is the function of time.

在我的場景中,從上面的代碼片段中,我看到它調用了 375 個方法。

注意:如果您在使用上面的代碼片段打印所有方法之前在 onCreate() 中添加了另一個方法,您也會看到該方法。 這意味着,你的課堂狀態(即快照)取決於你,你一次又一次地做什么,你不斷更新你的快照。

onCreate() 顯然首先。 然后您的活動可以進入 onPause()。 從那里它可以是 onResume() 或 onDestroy()。 這是我所知道的生命周期中最簡單的路徑。

我有一個沒有 onPause() 方法的活動。 通過一系列奇怪的事件,我在 DDMS 中注意到我的應用程序不可見,但它仍在從 AdMob 請求 freshAds :) 不錯的電池吸盤。 這已經解決了,但提醒我簡單的事情是多么重要。

我想我已經找到了我要找的東西! (我 1,波諾 0)

這是針對單個“游戲”活動,它使用最少的方法來控制處理游戲的“游戲線程”線程。 它使用一個額外的“GameData”類來保存激活之間需要持久化的數據。

如果應用失去焦點(即來電,或用戶點擊返回等),Game 會將 GameData 保存到文件中並退出。 要繼續,只需再次啟動應用程序,它就會立即返回到您離開的地方。

布局文件'game.xml'是一個覆蓋整個屏幕的SurfaceView

游戲.java:

  1. onCreate 為 SurfaceView 設置 SurfaceHolder 並創建 GameThread
  2. surfaceChanged調用GameThread.startThread啟動GameThread,如果還沒有啟動,則傳遞屏幕尺寸
  3. onPause 調用 GameThread.endThread 結束 GameThread 並結束本次活動
  4. onTouch 將觸摸事件傳遞給 GameThread.doTouch 方法

游戲線程.java:

  1. startThread 設置本地保存的數據,從文件加載 GameData 並啟動線程
  2. run 是一個標准的游戲循環,為每一幀調用相當標准的 updatePhysics 和 drawScreen 例程。 游戲循環完成后,它會將 GameData 保存到文件中
  3. endThread 在運行中停止游戲循環並等待它完成
  4. 來自游戲活動的 doTouch 動作觸摸事件

它似乎工作。 這確實意味着必須在一個線程中處理不同的屏幕(例如標題屏幕、選項、游戲和游戲結束),但這並不是世界末日,恕我直言。

也許我會在 CodeReview 上發布代碼(如果我這樣做,我會更新它),看看是否有人有任何意見。 同時,我最好開始編寫下一個 Angry Birds 的代碼!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM