#android #android-fragments #serializable #jsonobject
#Android #android-фрагменты #сериализуемый #json
Вопрос:
Я уже некоторое время разрабатываю приложения для Android, но только недавно попал во фрагменты, и поэтому у меня возникает много проблем с обучением работе с ними. Одно из действий в моих приложениях содержит четыре разных фрагмента, каждый из которых отображает список элементов для пользователя. Каждый фрагмент создается сначала и отображается только после выбора и скрытия при выборе другой вкладки. После создания каждого из этих фрагментов в качестве аргумента фрагменту передается ArrayList JSONObjects следующим образом
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;
Во фрагменте получен список массивов, и все работает просто отлично.
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, но было бы здорово, если бы кто-нибудь мог помочь мне работать с сериализуемыми или разделяемыми интерфейсами, чтобы исправить мою проблему, это было бы здорово. Также я реализовал сериализуемость как во фрагменте, так и в действии, как это было предложено другими.
Ответ №1:
Если вы уже получили нужные вам данные, просто удалите данные из пакета.
// get your data
Bundle bundle = getArguments();
JSONObject myData = (JSONObject) bundle.getSerializable("myData");
// remove it
getArguments().remove("myData");
Комментарии:
1. Это звучит как отличный способ сделать это
2. Теперь я уверен, что, удаляя каждое значение из моего пакета, я больше не получаю ошибок маршалирования, но не мог бы кто-нибудь объяснить, почему каждое значение должно быть удалено, даже если пакет больше не трогается после считывания? Очень любопытно!
3. я получал эту ошибку, когда запускал какое-либо действие, но это сработало. Спасибо
4. Отличный ответ, я не мог исправить эту ошибку до этого ответа. Почему необходимо удалять данные из пакета?
Ответ №2:
Что ж, мне удалось найти выход из этого, возможно, это не самый стандартный способ ведения дел, но на самом деле он решил мою проблему и может в какой-то степени помочь другим.
Вместо преобразования JSONArray, полученного из API, в массив JSON arraylist, а затем отправки его во фрагмент, я преобразовал массив 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 и преобразовал его в массив JSONObject ArrayList . И чтобы сохранить изменения, внесенные в мой список после использования фрагмента, я преобразовал 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)
amp;amp; (savedInstanceState.getSerializable("jsonArray") != null)) {
jsonActList = new JSONArray(savedInstanceState.getString("jsonArray"));
positionList = (ArrayList<String>) savedInstanceState.getSerializable("positionList");
}
Таким образом, мне не пришлось бы решать проблему с сериализуемостью или разделяемостью моих JSONObjects