2014-04-20 38 views
1

我在制作一个简单的游戏,它使用GridView和一个自定义的Adapter。这基本上是一个玩家可以在GridView中移动的游戏(只需更改单元格的图像)。游戏有10个级别。问题是,当我离开活动时(例如回到MainActivity),游戏被重置。当然,当电话关闭并重置游戏时也是如此。如何在Android中保存和加载GridView的状态

我想保留游戏状态,所以当玩家进入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; 
    } 
} 

所以现在的问题是,我怎么能这个对象保存到内部存储和retrive回来必要的时候?

我已经尝试了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

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

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()恢复比赛州。

如果我可以做一个小结构的建议,我喜欢让保持我的状态变量“一揽子”上课的时候我把它写入磁盘像这样:

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

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

如果你不知道如何把一个对象转换为字节数组,这里是它的SO问题: