view的onSaveInstanceState和onRestoreInstanceState


from : http://blog.csdn.net/hudashi/article/details/6932784


viewonSaveInstanceStateonRestoreInstanceState
View文档中对其的说明如下:
protected void onRestoreInstanceState (Parcelable state)
Since: API Level 1
Hook allowing a view to re-apply a representation of its internal state that had previously 
been generated by onSaveInstanceState(). This function will never be called with a null state.
Parameters
state  The frozen state that had previously been returned by onSaveInstanceState().
See Also
    * onSaveInstanceState()
    * restoreHierarchyState(SparseArray)
    * dispatchRestoreInstanceState(SparseArray)
protected Parcelable onSaveInstanceState ()
Since: API Level 1
Hook allowing a view to generate a representation of its internal state 
that can later be used to create a new instance with that same state. 
This state should only contain information that is not persistent or can not be reconstructed later. 
For example, you will never store your current position on screen because that will be computed again 
when a new instance of the view is placed in its view hierarchy.
Some examples of things you may store here: the current cursor position in a text view 
(but usually not the text itself since that is stored in a content provider or other persistent storage), 
the currently selected item in a list view.
Returns
    * Returns a Parcelable object containing the view's current dynamic state, 
    or null if there is nothing interesting to save. The default implementation returns null.
TextView文档中对其的说明如下:
public void onRestoreInstanceState (Parcelable state)
Since: API Level 1
Hook allowing a view to re-apply a representation of its internal state 
that had previously been generated by onSaveInstanceState(). 
This function will never be called with a null state.
Parameters
state  The frozen state that had previously been returned by onSaveInstanceState().
public Parcelable onSaveInstanceState ()
Since: API Level 1
Hook allowing a view to generate a representation of its internal state 
that can later be used to create a new instance with that same state. 
This state should only contain information that is not persistent or can not be reconstructed later.
 For example, you will never store your current position on screen 
 because that will be computed again when a new instance of the view is placed in its view hierarchy.
Some examples of things you may store here: the current cursor position 
in a text view (but usually not the text itself since that is stored in a content provider 
or other persistent storage), the currently selected item in a list view.
Returns
    * Returns a Parcelable object containing the view's current dynamic state, 
    or null if there is nothing interesting to save. The default implementation returns null
ViewTextView中对onSaveInstanceStateonRestoreInstanceState的描述都差不多。
但是在View中,这两个函数是
protected的,而在TextView中这两个函数是public的。在ListView中他们也是public的。
但在他们的文档比没说系统何时回调用这两个函数。从在View的子类TextView和ListView中,都把他们声明为public的来看,
该两个函数应该不是由系统来调用的。从实例1的运行来看,也没发现系统调用它们。
因此它们应该只是设计作为一个接口,

以便在ActivityonSaveInstanceState(Bundle outState)onRestoreInstanceState(Bundle  savedInstanceState)
调用来保存View的数据。
如何使用
onSaveInstanceState (),是在函数里面保存一些View有用的数据到一个Parcelable对象,并返回。
ActivityonSaveInstanceState(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使用
实例1
文件1:
Hello.java
package com.teleca;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
public class Hello extends Activity {
 String tag="hubin";
 MyTextView textView1;
 MyTextView tv2;

 final String kTextView1Name="tv1";
 LinearLayout layoutRoot=null;
    /** Called when the activity is first created. */
    @Override

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button button = (Button) findViewById(R.id.Button01);
        OnClickListener listener = new OnClickListener() {
         public void onClick(View v) {
          Intent intent =new Intent(Hello.this,Hello2.class);
         startActivity(intent);
         //finish();
         }
        };
        button.setOnClickListener(listener);
        if(layoutRoot==null)
         layoutRoot=(LinearLayout)findViewById(R.id.root);
        if(textView1==null)
        {
         textView1=new MyTextView(this,"first view");
         layoutRoot.addView(textView1);
        }
        
        Log.i(tag,"create one1");
        ;
    }
    protected void onSaveInstanceState(Bundle outState)
    {
     super.onSaveInstanceState(outState);
     Log.i(tag,"one SaveInstanceState");
     Parcelable savedState=textView1.onSaveInstanceState();
     outState.putParcelable(kTextView1Name, savedState);

    }
    protected void onRestoreInstanceState(Bundle  savedInstanceState)
    {
     super.onRestoreInstanceState(savedInstanceState);
     Log.i(tag,"one RestoreInstanceState");
     SavedState0 savedState=savedInstanceState.getParcelable(kTextView1Name);
     textView1.onRestoreInstanceState(savedState);

    }
    protected void onDestroy()
    {
     super.onDestroy();
     Log.i(tag,"one Destroy");
    }
}

文件2:Hello2.java
package com.teleca;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class Hello2 extends Activity {
 String tag="hubin";
    /** Called when the activity is first created. */
    @Override

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main2);
        Button button = (Button) findViewById(R.id.Button01);
        OnClickListener listener = new OnClickListener() {
         public void onClick(View v) {
          Intent intent =new Intent(Hello2.this,Hello.class);
         startActivity(intent);
         }
        };
        button.setOnClickListener(listener);
    }
    protected void onSaveInstanceState(Bundle b)
    {
     Log.i(tag,"two SaveInstanceState");
    }
    protected void onDestroy()
    {
     super.onDestroy();
     Log.i(tag,"two Destroy");
    }
}
文件3:MyTextView.java
package com.teleca;
import java.util.HashMap;
import java.util.Set;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import android.preference.Preference.BaseSavedState;
import android.util.Log;
import android.widget.TextView;
public class MyTextView extends TextView {
 String tag="hubin";
    int startPage;
    HashMap<Long, Boolean> checkedItemIds;
 public MyTextView(Context context,String text) {
  super(context);
  // TODO Auto-generated constructor stub
  Log.i(tag,"create TextView "+text);
  this.setText(text);
  startPage=(int)System.currentTimeMillis();
  checkedItemIds=new HashMap<Long,Boolean>();
  checkedItemIds.put((long)startPage+1, true);
  checkedItemIds.put((long)startPage+2, true);
  checkedItemIds.put((long)startPage+3, true);
 }
 public Parcelable onSaveInstanceState()
 {
  Parcelable superState = super.onSaveInstanceState();
  Log.i(tag,"onSave in TextView");
  Log.i(tag,"save startPage:"+startPage);
     Set<Long> set=checkedItemIds.keySet();
     Object keys[]=set.toArray();
     for(int i=0;i<keys.length;i++)
     {
      Log.i(tag,"i:"+Long.parseLong(""+keys));
     }
  return new SavedState0(superState,startPage,checkedItemIds);
 }
 @Override
 public void onRestoreInstanceState(Parcelable state) {
     SavedState0 ss = (SavedState0) state;
     Log.i(tag, "onRestoreInstanceState");
     super.onRestoreInstanceState(ss.getSuperState());
     
     startPage = ss.startPage;
     checkedItemIds.clear();
     checkedItemIds.putAll(ss.checkedItemIds);
     Log.i(tag,"restore startPage:"+startPage);
     Set<Long> set=checkedItemIds.keySet();
     Object keys[]=(Long[])set.toArray();
     for(int i=0;i<keys.length;i++)
     {
      Log.i(tag,"i:"+Long.parseLong(""+keys));
     }
 }
}
class SavedState0 extends BaseSavedState {
    int startPage;
    HashMap<Long, Boolean> checkedItemIds;
    SavedState0(Parcelable superState, int startPage,HashMap<Long, Boolean> checkedItemIds) {
        super(superState);
        this.startPage = startPage;
        this.checkedItemIds = checkedItemIds;
    }
    private SavedState0(Parcel in) {
        super(in);
        startPage = in.readInt();
        checkedItemIds = in.readHashMap(null);
    }
    @Override
    public void writeToParcel(Parcel out, int flags) {
        super.writeToParcel(out, flags);
        out.writeInt(startPage);
        out.writeMap(checkedItemIds);
    }
    @Override
    public String toString() {
        return "Text View SavedState{"
                + Integer.toHexString(System.identityHashCode(this)) + "}";
    }
    /*
     * Interface that must be implemented and provided as a public CREATOR field 
     * that generates instances of your Parcelable class from a Parcel. 
     */
    /*
     * Interface for classes whose instances can be written to and restored from a Parcel. 
     * Classes implementing the Parcelable interface must also have a static field called CREATOR, 
     * which is an object implementing the Parcelable.Creator  interface. 
     */

    public static final Parcelable.Creator<SavedState0> CREATOR
            = new Parcelable.Creator<SavedState0>() {
        public SavedState0 createFromParcel(Parcel in) {
            return new SavedState0(in);
        }
        public SavedState0[] newArray(int size) {
            return new SavedState0[size];
        }
    };
}

注意1:当我们构造一个Parcelable的子类一定要定义public static final Parcelable.Creator<SavedState0> CREATOR。
它用于从一个流创建Parcelable对象。注意是个具体的Parcelable对象。比如这里就是BaseSavedState对象。
对于Parcelable对象和流的转化机制(该示例的桥是Bundle),我想有两种可能:
A:在把Parcelable对象转为流的时候,除了Parcel的数据(通过方法writeToParcel得到),
还把Parcelable对象的构造器CREATOR的信息写到了流中。在读的时候,
就可以通过在流中读得关于CREATOR的信息找到Parcelable对象构造器CREATOR以便创建Parcelable对象(这里是BaseSavedState)
至于在写数据时,系统如何找到CREATOR,我想既然知道一个对象,那么虚拟机当然可以找他属于哪个类。
找到了属于哪个类,就可以找到CREATOR变量。当然也可能是通过一个对象的成员变量表直接找到CREATOR变量的。
B:在把Parcelable对象转为流的时候,除了Parcel的数据(通过方法writeToParcel得到),
还把Parcelable对象所属类的信息写到了流中。在读的时候,
就可以通过在流中读得关于Parcelable对象所属类的信息,找到Parcelable对象所属的类,
然后通过该类找到构造器CREATOR以便创建Parcelable对象(这里是BaseSavedState)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值