android基礎--活動任務堆疊
如果你的應用中涉及到的東西比較耗記憶體的話,比如:相機、第三方地圖、騰訊、新浪、錄音、視訊播放、大量圖片時,如果這些東西同時存在於應用中時,會有很多奇怪的問題出現,自動退出還不報錯等等一系列的問題,還有,如果我們的應用中使用startActivity()過多而且並沒有及時finish()掉的話,也會出現這樣那樣的問題,比如:退出應用時沒有退出乾淨,或者莫名其妙的報OOM,啟動的服務自動掛起什麼的!
其實,Google已經提供了一套完整的機制讓開發人員控制活動棧與任務棧,結合如下程式碼:(我會以最簡單的程式碼來說明實際開發中遇到的問題處理,不足之外,請大家直接指出批評,有錯必改!)
首先:我們來啟動三個Activity來模擬生成活動與任務堆疊,三個Activity分別是:AndroidStackTaskActivity1、AndroidStackTaskActivity2、AndroidStackTaskActivity3,具體程式碼如果下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
package com.xiaoma.www;
import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button;
/** * @Title: AndroidStackTaskActivity.java * @Package com.xiaoma.www * @Description: 活動、任務堆疊學習 * @author XiaoMa */ public class AndroidStackTaskActivity1 extends Activity implements OnClickListener { private Button next = null ;
/** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); init(); }
private void init() { next = (Button)findViewById(R.id.button1); next.setOnClickListener(this); }
@Override public void onClick(View v) { // TODO Auto-generated method stub Intent i = new Intent(this,AndroidStackTaskActivity2.class); startActivity(i); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
package com.xiaoma.www;
import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button;
/** * @Title: AndroidStackTaskActivity2.java * @Package com.xiaoma.www * @Description: 活動、任務堆疊學習 * @author XiaoMa */ public class AndroidStackTaskActivity2 extends Activity implements OnClickListener { private Button next = null ;
/** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main2); init(); }
private void init() { next = (Button)findViewById(R.id.button1); next.setOnClickListener(this); }
@Override public void onClick(View v) { // TODO Auto-generated method stub Intent i = new Intent(this,AndroidStackTaskActivity3.class); startActivity(i); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
package com.xiaoma.www;
import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button;
/** * @Title: AndroidStackTaskActivity2.java * @Package com.xiaoma.www * @Description: 活動、任務堆疊學習 * @author XiaoMa */ public class AndroidStackTaskActivity3 extends Activity implements OnClickListener { private Button next = null ;
/** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main2); init(); }
private void init() { next = (Button)findViewById(R.id.button1); next.setOnClickListener(this); }
@Override public void onClick(View v) { // TODO Auto-generated method stub Intent i = new Intent(this,AndroidStackTaskActivity3.class); startActivity(i); } } |
程式碼很簡單, 大家不用看執行效果也可以想出什麼情況 ,不過這個地方主要看堆疊,不看這些程式碼,貼在這裡供大家搞清楚三個Activity的啟動順序,此時,生成的活動堆疊如下圖所示:
這個地方說明下,有時候大家可以想著從1到2時可以繫結資料完成回顯,但是如果要簡單的回顯用繫結或startActivityForResult()這兩種方式啟動,但是如果涉及到三個以上的活動惑更多活動之間的跳轉時,有時候不得不必須重新啟動新的活動,也就出現了前面的1>>2>>3>>4>>>>>>>甚至更多的活動跳轉,這樣一個個關閉有時候還是關不乾淨,應用退出的時候也還是不乾淨的,更搞笑的是有時候還有使用者在多個活動之間跳轉並不進行任何資料操作時還要求返回上一個Activity時你就不能直接finish掉上一個Activity,不然人家說你跳轉不對,針對這個問題我們來看下Google提供的堆疊任務控制機制吧,很簡單,用Flag來控制,這個時候就有個問題,提供的方法有setFlag()、addFlag(),這兩個肯定有什麼區別的,不然不會出現兩個控制Flag的方法的,繼續….先看下如下兩種效果:
第一種:未設定Flag時
第二種 :已設定Flag時
如上所示,大家應該看出來了,同樣點選了六次按鈕之後按的返回鍵,第一種效果必須點選六次Back鍵後方可退出,而第二種效果只點擊一次即可退出,這就是Flag的魅力,激動….再來看Flag都有哪幾種吧,此處我列在這個地方,上面兩個效果中設定的是:i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);另外還有很多可以控制活動堆疊與任務棧的Flag,小馬在這個地方隨便列出兩個,剩餘的Flag值以截圖的形式顯示,節約時間:
- i.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
- i.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)其它:
大家可以很清楚的看到以後所含的標誌中有針對於TASK的,對吧?指的就是任務堆疊,至於什麼是任務堆疊,大家不用太過糾結於與活動堆疊之間的概念什麼的,只記住一點:如果你在應用中啟動Activity的時候沒加任務堆疊的控制Flag時,開發環境肯定報錯,而且提示的很準確 ,就是:你缺少新增任務堆疊Flag標誌位,具體少了哪個標誌,開發環境也會很準確的指出,必須要你新增才可正常編譯通過!下面列下小馬犯的錯誤,就是在一個Activity找到一個amr錄音檔案,直接以下面的方式啟動去播放錄音,猛報錯:
1 |
Intent i = new Intent(Intent.ACTION_VIEW); |
1 |
i.putExtra("filePath",path); |
1 |
startActivity(i); |
如果加了 i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);操作下任務堆疊就可以了,具體的原因,也可以用一句話來總結:如果在一個Activity中同一時間,要操作不用的功能,比如:跳轉時還要操作視訊錄音檔案的播放什麼的,都得設定新的任務棧來啟動開啟,如果不啟動新任務棧的話,有時候會無原無故的顯示空白還不報錯!上面的錯只是一個小點,小到可以忽略不講,寫在這是提醒大家,該加的時候必須加Flag,至於什麼時候加,大家可以參照下官方的文件及下面小馬貼出的官方文件中解釋堆疊的圖解,加以理解學習,如下所示:
Figure2:不多解釋,就是在A B 丙個任務堆疊,如果使用者正在於B任務堆疊進行互動時,A在等待喚醒,反之則反
Figure3: 下面這個就好玩了,學習了下官方的文件,講的是:無論啟動了一個新的任務堆疊或者在同一堆疊中來啟動一個活動,按返回鍵也還是會返回到使用者之前操作的Activity,如果以單例堆疊(類似單位模式)載入的話,就會在後臺生成一個針對於此活動的單獨的一個任務堆疊,當這個任務堆疊被喚醒到前臺時,此時的返回堆疊中就包含了從前幾個任務傳遞過來的棧頂的所有Activity,棧頂與棧底的顯示關係如果下圖:
這個地方順帶著講下,在控制活動堆疊時方式只有一種,就是直接在.java檔案中setFlag,如果是控制任務堆疊的話可以以addFlag或直接在全域性配置檔案中新增配置的方式來控制,大家可以直接在AndroidManifest.xml檔案中activity節點中新增哪下屬性:taskAffinity、launchMode、allowTaskReparenting、clearTaskOnLaunch、alwaysRetainTaskState、finishOnTaskLaunch,兩種控制任務堆疊的方式換湯不換藥,大家看個人習慣選擇使用就可以了…切記,用的時候一定搞清楚你要加的標誌位是什麼意思,不要看到個task就addFlag,設定Flag是為了讓應用更乾淨,控制更嚴密,如果加錯了標誌位,應用是不會報任何錯的,只是出現怪異的跳轉與關閉!!!