Domanda

I am working on a app that has 4 tabs, and 1 tab is google map.

When the user click on it , it can create the map correctly, however, if the user leave the current tab by click on other tab, and come back to this tab again, it will throw exception of error inflating layout XML.

So I log the flow, I found that in the onCreateView the second time , rootview is already create, but when I add if (rootView == null) , it still throw error of "need to removeView on child view" . How to fix that? Thanks.

public class Map extends Fragment {
     // Google Map
    private GoogleMap googleMap;
    private boolean isShowRoute;
    private Database db;
    private ArrayList<Restaurant> rList;
    private ArrayList<Spot> sList;

    View rootView;

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        Log.d("test1","" + rootView);
        rootView = inflater.inflate(R.layout.map, container, false);
        return rootView;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        Log.d("test1","b");
        super.onActivityCreated(savedInstanceState);
        db = new Database (getActivity());
        rList = db.getRestaurant();
        sList = db.getSpot();
        try {
            initilizeMap();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * function to load map. If map is not created it will create it for you
     * */
    private void initilizeMap() {
        if (googleMap == null) {
            googleMap = ((MapFragment) getActivity().getFragmentManager().findFragmentById(R.id.map)).getMap();

            // check if map is created successfully or not
            if (googleMap == null) {
                Toast.makeText(getActivity().getApplicationContext(),"Sorry! unable to create maps", Toast.LENGTH_SHORT).show();
            } else {
                googleMap.setMyLocationEnabled(true);
                googleMap.getUiSettings().setCompassEnabled(true);
                googleMap.getUiSettings().setMyLocationButtonEnabled(true); 

                if (isShowRoute)
                    showRoute();
                else
                    pinMap();
            }
        }
    }


    private void showRoute() {
//       if (RunTracker.routePoints.size() > 1){
//          Polyline route = googleMap.addPolyline(new PolylineOptions()
//            .geodesic(true));
//          route.setPoints(RunTracker.routePoints);
//          
//          LatLng lastLatLng = RunTracker.routePoints.get(RunTracker.routePoints.size() - 1);
//          googleMap.addMarker(new MarkerOptions().position(lastLatLng).title("You are here"));
//          googleMap.moveCamera( CameraUpdateFactory.newLatLngZoom(lastLatLng, 16.0f) );
//         }
    }

    private void pinMap() {
        for (Restaurant r : rList) {
            MarkerOptions marker = new MarkerOptions().position(new LatLng(r.lat, r.lng)).title(r.name);
            marker.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE));
            googleMap.addMarker(marker);
        }

        for (Spot s : sList) {
            MarkerOptions marker = new MarkerOptions().position(new LatLng(s.lat, s.lng)).title(s.name);
            marker.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
            googleMap.addMarker(marker);
        }

        googleMap.moveCamera( CameraUpdateFactory.newLatLngZoom(new LatLng(22.3079136,114.1778376), 10.0f) ); // go to MK MTR station by default
    }

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

}

Log cat

03-31 14:53:56.669: E/AndroidRuntime(4611): android.view.InflateException: Binary XML file line #6: Error inflating class fragment

Caused by: java.lang.IllegalArgumentException: Binary XML file line #6: Duplicate id 0x7f050006, tag null, or parent id 0xffffffff with another fragment for com.google.android.gms.maps.MapFragment

Layout

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

    <fragment
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.MapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

Update Code:

   @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onActivityCreated(savedInstanceState);
        db = new Database (getActivity());

        if (rList == null && sList == null) {
            rList = db.getRestaurant();
            sList = db.getSpot();
        }
    }

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

        rootView = inflater.inflate(R.layout.map, container, false);

        try {
            initilizeMap();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return rootView;
    }
È stato utile?

Soluzione

@Override
public void onDestroyView() {
    super.onDestroyView();
    if (mMap != null) {
        getActivity().getSupportFragmentManager().beginTransaction().remove(getActivity().getSupportFragmentManager().findFragmentById(R.id.map)).commit();
        mMap = null;
    }
}

The mapfragment's id must be removed from the FragmentManager or else if the same it is passed on the next time then app will crash

Altri suggerimenti

You can't add fragment inside a fragment. From Android document

Note: You cannot inflate a layout into a fragment when that layout includes a . Nested fragments are only supported when added to a fragment dynamically.

You get MapFragment from activity but after you change tab your fragment's life cycle changed, not activity. When you select tab 1 (MapFragment), it will try to get MapFragment again. So you should try

googleMap = ((MapFragment) getChildFragmentManager().findFragmentById(R.id.map)).getMap();

or you should remove MapFragment from fragment manager of activity.

Link

user782104 is correct that solved my same problem! I'm my case i was using a fragment so its:

@Override
public void onDestroyView() {
    super.onDestroyView();
    if(mMap != null)
    {
        getFragmentManager().beginTransaction().remove(getFragmentManager().findFragmentById(R.id.mapFrag)).commit();
        mMap = null;
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top