【问题标题】:MapView crashes in fragment with Coordinator layout, when changing configuration更改配置时,MapView 在具有协调器布局的片段中崩溃
【发布时间】:2016-08-23 12:12:02
【问题描述】:

我的 MapViewCoordinatorLayout 的自定义片段存在问题。我做了一个简单的应用程序来说明这一点。我也尝试在标准的 Google API 演示中做同样的事情,但没有出现任何问题,但可能是因为他们使用的是 MapFragment 而不是 MapView

下面,我已经上传了代码和布局。最后还有一个错误跟踪也被粘贴了。

public class BlankFragment extends Fragment implements OnMapReadyCallback {

    private MapView mapView;
    private Bundle BundleForMap;

    @Override
    public void onMapReady(GoogleMap googleMap) { }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        BundleForMap = savedInstanceState;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_blank, container, false);

        mapView = (MapView) view.findViewById(R.id.map_event_mapview);
        mapView.onCreate(BundleForMap);
        mapView.getMapAsync(this);
        return view;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
    }

    @Override
    public void onDetach() {
        super.onDetach();
    }

    @Override
    public void onResume() {
        super.onResume();
        mapView.onResume();
    }

    @Override
    public void onPause() {

        super.onPause();
        mapView.onPause();
    }

    @Override
    public void onDestroy() {
        mapView.onDestroy();
        super.onDestroy();
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        mapView.onLowMemory();
    }

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        mapView.onSaveInstanceState(savedInstanceState);
        super.onSaveInstanceState(savedInstanceState);
    }

}

Activity 只是调用该片段并用它替换容器视图:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

        BlankFragment blankFragment = new BlankFragment();
        fragmentTransaction.replace(R.id.container, blankFragment, "");

        fragmentTransaction.commit();

    }

这是片段布局:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.mapview_test.BlankFragment">

    <com.google.android.gms.maps.MapView
        android:id="@+id/map_event_mapview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/map_event_bottom_sheet"
        android:layout_height="match_parent"
        android:layout_width="match_parent" >

        <android.support.v4.widget.NestedScrollView
            android:id="@+id/bottom_sheet"
            android:layout_width="match_parent"
            android:layout_height="175dp"
            android:elevation="16dp"
            android:outlineProvider="bounds"
            android:background="@android:color/white"
            >

            <TextView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:padding="16dp"
                android:textSize="16sp"
                android:id="@+id/testText"/>

        </android.support.v4.widget.NestedScrollView>

    </android.support.design.widget.CoordinatorLayout>

</FrameLayout>

问题显然在于 Coordinator 布局以及它是如何打包的。

Process: com.example.alovita.mapview_test, PID: 12989
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.alovita.mapview_test/com.example.alovita.mapview_test.MainActivity}: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: android.support.design.widget.CoordinatorLayout$SavedState
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2370)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2432)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3992)
at android.app.ActivityThread.access$1000(ActivityThread.java:154)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1327)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5310)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
Caused by: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: android.support.design.widget.CoordinatorLayout$SavedState
at android.os.Parcel.readParcelableCreator(Parcel.java:2295)
at android.os.Parcel.readParcelable(Parcel.java:2245)
at android.os.Parcel.readValue(Parcel.java:2152)
at android.os.Parcel.readSparseArrayInternal(Parcel.java:2546)
at android.os.Parcel.readSparseArray(Parcel.java:1874)
at android.os.Parcel.readValue(Parcel.java:2209)
at android.os.Parcel.readArrayMapInternal(Parcel.java:2485)
at android.os.BaseBundle.unparcel(BaseBundle.java:221)
at android.os.Bundle.getBundle(Bundle.java:733)
at aac.a(:com.google.android.gms.DynamiteModulesB:74)
at maps.ad.u.a(Unknown Source)
at maps.ad.R.a(Unknown Source)
at wc.onTransact(:com.google.android.gms.DynamiteModulesB:66)
at android.os.Binder.transact(Binder.java:380)
at com.google.android.gms.maps.internal.IMapViewDelegate$zza$zza.onCreate(Unknown Source)
at com.google.android.gms.maps.MapView$zza.onCreate(Unknown Source)
at com.google.android.gms.dynamic.zza$3.zzb(Unknown Source)
at com.google.android.gms.dynamic.zza$1.zza(Unknown Source)
at com.google.android.gms.maps.MapView$zzb.zzbow(Unknown Source)
at com.google.android.gms.maps.MapView$zzb.zza(Unknown Source)
at com.google.android.gms.dynamic.zza.zza(Unknown Source)
at com.google.android.gms.dynamic.zza.onCreate(Unknown Source)
at com.google.android.gms.maps.MapView.onCreate(Unknown Source)
at com.example.alovita.mapview_test.BlankFragment.onCreateView(BlankFragment.java:45)
at android.app.Fragment.performCreateView(Fragment.java:2053)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:894)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1049)
at android.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1869)
at android.app.Activity.performCreateCommon(Activity.java:6860)
at android.app.Activity.performCreate(Activity.java:6867)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2323)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2432) 
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3992) 
at android.app.ActivityThread.access$1000(ActivityThread.java:154) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1327) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:135) 
at android.app.ActivityThread.main(ActivityThread.java:5310) 
at java.lang.reflect.Method.invoke(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:372) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699) 

问题出在这一行:

mapView.onCreate(BundleForMap);

当屏幕配置发生变化时,这个参数明显不是null,导致app崩溃。当在这里传递null 而不是捆绑时,它工作正常。当我删除 CoordinatorLayout 时,应用程序运行正常。

这是我的依赖项:

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.1"

    defaultConfig {
        applicationId "com.example.mapview_test"
        minSdkVersion 22
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:24.2.0'
    compile 'com.android.support:support-v4:24.2.0'
    compile 'com.android.support:recyclerview-v7:24.2.0'
    compile 'com.android.support:design:24.2.0'
    compile 'com.google.android.gms:play-services-appindexing:9.4.0'
    compile 'com.google.android.gms:play-services-maps:9.4.0'
    compile 'com.google.android.gms:play-services-location:9.4.0'
}

我长期以来一直坚持这一点。任何帮助将不胜感激

【问题讨论】:

    标签: android android-layout android-view android-mapview android-coordinatorlayout


    【解决方案1】:

    这似乎是众所周知的问题:Android Issue 6237

    我已经根据这个答案实现了自己的解决方案:Android Issue 6237 #C9

    实现如下(基于#C9的回答):

    我能够通过将 MapView 的已保存状态保存在单独的 Bundle 中,然后将其添加到传出的已保存状态束中来绕过它。然后在 onCreate() 中,我只需从传入的 MapView 中获取已保存的状态并将其传递给它的 onCreate() 方法,从而停止崩溃。

    @Override
        public void onSaveInstanceState(Bundle savedInstanceState) {
            final Bundle mapViewSaveState = new Bundle(savedInstanceState);
            mapView.onSaveInstanceState(mapViewSaveState);
            savedInstanceState.putBundle("mapViewSaveState", mapViewSaveState);
    
            Bundle customBundle = new Bundle();
            // put custom objects if needed to customBundle
    
            savedInstanceState.putBundle(ARG_CUSTOM_BUNDLE, customBundle);
            super.onSaveInstanceState(savedInstanceState);
        }
    

    然后,在onCreate 中使用mapViewSaveState(如果是片段,则使用onCreateView):

    mapView.onCreate(savedInstanceState != null ? savedInstanceState.getBundle("mapViewSaveState") : null);
    

    【讨论】:

    • 我在Activity 中遇到了同样的问题,其中DrawerLayout 包含FrameLayout,而我的Fragment 包含MapView 只是一个FrameLayout.. .这似乎已经解决了,所以谢谢!我不知道你是怎么想出来的!
    猜你喜欢
    • 2011-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-02
    • 2019-02-20
    • 1970-01-01
    相关资源
    最近更新 更多