Android activity相互跳轉後臺出現兩個頁面的坑

時光中的記憶發表於2017-09-15

首先解釋下,A activity啟動B activity連個activity的生命週期

A 啟動週期
onCreate()——>onStart()——>onResume()
A啟動B A不finish
A onPause()-->B onCreate()——>onStart()——>onResume()-->A onStop()
B返回A
B onPause()-->A onRestart()——>onStart()——>onResume()-->B onStop()——>onDestroy()

一個Activity的銷燬順序:

  (情況一)onPause()——>

  (情況二)onPause()——>onStop()——>

  (情況三)onPause()——>onStop()——>onDestroy()

  每一個活動( Activity )都處於某一個狀態,對於開發者來說,是無法控制其應用程式處於某一個狀態的,這些均由系統來完成。

  但是當一個活動的狀態發生改變的時候,開發者可以通過呼叫 onXX() 的方法獲取到相關的通知資訊。

  在實現 Activity 類的時候,通過覆蓋( override )這些方法即可在你需要處理的時候來呼叫。

  一、 onCreate :當活動第一次啟動的時候,觸發該方法,可以在此時完成活動的初始化工作。

  onCreate 方法有一個引數,該引數可以為空( null ),也可以是之前呼叫onSaveInstanceState
()方法儲存的狀態資訊。

  二、 onStart :該方法的觸發表示所屬活動將被展現給使用者。

  三、 onResume :當一個活動和使用者發生互動的時候,觸發該方法。

  四、 onPause
:當一個正在前臺執行的活動因為其他的活動需要前臺執行而轉入後臺執行的時候,觸發該方法。這時候需要將活動的狀態持久化,比如正在編輯的資料庫記錄等。

  五、 onStop :當一個活動不再需要展示給使用者的時候,觸發該方法。如果記憶體緊張,系統會直接結束這個活動,而不會觸發 onStop
方法。
所以儲存狀態資訊是應該在onPause時做,而不是onStop時做。活動如果沒有在前臺執行,都將被停止或者Linux管理程式為了給新的活動預留足夠的儲存空間而隨時結束這些活動。因此對於開發者來說,在設計應用程式的時候,必須時刻牢記這一原則。在一些情況下,onPause方法或許是活動觸發的最後的方法,因此開發者需要在這個時候儲存需要儲存的資訊。

  六、onRestart :當處於停止狀態的活動需要再次展現給使用者的時候,觸發該方法。

  七、 onDestroy :當活動銷燬的時候,觸發該方法。和onStop
方法一樣,如果記憶體緊張,系統會直接結束這個活動而不會觸發該方法。

  · onSaveInstanceState :系統呼叫該方法,允許活動儲存之前的狀態,比如說在一串字串中的游標所處的位置等。

  通常情況下,開發者不需要重寫覆蓋該方法,在預設的實現中,已經提供了自動儲存活動所涉及到的使用者介面元件的所有狀態資訊。

Activity狀態

一般認為Activity有以下四種狀態:

  活動的:當一個Activity在棧頂,它是可視的、有焦點、可接受使用者輸入的。Android試圖盡最大可能保持它活動狀態,殺死其它Activity來確保當前活動Activity有足夠的資源可使用。當另外一個Activity被啟用,這個將會被暫停。

  暫停:在很多情況下,你的Activity可視但是它沒有焦點,換句話說它被暫停了。有可能原因是一個透明或者非全屏的Activity被啟用。

  當被暫停,一個Activity仍會當成活動狀態,只不過是不可以接受使用者輸入。在極特殊的情況下,Android將會殺死一個暫停的Activity來為活動的Activity提供充足的資源。當一個Activity變為完全隱藏,它將會變成停止。

  停止:當一個Activity不是可視的,它“停止”了。這個Activity將仍然在記憶體中儲存它所有的狀態和會員資訊。儘管如此,當其它地方需要記憶體時,它將是最有可能被釋放資源的。當一個Activity停止後,一個很重要的步驟是要儲存資料和當前UI狀態。一旦一個Activity退出或關閉了,它將變為待用狀態。

  待用: 在一個Activity被殺死後和被裝在前,它是待用狀態的。待用Acitivity被移除Activity棧,並且需要在顯示和可用之前重新啟動它。

  activity的四種載入模式

  在android的多activity開發中,activity之間的跳轉可能需要有多種方式,有時是普通的生成一個新例項,有時希望跳轉到原來某個activity例項,而不是生成大量的重複的activity。載入模式便是決定以哪種方式啟動一個跳轉到原來某個Activity例項。

  在android裡,有4種activity的啟動模式,分別為:

  ·standard: 標準模式,一呼叫startActivity()方法就會產生一個新的例項。

  ·singleTop: 如果已經有一個例項位於Activity棧的頂部時,就不產生新的例項,而只是呼叫Activity中的newInstance()方法。如果不位於棧頂,會產生一個新的例項。

  ·singleTask: 會在一個新的task中產生這個例項,以後每次呼叫都會使用這個,不會去產生新的例項了。

  ·singleInstance: 這個跟singleTask基本上是一樣,只有一個區別:在這個模式下的Activity例項所處的task中,只能有這個activity例項,不能有其他的例項。

  這些啟動模式可以在功能清單檔案AndroidManifest.xml中進行設定,中的launchMode屬性。

四種載入模式的區別:

現在task棧元素為A-B-C-D(D在棧頂),這時候給D發一個啟動intent,如果D是
“standard”的,則生成D的一個新例項,棧變為A-B-C-D-D。
如果D是singleTop的話,則不會生產D的新例項,棧狀態仍為A-B-C-D
如果這時候給B發Intent的話,不管B的launchmode是”standard” 還是 “singleTop”,都會生成B的新例項,棧狀態變為A-B-C-D-B。
“singleInstance”是其所在棧的唯一activity,它會每次都被重用。
“singleTask” 如果在棧頂,則接受intent,否則,該intent會被丟棄,但是該task仍會回到前臺。
當已經存在的activity例項處理新的intent時候,會呼叫onNewIntent()方法,如果收到intent生成一個activity例項,那麼使用者可以通過back鍵回到上一個狀態;如果是已經存在的一個activity來處理這個intent的話,使用者不能通過按back鍵返回到這之前的狀態。

專案遇見這種坑

這裡寫圖片描述

參考了別人的資料後 http://blog.csdn.net/lizhiguo0532/article/details/7480993

有一個 Flag
Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
這個的意思是表示“如果這個activity已經啟動了,就不產生新的activity,而只是把這個activity例項加到棧頂“。
啟動時新增這個Flag就不會再出現上圖的那種情況了.

相關文章