編輯:Android開發實例
前言
本章內容為Android開發者指南的Framework Topics/Application Resources/Handling Runtime Changes章節,版本為Android 3.2 r1,翻譯來自:"CodeGuy"。
Handling Runtime Changes
譯者署名:CodeGuy
譯者鏈接:http://www.cnblogs.com/CodeGuy/
版本:Android 3.2 r1
原文
http://developer.android.com/guide/topics/resources/runtime-changes.html
處理運行時更改
一些設備配置在運行過程中可能會發生改變(例如屏幕橫向布局、鍵盤可用性和語言)。當這樣的變化發生時,Android會重新啟動這個正在運行的Activity(onDestroy()方法會被調用,然後調用onCreate()方法)。這個重啟的動作是為了通過自動往你的應用程序中載入可替代資源,從而使你的應用適應新的配置。
為了正確執行一次重啟,你的Activity在整個平凡的生命周期中重新保存它之前的狀態是很重要的,Android是通過在銷毀你的Activity之前調用onSaveInstanceState()方法來保存關於應用之前狀態的數據。然後你就可以在onCreate()方法或者onRestoreInstanceState()方法中重新保存應用的狀態了。為了測試你的應用可以通過應用的狀態原封不動地重啟自己,你應該給你的應用授權——當程序在執行不同的任務時應用的配置可以改變(例如屏幕的方向變化)。
為了處理一些事件,例如當用戶接聽一個打入的電話然後返回到你的應用程序中,在沒有丟失用戶數據或者狀態信息的情況下,你的應用應該具備在任何時候重啟自己的能力(更多參見Activity lifecycle)。
然而,你可能要面對這樣一個情景,重啟你的應用程序並重新保存大量有價值的數據會導致很差的用戶體驗。在這樣的情景面前,你有兩種選擇:
a. 在配置改變期間維持一個對象
當配置發生改變時允許你的Activity重啟,但讓其攜帶一個有狀態的對象到你的新Activity實例中。
b. 你自己來處理配置的變化
當某些配置發生變化的時候阻止系統重啟你的Activity,並且當配置改變時要接收一個回調,這樣你就可以根據需要來手動更新你的Activity。
在配置改變期間維持一個對象
如果重啟你的Activity,你需要恢復大量的數據,重新執行網絡連接,或者其他深入的操作,這樣由配置改變引起的一次完全啟動就會引起不好的用戶體驗。而且,僅有Activity生命周期中為你保存的的Bundle對象,你是不可能完全維護你的Activity的狀態的—不能傳遞很大的對象(如bitmap對象),並且這些對象裡面的數據必須序列化,然後解序列化,這些都需要消耗很多內存從而使配置改變得很慢。在這樣的情境下,當你的Activity由於配置發生改變而重啟時,你可以通過重新預置一個有狀態的對象來減緩你程序的負擔。
在運行期間配置改變時維護一個對象:
1. 重寫 onRetainNonConfigurationInstance() 方法來返回你想要維護的對象。
2. 當你的Activity再次創建時,調用getLastNonConfigurationInstance()方法恢復你的對象。
當你的Activity由於配置發生改變要關閉的時候,Android會在執行onStop()方法與onDestroy()方法之間調用onRetainNonConfigurationInstance()方法。為了在配置改變後更有效地保存狀態,在實現onRetainNonConfigurationInstance() 方法時你應該返回你所需要的一個對象。
這個場景的可貴之處在於當你的應用程序需要從網上下載很多數據的時候。如果用戶更改設備的方向並且Activity重啟,你的應用程序必須要重新載入數據,那就會很慢了。你需要做的就是實現onRetainNonConfigurationInstance() 方法並返回帶有你的數據的對象,然後當你的 Activity通過getLastNonConfigurationInstance()方法重啟時就能獲取數據。例如:
@Override
public Object onRetainNonConfigurationInstance() {
final MyDataObject data = collectMyLoadedData();
return data;
}
特別提醒:當你要返回任何對象的時候,你應該不要傳遞一個跟Activity有關聯的對象,例如一個Drawable對象,一個Adapter對象,一個View對象或者任何其他跟Context相關的對象 。如果你這樣做,它會洩漏原來Activity實例的所有視圖和資源。(洩漏資源意味著您的應用程序保持對他們的持有,他們不能被當做垃圾收集,因此內存就洩露了)
然後當你的Activity重啟時獲取數據:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final MyDataObject data = (MyDataObject) getLastNonConfigurationInstance();
if (data == null) {
data = loadMyData();
}
...
}
這個例子中,getLastNonConfigurationInstance()獲取了onRetainNonConfigurationInstance()方法中保存的數據。如果數據為空,(這種情況發生在,當Activity重啟是由其他原因而不是配置改變引起的)那麼程序將從原來的數據源載入數據對象 。
你自己來處理配置的變化
如果在某個特殊的配置發生改變的期間你的應用程序不需要更新資源,而且你有個操作限制需要你避免Activity的重啟,那麼你可以聲明使你自己的Activity來處理配置的變化,從而阻止系統重啟你的Activity。
特別提醒: 選擇自己來處理配置的變化會使得可替代資源的使用變得更困難,因為系統不會為你來自動調用這些資源。這種技術應該被視為最後的手段,對於大多數應用程序不建議使用。
為了聲明你的Activity來處理配置的變化,在清單文件中編輯正確的<activity>元素,包括賦好值的android:configChanges屬性,代表你要處理的配置。android:configChanges屬性所有可能的值都要在文檔中列出(最常用的值是:orientation來處理當屏幕的方向變化時,keyboardHidden來處理鍵盤可用性改變時)。你可以在屬性中聲明多個配置的值,通過“|”符號將它們分隔開。
例如,以下清單片段聲明了Activity中將同時處理屏幕的方向變化和鍵盤的可用性變化:
<activity android:name=".MyActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name">
當這些配置中的一個發生改變時,MyActivity不會重新啟動。相反,這個 Activity會接收onConfigurationChanged()方法的調用。這個方法傳遞一個Configuration類的對象來標識新的設備配置。通過讀取配置字段,你可以確定新的配置信息並通過更新你界面中使用的資源來正確應用這些改變。任何時候這個方法被調用,你的Activity的Resources對象會被更新並返回一個基於新配置的Resources對象,因此你可以在不用系統重啟你的Activity的情況下很容易地重置你的UI元素。
注意:從Android 3.2 (API level 13)開始,"screen size"也隨著設備的橫豎屏切換而改變。因此,如果你在API level 13或更高(minSdkVersion和targetSdkVersion屬性聲明)進行開發時,要防止因方向改變而重新啟動,你必須為" orientation
"添加"screen size"值。也就是說,你必須定義android:configChanges="orientation|screenSize"
。但是,如果你的應用程序目標
API level
為
12
或更低,你的
activity
總是要處理配置更改(配置更改沒有重新啟動你的
activty
,即使運行在
Android 3.2
或更高版本的設備)。
例如,接下來的onConfigurationChanged()方法中實現了檢查硬件鍵盤的可用性和當前設備的方向:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}
這個Configuration類的對象代表著當前所有的配置信息,不僅僅那些改變的配置信息。在很多時候,你不會確切地在乎這些配置是怎麼改變的,並且可以簡單地重新分配所有資源,提供您正在處理的配置的可替代資源。例如,因為這個Resources對象現在被更新,你可以通過setImageResource(int)方法重置任何ImageView,並重置恰當的資源給當前配置使用。(詳見:Providing Resources)
請注意,配置字段的值是一些匹配Configuration類裡特定的常量的整數。對於文檔中的每個字段使用那個常量,請在Configuration類中參閱相應的字段。
記住:當你聲明你的Activity來處理配置的變化時,你負責重置所有你提供可替代資源的元素 。如果你聲明你的Activity來處理屏幕方向的改變並具有在橫向和縱向之間切換的圖像,你必須在onConfigurationChanged()方法中給每個元素重新指定一個資源。
如果你不需要根據配置的變化來更新你的程序,你可以不實現onConfigurationChanged()方法。在這種情況下,所有在配置改變之前使用的資源仍然會被使用,並且你只需要避免你的Activity被重啟。然而,您的應用程序應該始終能夠關閉並從其之前的狀態完好地重新啟動。這不僅是因為存在有一些配置發生改變時你不能防止它重新啟動您的應用程序,而且為了處理一些事件,例如當用戶接收了電話然後返回到應用程序。
更多關於哪些配置變化時你可以在你的Activity中處理,參見android:configChanges文檔和Configuration類。
andriod短信整合備份發送到gmail郵箱,需要在andoid手機配置好gmail郵箱 github代碼 https://github.com/zhwj184
Android應用程序可以在許多不同地區的許多設備上運行。為了使應用程序更具交互性,應用程序應該處理以適合應用程序將要使用的語言環境方面的文字,數字,文件等。在本章中,我
本文實例講述了Android編程學習之異步加載圖片的方法。分享給大家供大家參考,具體如下: 最近在android開發中碰到比較棘手的問題,就是加載圖片內存溢出。我
在Activity中覆寫下面兩個方法:代碼如下: // 創建菜單 @Override public boo