Android InflateException Error in fragment layout with SupportMapFragment (recreated fragment)

烈酒焚心 提交于 2020-01-06 19:58:08

问题


All more or less works. But if the LocationFragment is recreated, the application falls.

Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest package="XX.XX.XXXXXXXX"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

<uses-feature
    android:glEsVersion="0x00020000"
    android:required="true"/>

<uses-feature android:name="android.hardware.camera"
    android:required="true" />

<application
    android:name=".App"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme">

    <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="@string/google_maps_key"/>

    <meta-data android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version"/>

    <activity
        android:name=".ui.activities.LaunchActivity"
        android:label="@string/app_name"
        android:screenOrientation="portrait"
        android:theme="@style/AppTheme.FullScreen"
        android:windowSoftInputMode="stateAlwaysHidden|adjustResize">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>

            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>
    <activity android:name=".ui.activities.MainActivity"
        android:screenOrientation="portrait"
        android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"/>
    <activity android:name=".ui.activities.SettingsActivity"
        android:screenOrientation="portrait"
        android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"/>
    <activity android:name="com.facebook.FacebookActivity"
        android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
        android:theme="@android:style/Theme.Translucent.NoTitleBar"
        android:label="@string/app_name" />

    <meta-data
        android:name="com.crashlytics.ApiKey"
        android:value="XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"/>

    <meta-data
        android:name="com.facebook.sdk.ApplicationId"
        android:value="@string/facebook_app_id"/>
</application>

public enum GeolocationState

import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import android.widget.Toast;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;

import java.io.IOException;
import java.util.List;
import java.util.Locale;

public enum GeolocationState  {
    INST;

private static final String TAG = "Geolocation";

public static final long WAITING_TIME_MILLIS = 3000L;
public static final float ACCURANCY_IN_METERS = 3f;

private Context context;
private LocationManager locationManager;
private Geocoder geocoder;

public void init(Context context) {
    this.context = context;
    locationManager = (LocationManager)     context.getSystemService(Context.LOCATION_SERVICE);
    geocoder = new Geocoder(context, Locale.getDefault());
}

public Address getAddress(Location location) {
    try {
        List<Address> addressList = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);

        if (addressList != null && !addressList.isEmpty()) {
            return addressList.get(0);
        }

    } catch (IOException e) {
        e.printStackTrace();
        Toast.makeText(context, "Помилка геопозиціонування", Toast.LENGTH_SHORT).show();
    }
    return null;
}

public void mapPositioning(GoogleMap mMap, double latitude, double longitude){
    LatLng coordinates = new LatLng(latitude, longitude);
    if(mMap!=null) {
        mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(coordinates, 13));
        CameraPosition cameraPosition = new CameraPosition.Builder()
                .target(coordinates)
                .zoom(17)
                .bearing(90)
                .tilt(0)
                .build();

            mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
        }
    }

    public LocationManager getLocationManager() {
        return locationManager;
    }
}

public class LocationFragment

import android.location.Address;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;

import java.text.DecimalFormat;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import xx.xx.xxxxxxxx.R;
import xx.xx.xxxxxxxx.services.ClaimState;
import xx.xx.xxxxxxxx.services.GeolocationState;
import xx.xx.xxxxxxxx.ui.activities.MainActivity;

public class LocationFragment extends BaseFragment implements OnMapReadyCallback, GoogleMap.OnMyLocationButtonClickListener{

private static final String TAG = LocationFragment.class.getName();

private GoogleMap mMap;
@BindView(R.id.positioning_text_view)
TextView positioningText;
@BindView(R.id.next_button)
Button nextButton;
private Unbinder unbinder;

public static Fragment newInstance() {
    return new LocationFragment();
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    View rootView = inflater.inflate(R.layout.fragment_location, container, false); 
//**INFLATE ERROR IN rootView WHEN YOU MOVE QUICKLY BETWEEN FRAGMENTS**
    unbinder = ButterKnife.bind(this, rootView);

    SupportMapFragment fragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
    fragment.getMapAsync(this);

    return rootView;
}

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    nextButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            ((MainActivity) getActivity()).moveToNext();
        }
    });
    nextButton.setVisibility(View.GONE);
}

@Override
public void onResume() {
    super.onResume();
    GeolocationState.INST.getLocationManager().requestLocationUpdates(
            LocationManager.GPS_PROVIDER,
            GeolocationState.WAITING_TIME_MILLIS,
            GeolocationState.ACCURANCY_IN_METERS,
            locationListener);
}

@Override
public void onPause() {
    super.onPause();
    GeolocationState.INST.getLocationManager().removeUpdates(locationListener);
}

private LocationListener locationListener = new LocationListener() {
    @Override
    public void onLocationChanged(Location location) {
        if(location != null && mMap != null) {
            Address address = GeolocationState.INST.getAddress(location);

            if (address != null) {
                ClaimState.INST.getClaim().setCity(address.getLocality());
                ClaimState.INST.getClaim().setAddress(address.getAddressLine(0));
                positioningText.setText(ClaimState.INST.getFullAddress());
                nextButton.setVisibility(View.VISIBLE);
            }

            DecimalFormat df = new DecimalFormat("#.######");
            ClaimState.INST.getClaim().setLatitude(df.format(location.getLatitude()).replace(",", "."));
            ClaimState.INST.getClaim().setLongitude(df.format(location.getLongitude()).replace(",", "."));
            GeolocationState.INST.mapPositioning(mMap, location.getLatitude(), location.getLongitude());
        }
    }

    @Override
    public void onProviderDisabled(String provider) {
    }

    @Override
    public void onProviderEnabled(String provider) {
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    }
};

@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    if(mMap != null) {
        mMap.setMyLocationEnabled(true);
        mMap.setOnMyLocationButtonClickListener(this);
        mMap.getUiSettings().setCompassEnabled(false);
    }
}

@Override
public boolean onMyLocationButtonClick() {
    return false;
}

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser && isResumed()){
        Toast toast = Toast.makeText(getContext(), "Bla-bla-bla", Toast.LENGTH_LONG);
        LinearLayout layout = (LinearLayout) toast.getView();
        if (layout.getChildCount() > 0) {
            TextView tv = (TextView) layout.getChildAt(0);
            tv.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
        }
        toast.setGravity(Gravity.CENTER, 0, 0);
        toast.show();
    }
}

@Override public void onDestroyView() {
    super.onDestroyView();
    unbinder.unbind();
}
}

fragment_location.xml (Layout)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent">


<RelativeLayout
    android:id="@+id/bottomPanel"
    android:layout_width="match_parent"
    android:layout_height="130dp"
    android:layout_alignParentBottom="true"
    android:background="@color/primaryColor">

    <TextView
        android:id="@+id/positioning_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="10dp"
        android:text="@string/positioning_in_progress"
        android:textColor="@android:color/white"
        android:textSize="17sp"/>

    <Button
        android:id="@+id/next_button"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_marginBottom="20dp"
        android:layout_marginRight="20dp"
        android:background="@drawable/button_background"
        android:paddingLeft="45dp"
        android:paddingRight="45dp"
        android:text="@string/next"
        android:textAllCaps="false"
        android:textSize="17sp"
        />
</RelativeLayout>

<fragment
    android:id="@+id/map"
    class="com.google.android.gms.maps.SupportMapFragment"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_above="@+id/bottomPanel"
    android:layout_alignParentTop="true" />

</RelativeLayout>

printStackTrace

07-28 13:17:57.257 28765-28765/xx.xx.xxxxxxxx E/AndroidRuntime: FATAL EXCEPTION: main
                                                              Process: xx.xx.xxxxxxxx, PID: 28765
                                                              android.view.InflateException: Binary XML file line #40: Binary XML file line #40: Error inflating class fragment
                                                                  at android.view.LayoutInflater.inflate(LayoutInflater.java:539)
                                                                  at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
                                                                  at xx.xx.xxxxxxxx.ui.fragments.LocationFragment.onCreateView(LocationFragment.java:55)
                                                                  at android.support.v4.app.Fragment.performCreateView(Fragment.java:1974)
                                                                  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
                                                                  at android.support.v4.app.FragmentManagerImpl.attachFragment(FragmentManager.java:1430)
                                                                  at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:732)
                                                                  at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617)
                                                                  at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:570)
                                                                  at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
                                                                  at android.support.v4.view.ViewPager.populate(ViewPager.java:1177)
                                                                  at android.support.v4.view.ViewPager.populate(ViewPager.java:1025)
                                                                  at android.support.v4.view.ViewPager$3.run(ViewPager.java:254)
                                                                  at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
                                                                  at android.view.Choreographer.doCallbacks(Choreographer.java:670)
                                                                  at android.view.Choreographer.doFrame(Choreographer.java:603)
                                                                  at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
                                                                  at android.os.Handler.handleCallback(Handler.java:739)
                                                                  at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                  at android.os.Looper.loop(Looper.java:148)
                                                                  at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                  at java.lang.reflect.Method.invoke(Native Method)
                                                                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
                                                               Caused by: android.view.InflateException: Binary XML file line #40: Error inflating class fragment
                                                                  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:782)
                                                                  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
                                                                  at android.view.LayoutInflater.rInflate(LayoutInflater.java:835)
                                                                  at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798)
                                                                  at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
                                                                  at android.view.LayoutInflater.inflate(LayoutInflater.java:423) 
                                                                  at xx.xx.xxxxxxxx.ui.fragments.LocationFragment.onCreateView(LocationFragment.java:55) 
                                                                  at android.support.v4.app.Fragment.performCreateView(Fragment.java:1974) 
                                                                  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067) 
                                                                  at android.support.v4.app.FragmentManagerImpl.attachFragment(FragmentManager.java:1430) 
                                                                  at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:732) 
                                                                  at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617) 
                                                                  at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:570) 
                                                                  at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141) 
                                                                  at android.support.v4.view.ViewPager.populate(ViewPager.java:1177) 
                                                                  at android.support.v4.view.ViewPager.populate(ViewPager.java:1025) 
                                                                  at android.support.v4.view.ViewPager$3.run(ViewPager.java:254) 
                                                                  at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858) 
                                                                  at android.view.Choreographer.doCallbacks(Choreographer.java:670) 
                                                                  at android.view.Choreographer.doFrame(Choreographer.java:603) 
                                                                  at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844) 
                                                                  at android.os.Handler.handleCallback(Handler.java:739) 
                                                                  at android.os.Handler.dispatchMessage(Handler.java:95) 
                                                                  at android.os.Looper.loop(Looper.java:148) 
                                                                  at android.app.ActivityThread.main(ActivityThread.java:5417) 
                                                                  at java.lang.reflect.Method.invoke(Native Method) 
                                                                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                                                                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
                                                               Caused by: java.lang.IllegalArgumentException: Binary XML file line #40: Duplicate id 0x7f0e0104, tag null, or parent id 0xffffffff with another fragment for com.google.android.gms.maps.SupportMapFragment
                                                                  at android.support.v4.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2293)
                                                                  at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:44)
                                                                  at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:186)
                                                                  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:746)
                                                                  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704) 
                                                                  at android.view.LayoutInflater.rInflate(LayoutInflater.java:835) 
                                                                  at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) 
                                                                  at android.view.LayoutInflater.inflate(LayoutInflater.java:515) 
                                                                  at android.view.LayoutInflater.inflate(LayoutInflater.java:423) 
                                                                  at xx.xx.xxxxxxxx.ui.fragments.LocationFragment.onCreateView(LocationFragment.java:55) 
                                                                  at android.support.v4.app.Fragment.performCreateView(Fragment.java:1974) 
                                                                  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067) 
                                                                  at android.support.v4.app.FragmentManagerImpl.attachFragment(FragmentManager.java:1430) 
.....

UPD: I have 4 fragments

CaptureFragment(1) - TypeFragment(2) - LocationFragment(3) - OverviewFragment(4)

When I quickly move between:

TypeFragment - LocationFragment

or

LocationFragment - OverviewFragment

all is ok.

But if I move CaptureFragment(1) -> TypeFragment(2) -> LocationFragment(3)

then

LocationFragment(3) -> TypeFragment(2) -> CaptureFragment(1)

then

CaptureFragment(1) -> TypeFragment(2)

it breaks.

I know that when the TypeFragment is created, it is created and the next activity CaptureFragment. At this point, the application falls.

Does anyone know how to fix it?


回答1:


This is how I load my map layout in a fragment:

private View view;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    if (view != null) {
        ViewGroup parent = (ViewGroup) view.getParent();
        if (parent != null)
            parent.removeView(view);
    }

    try {
        view = inflater.inflate(R.layout.map_fragment_location, container, false);
    } catch (InflateException e) {
        /* map is already there, just return view as it is */
    }

    ButterKnife.bind(this, view);

    SupportMapFragment mapFragment = (SupportMapFragment)getChildFragmentManager().findFragmentById(R.id.map);

    mapFragment.getMapAsync(this);

    return view;
}

This helps check your layout and if it already exists, you don't have to create again!

Please try it and let me know how it goes!




回答2:


It helped me

    private static View rootView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

        if (rootView == null) {
            rootView = inflater.inflate(R.layout.fragment_location, container, false);
        }

        unbinder = ButterKnife.bind(this, rootView);
        return rootView;
    }

LocationFragment and SupportMapFragment work correctly.

Maybe it's not the best solution. If you know a better solution, please share it.



来源:https://stackoverflow.com/questions/38637778/android-inflateexception-error-in-fragment-layout-with-supportmapfragment-recre

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!