關於轉屏,與activity狀態的儲存onRetainNonConfigurationInstance()

來源:互聯網
上載者:User

關於轉屏,與activity狀態的儲存

比較onSaveInstanceState() 與 onRetainNonConfigurationInstance()在不同需求中的用法

針對Android平台,不論出於哪種目的,都或多或少需要在多個Activities中的跳轉操作,其中包括為了獲得某些系統資源和必要資訊,而通過啟動(startActivity()&startActivityForResult() )Child Activity來提供一個選取器或者作為使用者輸入資訊的介質。這期間父級Activity將暫時性失去焦點,從而在這之前先通過 onSaveInstanceState() 方法臨時儲存一些必要的資訊,當父級的Activity重新成為當前焦點後,系統將觸發 onRestoreInstanceState() 恢複失去焦點前的原有資料!onRetainNonConfigurationInstance()也具有相同的目的來處理類似的請求,其主要是由於旋轉裝置而更改顯示模式,進而觸發這個方法的調用。

那麼在遇到某些特定需求時,特別是針對裝置旋轉後所導致的顯示模式發生變化後,應該依據什麼條件來判斷應用哪種方式才能更好的滿足需要呢?做出選擇之前有必要分別瞭解兩種方法的各自特點。

onSaveInstanceState()

在當前的Activity中通過新的Intent啟動其它Activities之後,它將通過這個方法自動儲存自身的資料,當再次出返回時可以通過 onRestoreInstanceState()複原資料。另外一種情況也將調用這個方法,當旋轉裝置後螢幕顯示模式發生改變時。需要注意的一點是整個過程完全由系統控制,無法通過onSaveInstanceState()返回一個自訂的資料。

另外,onSaveInstanceState()在所有Activity destroying過程中被調用,它僅僅是為了在重新回到這個特定的Activity之後,依據Activity state重新建立一個與之前狀態完全相同的Activity。例如:當我們啟動某些Connection時,State並不能依然儲存這個串連狀態。所以當調用onSaveInstanceState後,所有當前的connection將一同銷毀。當第二次通過 onRestoreInstanceState()找回之前的串連設定並重建立立新的串連實體。

如果大家有更多的發現,或者有不用於以上的驗證結果,非常感謝能參與這個話題的討論。

onRetainNonConfigurationInstance()

當Device configuration發生改變時,將伴隨Destroying被系統調用。通過這個方法可以像onSaveInstanceState()的方法一樣保留變化前的Activity State,最大的不同在於這個方法可以返回一個包含有狀態資訊的Object,其中甚至可以包含Activity Instance本身。新建立的Activity可以繼承大量來至於Parent Activity State資訊。

用這個方法儲存Activity State後,通過getLastNonConfigurationInstance()在新的Activity Instance中恢複原有狀態。

這個方法最大的好處是:

* 當Activity曾經通過某個網路資源得到一些圖片或者視頻資訊,那麼當再次恢複後,無需重新通過原始資源地址擷取,可以快速的載入整個Activity狀態資訊。

* 當Activity包含有許多線程時,在變化後依然可以持有原有線程,無需通過重新建立進程恢複原有狀態。

* 當Activity包含某些Connection Instance時,同樣可以在整個變化過程中保持串連狀態。

下邊是需要特別注意的幾點:

* onRetainNonConfigurationInstance()在onSaveInstanceState()之後被調用。
* 調用順序同樣介於onStop() 和 onDestroy()之間。

接下來將通過一個例子來簡單瞭解onRetainNonConfigurationInstance()和getLastNonConfigurationInstance()的用法。

這個例子將首先啟動一個包含兩個按鈕的Activity。其中一個按鈕用於調用本地通訊錄,並將所選擇的某一項作為傳回值傳給當前 Activity。另外一個按鈕的作用是查看當前所選擇的通訊資訊。正常的流程是當第一次啟動程式後,第二個查看資訊按鈕是不可用狀態。當通過Pick按鈕確定選擇並返回某一通訊錄內容時,查看資訊按鈕的狀態切換為可操作狀態。然後當改變裝置的Configuration時,可以注意到即便是 Activity通過onCreate()重新構建,但是之前所保證的UI屬性依然保持最後一次操作的狀態。

簡單建立一個包含兩個按鈕的UI:
?View Code XML

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
>
<Button android:id="@+id/pick"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_weight="1"
    android:text="Pick"
    android:enabled="true"
/>
<Button android:id="@+id/view"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_weight="1"
    android:text="View"
    android:enabled="false"
/>
</LinearLayout>;

程式入口主程式碼如下所示(例子中包含了如何調用系統通訊錄的方法):

package com.androidres.karka;

   import android.app.Activity;
   import android.content.Intent;
   import android.net.Uri;
   import android.os.Bundle;
   import android.view.View;
   import android.widget.Button;
   import android.util.Log;
   import android.provider.Contacts.People;

public class KarKa extends Activity {
static final int PICK_REQUEST=1337;
Button viewButton=null;
Uri contact=null;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

Button btn=(Button)findViewById(R.id.pick);

btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent i=new Intent(Intent.ACTION_PICK,
People.CONTENT_URI);

startActivityForResult(i, PICK_REQUEST);
}
});

viewButton=(Button)findViewById(R.id.view);

viewButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
startActivity(new Intent(Intent.ACTION_VIEW, contact));
}
});

restoreMe();

viewButton.setEnabled(contact!=null);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode==PICK_REQUEST) {
if (resultCode==RESULT_OK) {
contact=data.getData();
viewButton.setEnabled(true);
}
}
}

@Override
public Object onRetainNonConfigurationInstance() {
return(contact);
}

private void restoreMe() {
contact=null;

if (getLastNonConfigurationInstance()!=null) {
contact=(Uri)getLastNonConfigurationInstance();
}
}
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.