如何在Android中保存和加载GridView的状态

时间:2014-04-20 03:11:20

标签: java android gridview android-intent savestate

我正在制作一款使用GridView和自定义Adapter的简单游戏。它基本上是一个玩家可以通过GridView移动的游戏(只需更改单元格的图像)。游戏有10个级别。问题是,当我退出活动(例如回到MainActivity)时,游戏会重置。当手机关闭并且游戏重置时也很自然。

我想保留游戏状态,所以当玩家进入GameActivity时,他/她可以继续游戏。

我只需要保存3件事,适配器,等级数和可用动作。如果我知道如何解决这个问题,我就可以实现我的目标:

public class GameState implements Serializable {

    private GameAssetAdapter mAdapter;
    private int mLevel;
    private int mAvailableMoves;

    public GameState(GameAssetAdapter adapter, int level, int availableMoves) {
        mAdapter = adapter;
        mLevel = level;
        mAvailableMoves = availableMoves;
    }

    public GameAssetAdapter getAdapter() {
        return mAdapter;
    }

    public int getLevel() {
        return mLevel;
    }

    public int getAvailableMoves() {
        return mAvailableMoves;
    }
}

所以问题是,我如何将这个对象保存到内部存储器并在必要时将其恢复?

我已经尝试了onSaveInstanceState,但它没有按预期工作。手机关/开将重置此功能。即使用户在Android的应用程序列表中擦除应用程序,它也会被重置。我该怎么办?

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putSerializable(AppConstants.GAME_SAVE_ASSET_ADAPTER, mGameAssetAdapter);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_game);

    if(savedInstanceState != null)
    {   //Restore mGameAssetAdapter if was saved perviously
        if(mGameAssetAdapter == null){
            restoreGameAssetAdapter(savedInstanceState);
        }
    }

    //TODO get level and states!!
    mGameGridView = (GameGridView)findViewById(R.id.game_grid_view);
    mGameGridView.setNumColumns(GameConstants.COLUMNS);
    mGameGridView.setColumnWidth(GameHelper.getOptimumAssetImageWidth(this,
            GameConstants.COLUMNS));
    if(mGameAssetAdapter == null) {
        mGameAssetAdapter = new GameAssetAdapter(this, mLevel);
    }
    mGameGridView.setAdapter(mGameAssetAdapter);
    this.setTitle("Snakes and Ladders - Level " + mLevel);

    setupEvents();
}

private void restoreGameAssetAdapter(Bundle savedInstanceState) {
    if(savedInstanceState.getSerializable("GAME_ASSET_ADAPTER") != null){
        mGameAssetAdapter =
                (GameAssetAdapter) savedInstanceState.
                        getSerializable("GAME_ASSET_ADAPTER");
        Log.v(TAG, "Restored saved GameAssetAdapter! Hoooray!");
    }
}

1 个答案:

答案 0 :(得分:1)

您可以将状态写入存储。以下是我个人存储的一些代码:

private static byte[] readBytes(String dir, Context context) throws IOException
{
    FileInputStream fileIn = null;
    DataInputStream in = null;

    byte[] buffer = null;

    fileIn = context.openFileInput(dir);
    in = new DataInputStream(fileIn);

    int length = in.readInt();

    buffer = new byte[length];

    for(int x = 0;x < buffer.length;x++)
        buffer[x] = in.readByte();

    try 
    {
        fileIn.close();
    } catch (Exception e) {}

    try 
    {
        in.close();
    } catch (Exception e) {}

    fileIn = null;
    in = null;

    return buffer;
}

private static void writeBytes(String dir, byte bytes[], Context context) throws IOException
{
    FileOutputStream fileOut = null;
    DataOutputStream out = null;

    fileOut = context.openFileOutput(dir, Context.MODE_PRIVATE);
    out = new DataOutputStream(fileOut);

    int length = bytes.length;

    out.writeInt(length);
    out.write(bytes);
    out.flush();

    try 
    {
        fileOut.close();
    } catch (Exception e) {}

    try 
    {
        out.close();
    } catch (Exception e) {}
}

您可以使用writeBytes()方法保存状态,然后在重新启动应用程序时,您所要做的就是使用readBytes()来恢复游戏状态。

如果我可以提出一个小的结构性建议,我想制作一个包装&#39;当我将它写入磁盘时保存我的状态变量的类:

public class SavedState implements Serializible
{
    public GameState state;
    int id;
    ...
}

然后,当您将其写入磁盘时,您将把所有状态变量放在一个干净的类中。我还建议不要将DisplayAdapter保存为列表视图(可能存在很多问题)或其他问题。将基础数据结构保存到此包类,然后在恢复应用程序状态时创建新的DisplayAdapter

如果您不知道如何将对象转换为字节数组,那么这就是问题所在: