2012-12-01 15 views
23

私はAndroidゲームのすべてのデータをsavedInstanceStateバンドルに収めることに尽力しました。多くのParcelableオブジェクトを含む多くのデータがあります。これにより、アプリが一時停止されたり、向きが変わったりすると、アクティビティが再作成されてもデータが失われることはありません。バンドルをSharedPreferencesに保存する

しかし、私は最近、savedInstanceStateバンドルが長期保存には適していないことを発見しました。だから私は、ゲームの状態を常に元に戻すことができるように、私は自分の既存のsaveメソッドを長期的な解決策として適応させる方法を模索しています。

私は2つのソリューションこれまでの聞いたことがある:

1)向きの変更のためのsavedInstanceStateバンドルを使用するだけでなく、アプリが完全にシャットダウンする必要があるときのためにSharedPrefsを組み込みます。

これは、基本的に同じことを行うために2つの異なる完全な方法を使用するため、これは非常に非生産的です。また、私のsavedInstanceState BundleはParcelableオブジェクトを使用しているので、これらのオブジェクトのそれぞれにSharedPrefsに書き込むための別のメソッドを与える必要があります。本質的に、重複していて管理が難しいコードがたくさんあります。

2)savedInstanceStateバンドルをシリアル化し、ファイルに直接書き込みます。

私はこれには開放されていますが、実際にそれをやり遂げる方法はわかりません。しかし、私はAndroidのシリアル化が「喜んで/不可能に遅い」と聞いたので、よりよい解決策があることを願っています。

誰かが私にこの問題に対する解決策を提供できるのであれば、非常に感謝します。

+0

シリアライゼーションクラスを探してシリアライズするだけでは、それを見つけるのは難しくありません。 – mango

+0

私が見つけることができる唯一の情報は、シリアライズ可能を実装する必要があることを唯一の情報が示していますが、バンドルはこのインターフェイスを実装していません。 – Dan

+0

私はライブラリhttps://github.com/iamironz/binaryprefsを推奨しています。これにより、実装を通じて標準Javaのようなデータを保存できます。永続的なインターフェイス(jdkの外部化可能インターフェイス) –

答えて

3

私は今この問題に対する独自の解決策を思いつきました。これはバンドルをSharedPreferencesに保存する半自動的な手段です。私は半自動と言っています.Bundleを保存するには1つの方法しか必要ありませんが、データを再度取得してバンドルに戻す作業が必要です。ここで

は、バンドルを保存するためのコードです:私は、私は必要なのタイプの例を書かれているが、あなたはまた、他の種類が含まれるバンドルを持っている場合、これは容易に適応する必要があります

SharedPreferences save = getSharedPreferences(SAVE, MODE_PRIVATE); 
Editor ed = save.edit(); 
saveBundle(ed, "", gameState); 

/** 
* Manually save a Bundle object to SharedPreferences. 
* @param ed 
* @param header 
* @param gameState 
*/ 
private void saveBundle(Editor ed, String header, Bundle gameState) { 
    Set<String> keySet = gameState.keySet(); 
    Iterator<String> it = keySet.iterator(); 

    while (it.hasNext()){ 
     key = it.next(); 
     o = gameState.get(key); 
     if (o == null){ 
      ed.remove(header + key); 
     } else if (o instanceof Integer){ 
      ed.putInt(header + key, (Integer) o); 
     } else if (o instanceof Long){ 
      ed.putLong(header + key, (Long) o); 
     } else if (o instanceof Boolean){ 
      ed.putBoolean(header + key, (Boolean) o); 
     } else if (o instanceof CharSequence){ 
      ed.putString(header + key, ((CharSequence) o).toString()); 
     } else if (o instanceof Bundle){ 
      saveBundle(header + key, ((Bundle) o)); 
     } 
    } 

    ed.commit(); 
} 

注意。

このメソッドは、指定されたBundle内に格納されている他のBundleオブジェクトを再帰的に保存します。ただし、Parcelableオブジェクトでは機能しないため、Parcelableオブジェクトを変更してバンドルに格納する必要がありました。パーセルとバンドルはかなり類似しているので、これはあまり難しくありませんでした。残念ながら、バンドルはパーセルよりも少し遅いかもしれません。

私は以前のすべてのParcelableオブジェクトにコンストラクタを書き込んで、SharedPreferencesに格納されたデータから自分自身を再バンドルできるようにしました。必要なデータにキーを再構築するのは簡単です。あなたは、次のデータ構造を持っていると言う:

Bundle b { 
    KEY_X -> int x; 
    KEY_Y -> Bundle y { 
       KEY_Z -> int z; 
      } 
} 

次のようにこれらはSharedPreferencesに保存されます。

KEY_X -> x 
KEY_YKEY_Z -> z 

それは、世界で最も美しい方法ではないかもしれないが、それは動作しますが、それは私のコスト私のonSaveInstanceStateメソッドと私のonPauseメソッドは同じテクニックを使用しています。

+0

どうすればこのような状況でバンドルできますか? ありがとう –

+1

私はあなたが正確に何を意味するか分かりません...バンドルがSharedPrefsに保存されたら、他のバンドルのように取得できます。 – Dan

+0

ここでキーとoは何ですか?あなたがこれらの引数をどこに渡すか – ekjyot

18

おかげで、今週、問題47のAndroid Weeklyがこのライブラリを解き放ちました:android complex preferences

あなたに合っているはずです。

+0

これはとても有望でしたが、何でも空のものや、ポイントのような単純なオブジェクトを含むさまざまなBundleオブジェクトで試しましたが、まだ運がありません。保存するときに "循環参照"、またはロード時に "キー___に格納されたオブジェクトが別のゲームのインスタンスです"という文句が出ます。これは私を夢中にさせている... – Dan

+0

別の質問として投稿してください。あなたが私の住所にコメントをつけて、私がそれに従うことができるなら、私は興味があります。 – Snicolas

+1

実際、GSonを使ってJSonとしてすべてを保存しています...とにかく、あなたのデータは何かの内部クラスかもしれません。これはサイクルを非常に簡単にします。あなたのPOJOは別のクラスですか? – Snicolas

1

Danの回答をバンドルを自動的に再作成する機能で拡張し、名前の衝突を少なくしました。

+0

https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/src-html/org/ apache/commons/lang/StringUtils.html StringUtils関数が何をしているかを取得する(アンドロイドには含まれていません) –

関連する問題