Fragment 与 Parcel 一起崩溃:调用 onPause 方法时无法编组值错误
Posted
技术标签:
【中文标题】Fragment 与 Parcel 一起崩溃:调用 onPause 方法时无法编组值错误【英文标题】:Fragment crashes with Parcel: unable to marshal value error when onPause method is called 【发布时间】:2014-08-13 14:11:16 【问题描述】:我已经开发 android 应用程序有一段时间了,但最近才接触到 Fragments,因此在学习如何使用它们时遇到了很多问题。我的应用程序中的一个活动有四个不同的片段,每个片段都向用户显示一个项目列表。每个片段都是首先创建的,并且仅在选择时显示一次,并在选择另一个选项卡时隐藏。一旦创建了这些片段中的每一个,就会将 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;
在片段中接收到数组列表,一切正常。
actList = (ArrayList<JSONObject>) getArguments().getSerializable("array");
doingAdapter = new DoingAdapter(getActivity(), actList);
actListView.setAdapter(doingAdapter);
父 Activity 中有一个按钮可以启动设备摄像头。一旦发生这种情况并且片段中的 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)
我一直在 *** 中四处寻找,确实看到了一些与我的问题类似的问题,但是我似乎无法从其中任何一个问题中得到任何可以帮助我解决我的情况的问题。我确实了解片段试图保存其状态并且无法序列化我的 json 对象的问题的要点,但如果有人可以帮助我使用 Serializable 或 Parcelable 接口来解决我的问题,那就太好了,那就是伟大的。我还按照其他人的建议在片段和活动中实现了可序列化。
【问题讨论】:
【参考方案1】:如果您已经获得所需的数据,则只需从捆绑包中删除数据。
// get your data
Bundle bundle = getArguments();
JSONObject myData = (JSONObject) bundle.getSerializable("myData");
// remove it
getArguments().remove("myData");
【讨论】:
这听起来确实是个不错的方法 我现在很确定,通过从我的包中清除每个值,我不再收到编组错误,但有人可以解释为什么必须删除每个值,即使包在被读取后不再被触及?很好奇! 我在开始一些活动时遇到了这个错误,但是这个有效。谢谢 很好的答案,直到得到这个答案,我才能修复这个错误。为什么需要从包中删除数据?【参考方案2】:好吧,我设法解决了这个问题,它可能不是最标准的做事方式,但它确实解决了我的问题,并且可能在一定程度上帮助其他人。
我所做的不是将从 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 并将其转换为 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)
&& (savedInstanceState.getSerializable("jsonArray") != null))
jsonActList = new JSONArray(savedInstanceState.getString("jsonArray"));
positionList = (ArrayList<String>) savedInstanceState.getSerializable("positionList");
这样我就不必处理使我的 JSONObjects Serializable 或 Parcelable 的问题
【讨论】:
以上是关于Fragment 与 Parcel 一起崩溃:调用 onPause 方法时无法编组值错误的主要内容,如果未能解决你的问题,请参考以下文章
如何将 Service Worker 库 (MSW) 与 Parcel 捆绑器一起使用
从 Activity 调用 Fragment 时应用程序崩溃
如何将 jQuery 和 jQuery-ui 与 Parcel(捆绑器)一起使用?
在从 Fragment 内的 RecyclerView 的 ViewHolder 调用的 startActivity(intent) 中使用 putExtra 时,应用程序崩溃