谷歌地图代码中的BadParcelableException



运行稍微修改的谷歌地图示例会在谷歌地图代码中抛出BadParcelableExceptionLatLng类是可分包的,但找不到。似乎谷歌地图代码正在尝试解包未由它包裹的对象。什么情况会出现问题?

package com.example.mapdemo;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import android.os.Bundle;
public class RawMapViewDemoActivity extends android.support.v4.app.FragmentActivity {
    private MapView mMapView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.raw_mapview_demo);
        mMapView = (MapView) findViewById(R.id.map);
        mMapView.onCreate(savedInstanceState);
    }
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mMapView.onSaveInstanceState(outState);
        outState.putParcelable("marker", new LatLng(0, 0));
    }
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        LatLng ll = savedInstanceState.getParcelable("marker");
    }
}

FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity 
    ComponentInfo{com.example.mapdemo/com.example.mapdemo.RawMapViewDemoActivity}: 
    android.os.BadParcelableException: ClassNotFoundException when unmarshalling: 
    com.google.android.gms.maps.model.LatLng
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
   at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:2832)
   at android.app.ActivityThread.access$1600(ActivityThread.java:117)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
   at android.os.Handler.dispatchMessage(Handler.java:99)
   at android.os.Looper.loop(Looper.java:130)
   at android.app.ActivityThread.main(ActivityThread.java:3683)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:507)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
   at dalvik.system.NativeStart.main(Native Method)
Caused by: android.os.BadParcelableException: 
ClassNotFoundException when unmarshalling: com.google.android.gms.maps.model.LatLng
   at android.os.Parcel.readParcelable(Parcel.java:1958)
   at android.os.Parcel.readValue(Parcel.java:1846)
   at android.os.Parcel.readMapInternal(Parcel.java:2083)
   at android.os.Bundle.unparcel(Bundle.java:208)
   at android.os.Bundle.getBundle(Bundle.java:1078)
   at com.google.android.gms.maps.internal.MapStateHelper
       .getParcelableFromMapStateBundle(MapStateHelper.java:41)
   at maps.y.ae.a(Unknown Source)
   at maps.y.bm.onCreate(Unknown Source)
   at com.google.android.gms.maps.internal.IMapViewDelegate$Stub
       .onTransact(IMapViewDelegate.java:66)
   at android.os.Binder.transact(Binder.java:279)
   at com.google.android.gms.maps.internal.IMapViewDelegate$a$a
       .onCreate(Unknown Source)
   at com.google.android.gms.maps.MapView$b.onCreate(Unknown Source)
   at com.google.android.gms.internal.c$3.a(Unknown Source)
   at com.google.android.gms.internal.i.b(Unknown Source)
   at com.google.android.gms.maps.MapView$a.a(Unknown Source)
   at com.google.android.gms.maps.MapView$a.a(Unknown Source)
   at com.google.android.gms.internal.c.a(Unknown Source)
   at com.google.android.gms.internal.c.onCreate(Unknown Source)
   at com.google.android.gms.maps.MapView.onCreate(Unknown Source)
   at com.example.mapdemo.RawMapViewDemoActivity
       .onCreate(RawMapViewDemoActivity.java:40)
   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
   ... 12 more

只是为了补充这里的现有答案,在打电话之前,我一直在从保存状态中删除我的包裹mapView.onCreate并且它工作正常。

但是,在我的片段中添加ViewPager后,我没有意识到BadParcelableException已经返回并且代码已投入生产。事实证明,ViewPager也保存了它的状态,并且因为它是支持库的一部分,所以谷歌地图找不到要解包它的类。

因此,我选择反转该过程,而不是从我知道的捆绑包中删除包裹,而是选择创建一个新的捆绑包,用于仅复制地图的状态。

private final static String BUNDLE_KEY_MAP_STATE = "mapData";
@Override
public void onSaveInstanceState(Bundle outState) {
    // Save the map state to it's own bundle
    Bundle mapState = new Bundle();
    mapView.onSaveInstanceState(mapState);
    // Put the map bundle in the main outState
    outState.putBundle(BUNDLE_KEY_MAP_STATE, mapState);
    super.onSaveInstanceState(outState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_map, container, false);
    mapView = (MapView) view.findViewById(R.id.mapView);
    mapView.getMapAsync(this);
    Bundle mapState = null;
    if (savedInstanceState != null) {
        // Load the map state bundle from the main savedInstanceState
        mapState = savedInstanceState.getBundle(BUNDLE_KEY_MAP_STATE);
    }
    mapView.onCreate(mapState);
    return view;
}

我尝试了前两个答案但没有成功,但我找到了另一种解决方法:

保存状态时,在将数据添加到捆绑包之前,请注意转发 MapView.onSaveInstanceState 调用(您做得很好):

@Override
public void onSaveInstanceState(Bundle outState) {
    // Forward the call BEFORE adding our LatLng array, else it will crash :
    _mapView.onSaveInstanceState(outState);
    // Put your Parcelable in the bundle:
    outState.putParcelableArray("myLatLng", new LatLng(0, 0) );
}

在onCreate/onRestore中恢复状态时,请检查捆绑包是否不为空,如果是,请获取您的包裹,然后在转接呼叫之前将其从捆绑包中删除:

@Override
public void onCreate(Bundle savedInstanceState) {
    // If the bundle is not null, get your Parcelable :
    LatLng myLatLng = null;
    if(savedInstanceState != null) {
        myLatLng = (LatLng) savedInstanceState.getParcelable("myLatLng");
        // Remove your Parcelable from the bundle, else it will crash :
        savedInstanceState.remove("myLatLng");
    }
    // Forward the call :
    _mapView.onCreate(savedInstanceState);
    setUpMapIfNeeded();
}

此问题已在此处 code.google.com 提交,以防您想加注星标。

与此同时,我已经设法解决这个问题,只需将我的包裹添加到捆绑包中,然后再将其添加到最终的 onSaveInstanceState 捆绑包中。 这是有效的,因为捆绑包是MapView的内部类加载器的已知类。

创建了两个非常小的实用程序来为我执行此操作。 这是代码

public static Parcelable unbundleParcelable(String key, Bundle src) {
    Bundle b = src.getBundle(key);
    if (b != null) {
        return b.getParcelable("bundle_parcelable_util_key");
    }
    return null;
}
public static void bundleParcelable(String key, Bundle dest, Parcelable parcelable) {
    Bundle b = new Bundle();
    b.putParcelable("bundle_parcelable_util_key", parcelable);
    dest.putBundle(key, b);
}

我已经修改了上一篇文章中的代码以使用我的临时解决方案。 这是我如何使用它。

@Override
public void onSaveInstanceState(Bundle outState) {
    // Forward the call BEFORE adding our LatLng array, else it will crash :
    _mapView.onSaveInstanceState(outState);
    // Put your Parcelable in the bundle:
    bundleParcelable("myLatLng", outState, new LatLng(0, 0));
}
@Override
public void onCreate(Bundle savedInstanceState) {
    // Forward the call :
    _mapView.onCreate(savedInstanceState);
    LatLng myLatLng = null;
    if(savedInstanceState != null) {
        // Extract your Parcelable
        myLatLng = (LatLng) unbundleParcelable("myLatLng", savedInstanceState);
    }
    setUpMapIfNeeded();
}

这应该适用于您在项目中使用的任何自定义包裹。

我找到了一个解决方法(有点)。在它发生的地方,只是尝试第二次这样做。它总是捕获异常,第二次问题似乎没有发生在这个地方。这对我有用。

try {
    mapIntent.putExtra(Intents.EXTRA_LATLNG, new LatLng(
        store.getLatitude(), store.getLongitude()));
} catch (BadParcelableException e) {
    mapIntent.putExtra(Intents.EXTRA_LATLNG, new LatLng(
        store.getLatitude(), store.getLongitude()));
}

我找到了更简单的解决方法。在执行任何操作之前,将片段或活动的类装入器提供给捆绑包:

savedInstanceState.setClassLoader(getClass().getClassLoader());

当直接传递到MapFragment或MapView的onCreateView或onCreate时,这似乎不起作用,因此您必须手动划分地图的CameraPosition并将空捆绑包传递到这些函数中。

当我离开我的应用程序时,我还有一个BadParcelableException(FragmentActivity带有选项卡,每个选项卡中都有一个Fragment)。我通过先打电话mapmpvMap.onSaveInstanceState(outState);然后打电话super.onSaveInstanceState(outState);来解决这个问题

相关内容

  • 没有找到相关文章

最新更新