編輯:關於Android編程
先來看看官方給出的聲明周期圖:
這裡需要說明如下幾點:
很多時候我們的activity可能會由於系統資源的緊缺被系統殺死,或者系統配置發生變化等
如果當前activity從橫屏直接旋轉到豎屏,此時由於系統配置發生了變化,在默認情況下,activity就會被銷毀並重新創建。
當系統配置發生變化之後,activity會被銷毀,其onPause,onStop,onDestroy均會被回調,同時由於activity是在異常情況下終止的,系統會回調onSaveInstanceState來保存當前activity的狀態。onSaveInstanceState是在onStop之前調用的,onRestoreInstanceState是在onStart之後調用的
我們來看下面的栗子:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 這裡當activity正常啟動的時候,savedInstanceState是null,所以需要做非空判斷 if (null != savedInstanceState) { String str = savedInstanceState.getString("killedStr"); Log.d(TAG,"onCreate runs...str is :"+str); } } /** * 當activity被銷毀,並重新創建時候,回調該方法獲取之前保存的數據 */ @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); Log.d(TAG,"onRestoreInstanceState runs..."); String str = savedInstanceState.getString("killedStr"); savedInstanceState.putString("killedStr","testString"); Log.d(TAG,"onRestoreInstanceState runs...str is :"+str); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); Log.d(TAG,"onSaveInstanceState runs..."); outState.putString("killedStr","testString"); } }
可以看到,我們可以同時在onRestoreInstanceState和onCreate中獲取之前保存的數據,區別在於在onRestoreInstanceState方法中,其參數一定不是null,而在onCreate中,如果當前activity正常啟動的時候,其參數為null
onSaveInstanceState方法,系統只會在Activity即將被銷毀,並且有機會重新顯示的情況下才會去調用它
通常情況下我們的activity可以分為下面三種優先級:
前台activity,表示正在和用戶進行交互的activity 可見但非前台activity。 後台activity需要注意到的是,在sdkversion > 13時候,為了防止旋轉屏幕activity重啟,除了orientation還需要添加screenSize
activity有四種啟動模式:
standard默認情況下,所有的activity所需要的任務棧的名字為當前的包名,我們可以單獨為每個activity指定TaskAffinity屬性,TaskAffinity屬性主要和singleTask啟動模式或者allowTaskReparenting配對使用。
當TaskAffinity和singleTask啟動模式配對使用的時候,此時待啟動的singleTask模式的activity所在的任務棧,和TaskAffinity是相同的。 當TaskAffinity和allowTaskReparenting結合使用的時候,當一個應用A啟動了應用B的某一個activity,如果B的allowTaskReparenting屬性為true,那麼當應用B被啟動以後,此activity會直接從應用A的任務棧轉移到應用B的任務棧中。我們可以分別在代碼中或者AndroidManifest.xml裡為activity指定啟動模式。
// 在AndroidManifest.xml中指定 android:launchMode="singleTask" // 在代碼中指定,優先級較高 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// 為MainActivity指定啟動模式為singleTask @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.id_text).setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { Intent intent = new Intent(MainActivity.this,MainActivity.class); MainActivity.this.startActivity(intent); } }); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); Log.d(TAG,"onNewIntent runs...."); } @Override protected void onPause() { super.onPause(); Log.d(TAG,"onPause runs...."); } @Override protected void onResume() { super.onResume(); Log.d(TAG,"onResume runs...."); }
此時我們連續點擊三次,啟動當前MainActivity。
此時由於我們指定當前MainActivity的啟動模式為singleTask,所以在默認的棧中,只有一個MainActivity實例,所以此時我們雖然啟動了三次,但是按下back鍵盤的時候,會直接返回到桌面。
通過adb shell dumpsys activity 來查看當前的activity和其任務棧
現在我們為MainActivity去掉singleTask,做相同的操作。
我們都知道,隱式啟動一個activity時候,就需要匹配當前activity的IntentFilter設置,如果匹配不成功,將無法啟動目的activity,IntentFilter中設置的過濾信息有action,category,data。
為了匹配過濾列表,需要同時匹配action,category,data信息,否則會匹配失敗,只有一個intent同時匹配action類別,category類別,data類別才算完全匹配,另外一個activity可能有多個intent-filter,一個intent只要能夠匹配任何一組intent-filter即可以成功啟動對應的activity
一個過濾規則中可以有多個action,只要intent中的action只要能夠和其中的一個action相同即可匹配成功。action的匹配而規則要求intent中的action存在且必須和過濾規則中的一個action相同。
我們的代碼中可以沒有category,但是XML中要加上”android.intent.category.DEFAULT”這句。
如果你在代碼中定義了一個或者多個category,那麼你必須跟XML文件中定義的一樣。比如你定義了一個category,那麼要在XML文件中匹配到一個,,如果你定義了多個category,那麼要在XML文件中全部匹配
data的匹配規則和action類似,它也要intent中必須含有data數據,並且data數據能夠完全匹配過濾規則中的某一個data,這裡的完全匹配是指過濾規則中出現的data部分也出現在了Intent的data中。
如果要為intent指定完整的data,必須要調用setDataAndType方法,因為setData和setType方法中,會彼此清除掉對方設置的值
如果我們使用intent匹配了一個activity,並且會啟動當前的activity,那麼如果當前的activity不存在即匹配失敗的話,就會出現ActivityNotFoundException這樣的錯誤。
我們可以采用PackageManager的resolveActivity或者intent的resolveActivity方法,如果找不到匹配的activity,就會返回null,我們通過返回值可以規避上面的錯誤。
另外PackageManager還提供了queryIntentActivities方法,這個方法和resolveActivity不同之處在於:它返回的不是最佳匹配的activity,而是所有成功匹配的activity。
public abstract ListqueryIntentActivities(Intent intent,int flags); public abstract ResolveInfo resolveActivity(Intent intent,int flags);
上面兩個方法第二個參數,使用時候需要注意,我們需要使用MATCH_DEFAULT_ONLY這個標記為,該標記為的含義是僅僅匹配在intent-filter中聲明了
這樣的activity。這樣做的好處在於只要上面兩個方法返回值不是null,則startActivity一定可以成功。
ok,今天就到這裡了,本篇博客來自android開發藝術探索的學習筆記。
把Android SDK升級到了最新版本,但是Eclipse的ADT插件需要Eclipse3.6版本以上才可以安裝,無奈下載了Eclipse3.7版本的。一
本節引言: 最近一段時間因為工作上的事以及面試等等,耽誤了博客的更新,這裡道歉下~ 今天下午去追夢網絡面試了一趟,全齊大神給小弟我上了一課,增長了
如果我們在文件浏覽器中點擊一個文件,然後點擊它,會彈出一個列表給你選擇 如果使自己的應用也出現在這個列表上,必須在menifest的這個act
過濾操作符3.1 filter符合某種規則的Observable才會向下傳遞,例子 Observable.range(100,10).filter(new Fun