私はしばらくの間Androidアプリを開発してきましたが、最近フラグメントに取り掛かったため、それらの操作方法を学ぶのに多くの問題が発生しました。私のアプリケーションのアクティビティの1つには4つあります。さまざまなフラグメント。それぞれがアイテムのリストをユーザーに表示します。各フラグメントは最初に作成され、選択すると表示され、別のタブを選択すると非表示になります。これらの各フラグメントが作成されると、JSONObjectsのArrayListがとして渡されます。次のようにフラグメントへの引数
ft = fm.beginTransaction();
if(currentFragment !=null){
ft.hide(currentFragment);
}
if(whereFragment !=null){
ft.show(whereFragment);
}else{
if(mPlaceList.size()>0){
Bundle bundle = new Bundle();
bundle.putSerializable("array", mPlaceList);
whereFragment = new WhereFragment();
whereFragment.setArguments(bundle);
ft.add(R.id.newpost_container,whereFragment, "whereFragment");
}
}
ft.commit();
currentFragment = whereFragment;
Arraylistはフラグメントで受信され、すべてが正常に機能します。
actList = (ArrayList<JSONObject>) getArguments().getSerializable("array");
doingAdapter = new DoingAdapter(getActivity(), actList);
actListView.setAdapter(doingAdapter);
親アクティビティには、デバイスのカメラを起動するボタンがあります。それが発生し、フラグメントのonPauseメソッドが呼び出されると、アプリケーションがクラッシュし、Logcatでこのエラーが発生します
Logcat:
06-23 17:51:31.190: E/ACRA(29221): com.parspake.anar fatal error : Parcel: unable to marshal value {"type":"act","id":"5327f9827f49143f3a001c76","title":"خونه","actType":"where"}
06-23 17:51:31.190: E/ACRA(29221): Java.lang.RuntimeException: Parcel: unable to marshal value {"type":"act","id":"5327f9827f49143f3a001c76","title":"خونه","actType":"where"}
06-23 17:51:31.190: E/ACRA(29221): at Android.os.Parcel.writeValue(Parcel.Java:1235)
06-23 17:51:31.190: E/ACRA(29221): at Android.os.Parcel.writeList(Parcel.Java:622)
06-23 17:51:31.190: E/ACRA(29221): at Android.os.Parcel.writeValue(Parcel.Java:1195)
06-23 17:51:31.190: E/ACRA(29221): at Android.os.Parcel.writeMapInternal(Parcel.Java:591)
06-23 17:51:31.190: E/ACRA(29221): at Android.os.Bundle.writeToParcel(Bundle.Java:1619)
06-23 17:51:31.190: E/ACRA(29221): at Android.os.Parcel.writeBundle(Parcel.Java:605)
06-23 17:51:31.190: E/ACRA(29221): at Android.support.v4.app.FragmentState.writeToParcel(Fragment.Java:132)
06-23 17:51:31.190: E/ACRA(29221): at Android.os.Parcel.writeTypedArray(Parcel.Java:1102)
06-23 17:51:31.190: E/ACRA(29221): at Android.support.v4.app.FragmentManagerState.writeToParcel(FragmentManager.Java:368)
06-23 17:51:31.190: E/ACRA(29221): at Android.os.Parcel.writeParcelable(Parcel.Java:1254)
06-23 17:51:31.190: E/ACRA(29221): at Android.os.Parcel.writeValue(Parcel.Java:1173)
06-23 17:51:31.190: E/ACRA(29221): at Android.os.Parcel.writeMapInternal(Parcel.Java:591)
06-23 17:51:31.190: E/ACRA(29221): at Android.os.Bundle.writeToParcel(Bundle.Java:1619)
06-23 17:51:31.190: E/ACRA(29221): at Android.os.Parcel.writeBundle(Parcel.Java:605)
06-23 17:51:31.190: E/ACRA(29221): at Android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.Java:2096)
06-23 17:51:31.190: E/ACRA(29221): at Android.app.ActivityThread$StopInfo.run(ActivityThread.Java:2918)
06-23 17:51:31.190: E/ACRA(29221): at Android.os.Handler.handleCallback(Handler.Java:615)
06-23 17:51:31.190: E/ACRA(29221): at Android.os.Handler.dispatchMessage(Handler.Java:92)
06-23 17:51:31.190: E/ACRA(29221): at Android.os.Looper.loop(Looper.Java:137)
06-23 17:51:31.190: E/ACRA(29221): at Android.app.ActivityThread.main(ActivityThread.Java:4827)
06-23 17:51:31.190: E/ACRA(29221): at Java.lang.reflect.Method.invokeNative(Native Method)
06-23 17:51:31.190: E/ACRA(29221): at Java.lang.reflect.Method.invoke(Method.Java:511)
06-23 17:51:31.190: E/ACRA(29221): at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:841)
06-23 17:51:31.190: E/ACRA(29221): at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:608)
06-23 17:51:31.190: E/ACRA(29221): at dalvik.system.NativeStart.main(Native Method)
私はstackoverflowで周りを見回していて、私のような問題でいくつかの質問を目にしますが、私の状況を助けることができるそれらのどれからも何も取ることができないようです。フラグメントが状態を保存しようとしてjsonオブジェクトをシリアル化できないという問題の要点はわかりますが、SerializableまたはParcelableインターフェイスを使用して問題を修正するのを誰かが手伝ってくれるといいですね。すごい。また、他の人から提案されているように、フラグメントとアクティビティの両方にSerializableを実装しました。
さて、私はこれから抜け出す方法を見つけることができました。それは物事を行うための最も標準的な方法ではないかもしれませんが、実際に私の問題を解決し、ある程度他の人を助けるかもしれません。
APIから受け取ったJSONArrayをJSON配列リストに変換してからフラグメントに送信する代わりに、JSON配列を文字列に変換してバンドルと一緒に送信しました。
ft = fm.beginTransaction();
if(currentFragment !=null){
ft.hide(currentFragment);
}
if(doingFragment !=null){
ft.show(doingFragment);
}else{
if(mActList.size()>0){
Bundle bundle = new Bundle();
bundle.putString("array", jArrayWhat.toString());
doingFragment = new DoingFragment();
doingFragment.setArguments(bundle);
ft.add(R.id.newpost_container,doingFragment, "doingFragment");
}
}
ft.commit();
フラグメントでは、バンドルを受け取り、文字列をJSONArrayに変換しました。
jsonActList = new JSONArray(getArguments().getString("array"));
次に、JSONArrayを繰り返し処理し、JSONObjectArrayListに変換しました。また、フラグメントの使用後にマイリストに加えられた変更を保持するために、ArrayListをJSONArrayに変換して保存しました。
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
JSONArray jArray = new JSONArray(Arrays.asList(actList));
outState.putString("jsonArray", jArray.toString());
}
状態が保存されたので、次のようにonCreateViewメソッドで簡単に復元できます。
if ((savedInstanceState != null)
&& (savedInstanceState.getSerializable("jsonArray") != null)) {
jsonActList = new JSONArray(savedInstanceState.getString("jsonArray"));
positionList = (ArrayList<String>) savedInstanceState.getSerializable("positionList");
}
このようにして、JSONObjectsをシリアライズ可能またはパーセル可能にする問題に対処する必要がなくなります。
必要なデータをすでに取得している場合は、バンドルからデータを削除するだけです。
// get your data
Bundle bundle = getArguments();
JSONObject myData = (JSONObject) bundle.getSerializable("myData");
// remove it
getArguments().remove("myData");