Android中InstanceState()使用詳解

    本文介紹Android中關於Activity的兩個神祕方法:onSaveInstanceState() 和 onRestoreInstanceState(),而且在介紹這兩個方法以後,再分別來實現使用InstanceState保存和恢復數據功能、Android實現屏幕旋轉異步下載效果這樣兩個示例。前端

  首先來介紹onSaveInstanceState() 和 onRestoreInstanceState() 。關於這兩個方法,一些朋友可能在Android開發過程當中不多用到,但在有時候掌握其用法會幫咱們起到比較好的效果。尤爲是在應用程序在不知道的狀況下退出後,如何實現其數據保存的功能。先來讓咱們看下這兩個方法的有什麼樣的做用。
 java

  1. 基本做用: android

  Activity的 onSaveInstanceState() 和 onRestoreInstanceState()並非生命週期方法,它們不一樣於 onCreate()、onPause()等生命週期方法,它們並不必定會被觸發。當應用遇到意外狀況(如:內存不足、用戶直接按Home鍵)由系統銷燬一個Activity時,onSaveInstanceState() 會被調用。可是當用戶主動去銷燬一個Activity時,例如在應用中按返回鍵,onSaveInstanceState()就不會被調用。由於在這種狀況下,用戶的行爲決定了不須要保存Activity的狀態。一般onSaveInstanceState()只適合用於保存一些臨時性的狀態,而onPause()適合用於數據的持久化保存。
 數據庫

  在activity被殺掉以前調用保存每一個實例的狀態,以保證該狀態能夠在onCreate(Bundle)或者onRestoreInstanceState(Bundle) (傳入的Bundle參數是由onSaveInstanceState封裝好的)中恢復。這個方法在一個activity被殺死前調用,當該activity在未來某個時刻回來時能夠恢復其先前狀態。 緩存

 

  例如,若是activity B啓用後位於activity A的前端,在某個時刻activity A由於系統回收資源的問題要被殺掉,A經過onSaveInstanceState將有機會保存其用戶界面狀態,使得未來用戶返回到activity A時能經過onCreate(Bundle)或者onRestoreInstanceState(Bundle)恢復界面的狀態。app

 

  關於onSaveInstanceState (),是在函數裏面保存一些View有用的數據到一個Parcelable對象並返回。在Activity的onSaveInstanceState(Bundle outState)中調用View的onSaveInstanceState (),返回Parcelable對象,框架

  接着用Bundle的putParcelable方法保存在Bundle  savedInstanceState中。異步

 

  當系統調用Activity的的onRestoreInstanceState(Bundle savedInstanceState)時, 同過Bundle的getParcelable方法獲得Parcelable對象,而後把該Parcelable對象傳給View的onRestoreInstanceState (Parcelable state)。在的View的onRestoreInstanceState中從Parcelable讀取保存的數據以便View使用。ide

 

  這就是onSaveInstanceState() 和 onRestoreInstanceState() 兩個函數的基本做用和用法。函數

 

  2. onSaveInstanceState() 何時調用 

  先看Application Fundamentals上的一段話:

  Android calls onSaveInstanceState() before the activitybecomes vulnerable to being destroyed by the system, but does not bothercalling it when the instance is actually being destroyed by a user action (suchas pressing the BACK key).

 

  從這句話能夠知道,當某個activity變得"容易"被系統銷燬時,該activity的onSaveInstanceState()就會被執行,除非該activity是被用戶主動銷燬的,例如當用戶按BACK鍵的時候。

 

  注意上面的雙引號,何爲"容易"?意思就是說該activity尚未被銷燬,而僅僅是一種可能性。這種可能性有哪些?經過重寫一個activity的全部生命週期的onXXX方法,包括onSaveInstanceState()和onRestoreInstanceState() 方法,咱們能夠清楚地知道當某個activity(假定爲activity A)顯示在當前task的最上層時,其onSaveInstanceState()方法會在何時被執行,有這麼幾種狀況:

 

  (1)、當用戶按下HOME鍵時。

  這是顯而易見的,系統不知道你按下HOME後要運行多少其餘的程序,天然也不知道activity A是否會被銷燬,所以系統會調用onSaveInstanceState(),讓用戶有機會保存某些非永久性的數據。如下幾種狀況的分析都遵循該原則

 

  (2)、長按HOME鍵,選擇運行其餘的程序時。

 

  (3)、按下電源按鍵(關閉屏幕顯示)時。

 

  (4)、從activity A中啓動一個新的activity時。

 

  (5)、屏幕方向切換時,例如從豎屏切換到橫屏時。

 

  在屏幕切換以前,系統會銷燬activity A,在屏幕切換以後系統又會自動地建立activity A,因此onSaveInstanceState()必定會被執行,且也必定會執行onRestoreInstanceState()。

 

  總而言之,onSaveInstanceState()的調用遵循一個重要原則,即當系統存在「未經你許可」時銷燬了咱們的activity的可能時,則onSaveInstanceState()會被系統調用,這是系統的責任,由於它必需要提供一個機會讓你保存你的數據(固然你不保存那就隨便你了)。若是調用,調用將發生在onPause()或onStop()方法以前。(雖然測試時發現多數在onPause()前)

 

  3. onRestoreInstanceState()何時調用 

  onRestoreInstanceState()被調用的前提是,activity A「確實」被系統銷燬了,而若是僅僅是停留在有這種可能性的狀況下,則該方法不會被調用,例如,當正在顯示activity A的時候,用戶按下HOME鍵回到主界面,而後用戶緊接着又返回到activity A,這種狀況下activity A通常不會由於內存的緣由被系統銷燬,故activity A的onRestoreInstanceState方法不會被執行 此也說明上兩者,大多數狀況下不成對被使用。

 

  onRestoreInstanceState()在onStart() 和 onPostCreate(Bundle)之間調用。

 

  4. onSaveInstanceState()方法的默認實現

  若是咱們沒有覆寫onSaveInstanceState()方法, 此方法的默認實現會自動保存activity中的某些狀態數據, 好比activity中各類UI控件的狀態.。android應用框架中定義的幾乎全部UI控件都恰當的實現了onSaveInstanceState()方法,所以當activity被摧毀和重建時, 這些UI控件會自動保存和恢復狀態數據. 好比EditText控件會自動保存和恢復輸入的數據,而CheckBox控件會自動保存和恢復選中狀態.開發者只須要爲這些控件指定一個惟一的ID(經過設置android:id屬性便可), 剩餘的事情就能夠自動完成了.若是沒有爲控件指定ID, 則這個控件就不會進行自動的數據保存和恢復操做。

 

  由上所述, 若是咱們須要覆寫onSaveInstanceState()方法, 通常會在第一行代碼中調用該方法的默認實現:super.onSaveInstanceState(outState)。

 

  5. 是否須要重寫onSaveInstanceState()方法 

  既然該方法的默認實現能夠自動的保存UI控件的狀態數據, 那何時須要覆寫該方法呢? 

 

  若是須要保存額外的數據時, 就須要覆寫onSaveInstanceState()方法。你們須要注意的是:onSaveInstanceState()方法只適合保存瞬態數據, 好比UI控件的狀態, 成員變量的值等,而不該該用來保存持久化數據,持久化數據應該當用戶離開當前的 activity時,在 onPause() 中保存(好比將數據保存到數據庫或文件中)。說到這裏,還要說一點的就是在onPause()中不適合用來保存比較費時的數據,因此這點要理解。

 

  因爲onSaveInstanceState()方法方法不必定會被調用, 所以不適合在該方法中保存持久化數據, 例如向數據庫中插入記錄等. 保存持久化數據的操做應該放在onPause()中。如果永久性值,則在onPause()中保存;若大量,則另開線程吧,別阻塞UI線程。 

 

  6. 引起activity銷燬和重建的其它狀況

  除了系統處於內存不足的緣由會摧毀activity以外, 某些系統設置的改變也會致使activity的摧毀和重建. 例如改變屏幕方向(見上例), 改變設備語言設定, 鍵盤彈出等。

 

  另外,當屏幕的方向發生了改變, Activity會被摧毀而且被從新建立,若是你想在Activity被摧毀前緩存一些數據,而且在Activity被從新建立後恢復緩存的數據。能夠重寫Activity的 onSaveInstanceState() 和 onRestoreInstanceState()方法,以下代碼所示:

package com.code.test; 

import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

/**
 * Android使用InstanceState保存和恢復數據
 * @Description: Android使用InstanceState保存和恢復數據

 * @File: MyTestCodeActivity.java

 * @Package com.code.test

 * @Author Hanyonglu

 * @Date 2012-03-28 下午04:53:15

 * @Version V1.0
 */
public class MainActivity extends Activity {
    private String message = "";
    private EditText text = null;
    private Button button = null;
 
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        text = (EditText) findViewById(R.id.editText1);
        button = (Button) findViewById(R.id.btnSave);
        
        button.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
                Toast.makeText(getApplicationContext(), "保存", Toast.LENGTH_SHORT).show();
            }
        });
    }
 
    @Override
    public void onResume(){
        super.onResume();
        Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
    }
 
    @Override
    public void onSaveInstanceState(Bundle savedInstanceState){
        super.onSaveInstanceState(savedInstanceState);
        savedInstanceState.putString("message", text.getText().toString());
    }
 
    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState){
        super.onRestoreInstanceState(savedInstanceState);
        message = savedInstanceState.getString("message");
    }
}

        還有須要注意的是, onSaveInstanceState()方法並非必定會被調用的, 由於有些場景是不須要保存狀態數據的。 好比用戶按下BACK鍵退出activity時, 用戶顯然想要關閉這個activity, 此時是沒有必要保存數據以供下次恢復的, 也就是onSaveInstanceState()方法不會被調用。若是調用onSaveInstanceState()方法,調用將發生在onPause()或onStop()方法以前。

        代碼以下所示:

@Override
    public void onSaveInstanceState(BundlesavedInstanceState) {
        savedInstanceState.putBoolean("MyBoolean", true);
        savedInstanceState.putDouble("myDouble", 1.9); 
        // etc.
        super.onSaveInstanceState(savedInstanceState);
    }

    @Override
    public void onRestoreInstanceState(BundlesavedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        boolean myBoolean =savedInstanceState.getBoolean("MyBoolean");
        double myDouble =savedInstanceState.getDouble("myDouble");
    }

        以上就是在Android中關於InstanceState保存數據和恢復數據的過程,在這裏我想再重複一遍:onSaveInstanceState()和onRestoreInstanceState()機制來保存數據時,它僅在非用戶顯式的指令殺死應用程序時保存和恢復數據。咱們可使用它在咱們的程序中來保存數據,能夠做爲保存數據的一種方式,但在使用過程當中須要注意其使用原理和方法。

相關文章
相關標籤/搜索