您的位置:首页 > 其它

onPause()和onSaveInstanceState(Bundle savedInstanceState)回调函数保存

2015-04-28 21:40 387 查看
写过Android程序的都知道Activity中有一个名称叫onCreate的方法。该方法是在Activity创建时被系统调用,是一个Activity生命周期的开始。可是有一点容易被忽视,就是onCreate方法的参数savedInstanceState。因为在一般的程序开发中,很少用到这个参数。

onCreate方法的完整定义如下:

public void onCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

}

    从上面的代码可以看出,onCreate方法的参数是一个Bundle类型的参数。Bundle类型的数据与Map类型的数据相似,都是以key-value的形式存储数据的。

    从字面上看savedInstanceState,是保存实例状态的。实际上,savedInstanceState也就是保存Activity的状态的。那么,savedInstanceState中的状态数据是从何处而来的呢?下面我们介绍Activity的另一个方法saveInstanceState。

    onsaveInstanceState方法是用来保存Activity的状态的。当一个Activity在生命周期结束前,会调用该方法保存状态。这个方法有一个参数名称与onCreate方法参数名称相同。如下所示:

public void onSaveInstanceState(Bundle savedInstanceState){

super.onSaveInstanceState(savedInsanceState);

}

    在实际应用中,当一个Activity结束前,如果需要保存状态,就在onsaveInstanceState中,将状态数据以key-value的形式放入到savedInstanceState中。这样,当一个Activity被创建时,就能从onCreate的参数savedInsanceState中获得状态数据。

    状态这个参数在实现应用中有很大的用途,比如:一个游戏在退出前,保存一下当前游戏运行的状态,当下次开启时能接着上次的继续玩下去。再比如:电子书程序,当一本小说被阅读到第199页后退出了(不管是内存不足还是用户自动关闭程序),当下次打开时,读者可能已忘记了上次已阅读到第几页了,但是,读者想接着上次的读下去。如果采用saveInstallState参数,就很容易解决上述问题。

简单的事例api中snake游戏 在SnakeView类中

private int[] coordArrayListToArray(ArrayListcvec) {

        int count = cvec.size();

        int[] rawArray = new int[count * 2];

        for (int index = 0; index < count; index++) {

            Coordinate c = cvec.get(index);

            rawArray[2 * index] = c.x;

            rawArray[2 * index + 1] = c.y;

        }

        return rawArray;

    }

    

    public Bundle saveState() {

        Bundle map = new Bundle();

        map.putIntArray("mAppleList", coordArrayListToArray(mAppleList));

        map.putInt("mDirection", Integer.valueOf(mDirection));

        map.putInt("mNextDirection", Integer.valueOf(mNextDirection));

        map.putLong("mMoveDelay", Long.valueOf(mMoveDelay));

        map.putLong("mScore", Long.valueOf(mScore));

        map.putIntArray("mSnakeTrail", coordArrayListToArray(mSnakeTrail));

        return map;

    }

在snakeActivity中实现

   @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.snake_layout);

        mSnakeView = (SnakeView) findViewById(R.id.snake);

        mSnakeView.setTextView((TextView) findViewById(R.id.text));

        if (savedInstanceState == null) {

            // We were just launched -- set up a new game

            mSnakeView.setMode(SnakeView.READY);

        } else {

            // We are being restored

            Bundle map = savedInstanceState.getBundle(ICICLE_KEY);

            if (map != null) {

                mSnakeView.restoreState(map);

            } else {

                mSnakeView.setMode(SnakeView.PAUSE);

            }

        }

    }

并重写onSavedInstanceState(),此方法会在activity结束时,调用.

    @Override

    public void onSaveInstanceState(Bundle outState) {

        //Store the game state

        outState.putBundle(ICICLE_KEY, mSnakeView.saveState());

    }

转自:http://blog.sina.com.cn/s/blog_652dd96d0100ug6h.html

在看贪吃蛇代码的时候,看到下面这个回调函数,用来保存贪吃蛇的游戏数据。   

    @Override

    public void onSaveInstanceState(Bundle outState) {

        //Store the game state

        outState.putBundle(ICICLE_KEY, mSnakeView.saveState());

    }

下面是对这个回调函数和onPause()方法保存数据的异同。

public class TestPictureLayout extends Activity {

     static final int DAY_VIEW_MODE = 0;

     static final int WEEK_VIEW_MODE = 1;

     private SharedPreferences mPrefs;

     private int mCurViewMode;

     private int i;

     protected void onCreate(Bundle savedInstanceState) {

         super.onCreate(savedInstanceState);

         SharedPreferences mPrefs = getSharedPreferences();

         mCurViewMode = mPrefs.getInt("view_mode" DAY_VIEW_MODE);

if(savedInstanceState!=null)

{

i=savedInstanceState.getInt("data");

//这个是之前保存的数据

}

else{

//这个是从另外一个界面进入这个时传入的

i=getIntent().getint("data");

}

     

     }protected void onPause() {

         super.onPause();

//界面失去控制权时保存数据

         SharedPreferences.Editor ed = mPrefs.edit();

         ed.putInt("view_mode", mCurViewMode);

         ed.commit();

     }

}

  @Override

public void onSaveInstanceState(Bundle outState) {

//界面销毁之前保存数据

super.onSaveInstanceState(outState);

outState.putInt("data",1);}

@Override

public void onRestoreInstanceState(Bundle savedInstanceState) {

//执行于onStart()之后,回复之前保存过的数据,其实可以不要,因为oncreate中已经获取过了

super.onRestoreInstanceState(savedInstanceState);

i=savedInstanceState.getInt("data");

}

}

在activity被杀掉之前调用保存每个实例的状态,以保证该状态可以在onCreate(Bundle)或者 onRestoreInstanceState(Bundle) (传入的Bundle参数是由onSaveInstanceState封装好的)中恢复。这个方法在一个activity被杀死前调用,当该 activity在将来某个时刻回来时可以恢复其先前状态。

例如,如果activity B启用后位于activity A的前端,在某个时刻activity A因为系统回收资源的问题要被杀掉,A通过onSaveInstanceState将有机会保存其用户界面状态,使得将来用户返回到activity A时能通过onCreate(Bundle)或者onRestoreInstanceState(Bundle)恢复界面的状态。

不要将这个方法 和activity生命周期回调如onPause()或onStop()搞混淆了,onPause()在activtiy被放置到背景或者自行销毁时总会 被调用,onStop()在activity被销毁时被调用。一个会调用onPause()和onStop(),但不触发 onSaveInstanceState的例子是当用户从activity B返回到activity A时:没有必要调用B的onSaveInstanceState(Bundle),此时的B实例永远不会被恢复,因此系统会避免调用它。一个调用
onPause()但不调用onSaveInstanceState的例子是当activity B启动并处在activity A的前端:如果在B的整个生命周期里A的用户界面状态都没有被破坏的话,系统是不会调用activity A的onSaveInstanceState(Bundle)的。

默认的实现负责了大部分UI实例状态(的保存),采用的方式是调用UI层上每个拥有id的view的onSaveInstanceState() ,并且保存当前获得焦点的view的id(所有保存的状态信息都会在默认的onRestoreInstanceState(Bundle)实现中恢复)。
如果你覆写这个方法来保存额外的没有被各个view保存的信息,你可能想要在默认实现过程中调用或者自己保存每个视图的所有状态。如果被调用,这个方法会 在onStop()前被触发,但系统并不保证是否在onPause()之前或者之后触发。

转自:http://dev.10086.cn/cmdn/wiki/index.php?doc-view-5405.html。

在Activity中保存用户的当前操作状态,如输入框中的文本,一般情况下载按了home键后,重新进入文本框中的东西会丢下,所以我们要保存当前页面信息,如在写短信的时候接到一个电话,那么当你接电话的时候短信界面就会别隐藏,那么我们希望接完电话后可以继续编辑短信,就需要保存状态。使用办法:
重写Activity中的onSaveInstanceState(Bundle outState)和onRestoreInstanceState(Bundle savedInstanceState)方法,步骤为:(1)在离开页面的时候用onSaveInstanceState中的outState可以保存你所需要的值,(2)在重新回到该页面的时候可以使用onRestoreInstanceState从saveInstanceState中获取保存过得值来重新初始化界面。
从android的API文档可以知道,onSaveInstanceState是在OnStop之前执行,onRestoreInstanceState在OnStart后执行,因此如果是Activity销毁过后的话再启动数据就没有保存了,即在finish或用户按下Back后,该功能就失效了。一般用在当前Activity被其他Activity覆盖和按Home键后重新进入该Activity的时候。

实例代码如下:
@Override

protected void onSaveInstanceState(Bundle outState) {

super.onSaveInstanceState(outState);

// save the current data, for instance when changing screen orientation

outState.putSerializable("dataset", mDataset);

outState.putSerializable("renderer", mRenderer);

}
@Override

protected void onRestoreInstanceState(Bundle savedState) {

super.onRestoreInstanceState(savedState);

// restore the current data, for instance when changing the screen

// orientation

mDataset = (XYMultipleSeriesDataset) savedState.getSerializable("dataset");

mRenderer = (XYMultipleSeriesRenderer) savedState.getSerializable("renderer");
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  savedInstanceState