安卓自定义View的状态保存与恢复

安卓自定义View的状态保存与恢复

我们在开发某些安卓应用(如安卓小游戏)时,可能会用到自定义View,这时候往往需要保存自定义View的状态信息,以便在遇到某些情况(如由于系统内存资源紧张被系统杀死;或者在平板上经常发生的旋转屏幕)时能够恢复之前的状态信息,不给用户带来不必要的麻烦。
笔者在开发一款安卓平台的人机五子棋时就用到了自定义View,由于需要适配平板,因此要考虑旋转屏幕的情况。首先看一下Activity的生命周期,如下图所示:
安卓自定义View的状态保存与恢复_第1张图片

从下图可知,翻转屏幕时依次调用了
onPause(),onStop(),onDestroy(),onCreate(),onStart(),onResume()方法来进行当前活动的摧毁和重建。
安卓自定义View的状态保存与恢复_第2张图片
在这一过程中,安卓会自动完成系统自带的View的状态的保存和恢复,而对于我们的自定义View的状态保存和恢复则需要我们自己来完成。

下面就谈谈如何进行自定义View的状态保存和恢复,主要用到两个方法。onSaveInstanceState()和onRestoreInstanceState(Parcelable state)。
onSaveInstanceState()的源码如下,主要任务是在可序列化对象state中存储需要被保存的信息mStartActivityRequestWho。

@CallSuper
    protected Parcelable onSaveInstanceState() {
        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
        if (mStartActivityRequestWho != null) {
            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
            return state;
        }
        return BaseSavedState.EMPTY_STATE;
    }

onRestoreInstanceState(Parcelable state)源码如下:主要任务是根据参数state的mStartActivityRequestWhoSaved属性值来得到被保存的信息mStartActivityRequestWho,以便在重建Activity的时候恢复被保存的信息。

@CallSuper
    protected void onRestoreInstanceState(Parcelable state) {
        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
        if (state != null && !(state instanceof AbsSavedState)) {
            throw new IllegalArgumentException("Wrong state class, expecting View State but "
                    + "received " + state.getClass().toString() + " instead. This usually happens "
                    + "when two views of different type have the same id in the same hierarchy. "
                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
                    + "other views do not use the same id.");
        }
        if (state != null && state instanceof BaseSavedState) {
            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
        }
    }

下面拿笔者自己写的小游戏五子棋来举个例子。没有重写上述两个方法的效果图如下,当旋转屏幕时,棋盘上的棋子消失了(T . T)
安卓自定义View的状态保存与恢复_第3张图片

重写方法如下:

    private static final String INSTANCE="instance";
    //游戏结束与否
    private static final String INSTANCE_GAME_OVER="instance_game_over";
    //白棋数组
    private static final String INSTANCE_WHITE_ARRAY="instance_white_array";
    //黑棋数组
    private static final String INSTANCE_BLACK_ARRAY="instance_black_array";
    //棋盘信息
    private static String INSTANCE_CHESSBOARD[];
    //玩家胜利
    private static final String INSTANCE_MYWIN="instance_mywin";
    //计算机胜利
    private static final String INSTANCE_COMPUTERWIN="instance_computerwin";
    //人机算法参数1
    private static final String INSTANCE_MS="instance_ms";
    //人机算法参数2
    private static final String INSTANCE_CS="instance_cs";

    @Override
    protected Parcelable onSaveInstanceState() {
        //将数据保存在可序列化对象bundle中
        Bundle bundle=new Bundle();
        //保存系统原有的其他状态信息                    
        bundle.putParcelable(INSTANCE,super.onSaveInstanceState());
        //根据信息数据类型的不同,调用不同方法进行,存储到bundle中
        bundle.putBoolean(INSTANCE_GAME_OVER,gameOver);
        bundle.putParcelableArrayList(INSTANCE_WHITE_ARRAY,mWhiteArray);
        bundle.putParcelableArrayList(INSTANCE_BLACK_ARRAY,mBlackArray);
        INSTANCE_CHESSBOARD=new String[MAX_LINE];
        for(int i=0;i"instance_chessboard"+i;
            bundle.putIntArray(INSTANCE_CHESSBOARD[i],chessBoard[i]);
        }
        bundle.putIntArray(INSTANCE_MYWIN,myWin);
        bundle.putIntArray(INSTANCE_COMPUTERWIN,computerWin);
        bundle.putIntArray(INSTANCE_MS,ms);
        bundle.putIntArray(INSTANCE_CS,cs);

        //返回bundle
        return bundle;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        //判断state的类型是否为bundle,若是则从bundle中取数据
        if(state instanceof Bundle){
            Bundle bundle=(Bundle)state;
            gameOver=bundle.getBoolean(INSTANCE_GAME_OVER);
            mWhiteArray=bundle.getParcelableArrayList(INSTANCE_WHITE_ARRAY);
            mBlackArray=bundle.getParcelableArrayList(INSTANCE_BLACK_ARRAY);
            for(int i=0;isuper.onRestoreInstanceState(bundle.getParcelable(INSTANCE));
            return;
        }
        super.onRestoreInstanceState(state);
    }

现在再来看一下加了上述方法后的运行情况:
安卓自定义View的状态保存与恢复_第4张图片

最终效果如下:
安卓自定义View的状态保存与恢复_第5张图片

你可能感兴趣的:(android)