Pergunta

I have implemented a google map in my android project in a fragment. When I load the fragment the first time it calls an async tasks and loads the markers and displays correctley.

But if I move to another fragment and then come back to the map it crashes once it tries to load again.

My error is:

android.view.InflateException: Binary XML file line #4: Error inflating class fragment
       at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java)
       at android.view.LayoutInflater.inflate(LayoutInflater.java)
       at android.view.LayoutInflater.inflate(LayoutInflater.java)
       at com.beerportfolio.beerportfoliopro.BreweryMap.onCreateView(BreweryMap.java:28)
       at android.support.v4.app.Fragment.performCreateView(Fragment.java:1500)
       at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:938)
       at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1115)
       at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
       at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1478)
       at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:446)
       at android.os.Handler.handleCallback(Handler.java)
       at android.os.Handler.dispatchMessage(Handler.java)
       at android.os.Looper.loop(Looper.java)
       at android.app.ActivityThread.main(ActivityThread.java)
       at java.lang.reflect.Method.invokeNative(Method.java)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
       at dalvik.system.NativeStart.main(NativeStart.java)
Caused by: java.lang.IllegalArgumentException: Binary XML file line #4: Duplicate id 0x7f09003f, tag null, or parent id 0x0 with another fragment for com.google.android.gms.maps.SupportMapFragment
       at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:296)
       at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java)
       at android.view.LayoutInflater.inflate(LayoutInflater.java)
       at android.view.LayoutInflater.inflate(LayoutInflater.java)
       at com.beerportfolio.beerportfoliopro.BreweryMap.onCreateView(BreweryMap.java:28)
       at android.support.v4.app.Fragment.performCreateView(Fragment.java:1500)
       at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:938)
       at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1115)
       at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
       at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1478)
       at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:446)
       at android.os.Handler.handleCallback(Handler.java)
       at android.os.Handler.dispatchMessage(Handler.java)
       at android.os.Looper.loop(Looper.java)
       at android.app.ActivityThread.main(ActivityThread.java)
       at java.lang.reflect.Method.invokeNative(Method.java)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
       at dalvik.system.NativeStart.main(NativeStart.java)

In the error it says something about a duplicate so I assumed it was having trouble re-loading the map markers, so I tried to place a clear markers at the start but that doesn't fix it.

My code for my map is:

public class BreweryMap extends Fragment {

    public BreweryMap(){}

    String beerId = "";

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

        View rootView = inflater.inflate(R.layout.activity_brewmap, container, false);
        setHasOptionsMenu(true);

        //get user information
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
        String userName = prefs.getString("userName", null);
        String userID = prefs.getString("userID", null);


        GoogleMap mMap;
        mMap = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();

        mMap.clear();

        //add url
        String url = "myURL";

        //call async to get breweries to add to
        new GetVisitedBreweries(getActivity(), mMap).execute(url);


        return rootView;
    }

The async tasks gets JSON parses the information and loads the map markers onto the map.

Foi útil?

Solução

From this link..Check it..

you declare the fragment programatically, not in XML. This probably means nesting layouts.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
   android:layout_width="match_parent"
   android:layout_height="match_parent" >

<!-- Lots of fancy layout -->   

<RelativeLayout
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </RelativeLayout>
</RelativeLayout>

Then you need to create your fragment programatically, but it needs to be done carefully with consideration for the Fragments lifecycle (http://developer.android.com/reference/android/app/Fragment.html#getChildFragmentManager()). To ensure everything is created at the right time, your code should look like this.

public class MyFragment extends Fragment {

private SupportMapFragment fragment;
private GoogleMap map;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.layout_with_map, container, false);
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    FragmentManager fm = getChildFragmentManager();
    fragment = (SupportMapFragment) fm.findFragmentById(R.id.map);
    if (fragment == null) {
        fragment = SupportMapFragment.newInstance();
        fm.beginTransaction().replace(R.id.map, fragment).commit();
    }
}

@Override
public void onResume() {
    super.onResume();
    if (map == null) {
        map = fragment.getMap();
        map.addMarker(new MarkerOptions().position(new LatLng(0, 0)));
    }
}
}

Outras dicas

I recently ran into a nearly identical problem and the code below was my solution. You should be able to just rename things and add in your extra code to do what you want to do.

public class TrackerFragment extends Fragment {

private SupportMapFragment mMap;
private GoogleMap googleMap;
//private boolean chronoRunning = false;

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

    activityBody();
    return rootView;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    FragmentManager fm = getChildFragmentManager();
    mMap = (SupportMapFragment) fm.findFragmentById(R.id.map);
    if (mMap == null) {
        mMap = SupportMapFragment.newInstance();
        fm.beginTransaction().replace(R.id.map, mMap).commit();
    }
}

@Override
public void onResume() {
    super.onResume();
    if (googleMap == null) {
        googleMap = mMap.getMap();
        googleMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)));
    }
}

I am too late, but this worked after lot of search

Do It Programmatically, use normal FrameLayout in xml.

SupportMapFragment mapFragment = SupportMapFragment.newInstance();
    FragmentTransaction fragmentTransaction =
            getChildFragmentManager().beginTransaction();
    fragmentTransaction.replace(R.id.map, mapFragment);
    fragmentTransaction.commit();
    mapFragment.getMapAsync(this);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top