1. 程式人生 > >activity使用Intent頻繁切換導致記憶體溢位:dequeue native buffer fail:Out of memory

activity使用Intent頻繁切換導致記憶體溢位:dequeue native buffer fail:Out of memory

兩個activity,activity中並沒有複雜的ui操作,也沒有執行子執行緒,但是在真機測試的時候,頻繁地進行切換,就會報記憶體溢位錯誤,如下:

<SwapBuffers:886>:dequeue native buffer fail:Out of memory
<GetSurfaceSize:387>:dequeue native buffer failed:Out of memory

跳轉流程是:Activity1通過Intent跳轉到Activity2,Activity2再通過Intent跳轉到Activity1。大約連續操作7-9次,就會報錯。

測試過程中發現如果Activity2使用返回鍵的onBackPress()方法進行返回,就不會報錯,也就是說可以肯定的是Intent出了問題。直觀感覺,有點像一個Activity不斷地在被例項,卻一直沒有被釋放。

後來查到Activity的啟動模式,將AndroidManifest.xml中的activity加上android:launchMode="singleTask"就對了,如下:

<activity
            android:name="com.example.main.Activity1"
            android:screenOrientation="portrait"
            android:launchMode="singleTask"
            android:theme="@style/common_title_bar">
        </activity>
關於android的launchMode,在網上查了相關的資料,整理如下,內容出處:http://www.cnblogs.com/ok-lanyan/articles/2593782.html

在Android的中Activity有4種啟動方式:"standard"、"singleTop"、"singleTask"、"singleInstance"。

1、standard啟動方式
這種方式也是系統預設的。說的簡單點,我們在使用startActivity()方法的時候,系統就會啟動一個新的Activity例項,不管它先前啟動沒有。如果想知道具體細節可以檢視這個帖子http://marshal.easymorse.com/archives/2950

,我在這裡就不細細講解了。


2、singleTop啟動方式
如果大家把standard啟動方式看懂了,這個我就說一下區別,大家就明白了。如果我們要呼叫的Activity在Task棧頂,系統不會像在standard方式下建立一個新的例項,而是呼叫onNewIntent()方法,來引導intent到棧頂的例項。如果呼叫的Activity不在Task棧頂,系統此時呼叫方式與standard方式下的一模一樣。
舉個例子:
現在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。


注意:在一個Activity處理新的intent的時候,使用者不能使用Back button來返回到先前的Activity。直到新的intent到達onNewIntent()方法中後,才可以。

3、singleTask啟動方式


如果已經有其他的Task並且包含Activity例項,那就直接呼叫那個Task的例項。(只有一個Task中會有) 而不是建立一個新的例項。重點:假如你啟動一個singleTask的Activity,同時這個Activity在background task中,那麼整個background task都會被調入到前臺來。


有人問如果我呼叫圖中的Activity X,會怎樣?系統會先把Activity Y銷燬,然後再將Activity X放到前臺。

4、singleInstance啟動方式

singleInstance 新建一個Task,且在該Task中只有它的唯一一個例項。 (只有一個Task會有,且該Task中只有它)。“singleInstance”是其所在棧的唯一activity,它會每次都被重用。

總結:

standard  每次都會新建,每個Task都可以有,且每個Task都可以有多個例項(每個Task都可以有,且可以有多個)
singleTop 當前例項如果在棧頂,就不新建例項,呼叫其OnNewIntent。 如不在棧頂,則新建例項 (每個Task都可以有,且可以有多個,在棧頂時可複用)
singleTask 新建一個Task,如果已經有其他的Task並且包含該例項,那就直接呼叫那個Task的例項。(只有一個Task中會有)
singleInstance 新建一個Task,且在該Task中只有它的唯一一個例項。 (只有一個Task會有,且該Task中只有它)

intent的flag可以覆蓋activity的啟動模式:
FLAG_ACTIVITY_NEW_TASK  類似singleTask
FLAG_ACTIVITY_SINGLE_TOP 類似singleTop 
FLAG_ACTIVITY_CLEAR_TOP 無對應

補充說明裡面遺漏的東西。

使用者一定要能夠離開一個task,和再回到這個task。所以,"singleTask"和"singleInstance",只能用作啟動Activity的屬性。如果不這樣,我們在啟動一個singleTask的Activity之後,使用Home鍵到主介面,就會回不去了,因為它不代表一個應用的啟動。