如何序列化捆绑?

her*_*rmo 20 serialization android bundle

我想序列化一个Bundle对象,但似乎找不到一种简单的方法.使用Parcel似乎不是一个选项,因为我想将序列化数据存储到文件中.

有关如何做到这一点的任何想法?

我想要这个的原因是保存和恢复我的活动状态,当它被用户杀死时.我已经创建了一个Bundle,其中包含我要保存在onSaveInstanceState中的状态.但是当活动被SYSTEM杀死时,android只保留这个Bundle.当用户杀死活动时,我需要自己存储它.因此,我想将其序列化并存储到文件中.当然,如果你有任何其他方式来完成同样的事情,我也会感激.

编辑:我决定将我的状态编码为JSONObject而不是Bundle.然后可以将JSON对象作为Serializable放入Bundle中,或者存储到文件中.可能不是最有效的方式,但它很简单,似乎工作正常.

ref*_*log 7

将任何Parcelable存储到文件中非常容易:

FileOutputStream fos = context.openFileOutput(localFilename, Context.MODE_PRIVATE);
Parcel p = Parcel.obtain(); // i make an empty one here, but you can use yours
fos.write(p.marshall());
fos.flush();
fos.close();
Run Code Online (Sandbox Code Playgroud)

请享用!

  • 从方法mashall()检索的数据不得放在任何类型的持久存储中(在本地磁盘上,通过网络等).为此,您应该使用标准序列化或其他类型的通用序列化机制.Parcel编组表示针对本地IPC进行了高度优化,因此不会尝试保持与在不同版本的平台中创建的数据的兼容性.(http://developer.android.com/reference/android/os/Parcel.html#marshall()) (12认同)
  • 是的,我也发现了.问题在于,无法保证您可以再次解组,例如操作系统是否已更新且包裹已更改.但是,如果你能忍受那么,那就没事了. (9认同)

snc*_*tln 6

我使用SharedPreferences来解决这个限制,它使用与Bundle类相同的putXXX()和getXXX()样式来存储和检索数据,并且如果您之前使用过Bundle则相对简单.

所以在onCreate我有这样的支票

if(savedInstanceState != null)
{
    loadGameDataFromSavedInstanceState(savedInstanceState);
}
else
{
    loadGameDataFromSharedPreferences(getPreferences(MODE_PRIVATE));
}
Run Code Online (Sandbox Code Playgroud)

我将游戏数据保存到onSaveInstanceState()中的Bundle,并从onRestoreInstanceState()中的Bundle加载数据

我还将游戏数据保存到onPause()中的SharedPreferences,并从onResume()中的SharedPreferences加载数据

onPause()
{
    // get a SharedPreferences editor for storing game data to
    SharedPreferences.Editor mySharedPreferences = getPreferences(MODE_PRIVATE).edit();

    // call a function to actually store the game data
    saveGameDataToSharedPreferences(mySharedPreferences);

   // make sure you call mySharedPreferences.commit() at the end of your function
}

onResume()
{
    loadGameDataFromSharedPreferences(getPreferences(MODE_PRIVATE));
}
Run Code Online (Sandbox Code Playgroud)

如果有些人认为这是对SharedPreferences的错误使用,我不会感到惊讶,但它完成了工作.我已经在我的所有游戏(近200万次下载)中使用这种方法超过一年,它的工作原理.

  • 当然有效,我只是希望避免使用两种捆绑状态的方式,即使它们非常相似. (2认同)

asg*_*oth 6

将其转换为SharedPreferences:

private void saveToPreferences(Bundle in) {
    Parcel parcel = Parcel.obtain();
    String serialized = null;
    try {
        in.writeToParcel(parcel, 0);

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        IOUtils.write(parcel.marshall(), bos);

        serialized = Base64.encodeToString(bos.toByteArray(), 0);
    } catch (IOException e) {
        Log.e(getClass().getSimpleName(), e.toString(), e);
    } finally {
        parcel.recycle();
    }
    if (serialized != null) {
        SharedPreferences settings = getSharedPreferences(PREFS, 0);
        Editor editor = settings.edit();
        editor.putString("parcel", serialized);
        editor.commit();
    }
}

private Bundle restoreFromPreferences() {
    Bundle bundle = null;
    SharedPreferences settings = getSharedPreferences(PREFS, 0);
    String serialized = settings.getString("parcel", null);

    if (serialized != null) {
        Parcel parcel = Parcel.obtain();
        try {
            byte[] data = Base64.decode(serialized, 0);
            parcel.unmarshall(data, 0, data.length);
            parcel.setDataPosition(0);
            bundle = parcel.readBundle();
        } finally {
            parcel.recycle();
        }
    }
    return bundle;
}
Run Code Online (Sandbox Code Playgroud)

  • 这再次违背了将Parcel的内容存储到任何形式的持久性内存(Javadocs警告过)的建议.假设您出于某种原因更新了操作系统,那么上面的代码会在"restoreFromPreferences()"方法中使您的应用程序崩溃,或者在包中返回一些未知值. (5认同)