Search code examples
android-maps-v2android-mapsandroid-maps-extensions

How to reuse SupportMapFragment inside other Fragment


I just switched to the newest version of android-maps-extensions (2.2.0) together with newest Play Services (6.5.87) and support library (21.0.3). And now I can't reuse my MapFragment.

I have MainActivity with NavigationDrawer. One of the fragments is fragment with GoogleMap fragment inside. When I switch between fragments in NavigationDrawer they recreate themselves. Previously I used very simply solution for this. I used already inflated view:

 public View onCreateView(LayoutInflater inflater, ViewGroup container, final Bundle savedInstanceState) {
    super.onCreateView(inflater, container, savedInstanceState);
    if (view != null) {
        ViewGroup parent = (ViewGroup) view.getParent();
        if (parent != null) {
            parent.removeView(view);
        }
        return view;
    }
    view = inflater.inflate(R.layout.fragment_map, container, false);

    SupportMapFragment mapFragment = SupportMapFragment.newInstance();
    FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
    transaction.add(R.id.container, mapFragment).commit();

    mapFragment.getExtendedMapAsync(new OnMapReadyCallback() {
        public void onMapReady(GoogleMap googleMap) {
            map = googleMap;
            setupMap();
        }
    });

    return view;
}

But now it doesn't work. Map doesn't show when this fragment opens second time.

I can just throw out this ugly code

 if (view != null) {
        ViewGroup parent = (ViewGroup) view.getParent();
        if (parent != null) {
            parent.removeView(view);
        }
        return view;
    }

And always recreate view with inside. But I have thousands of Markers (of course with awesome Clustering) and it takes many time to repaint them.

I know it's not the problem of extensions-library, Google Maps have the same behavior. But maybe you know right decision?


Solution

  • Instead of using MapFragment we can use MapView, that exists in androidmapsextensions too. And it can be reused.

    Since adding MapView programatically, need to call mapView.onCreate(bundle)

    private MapView mapView;
    
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        View view = inflater.inflate(R.layout.fragment_map, container, false);
    
        if (mapView != null) {        
            ViewGroup parentViewGroup = (ViewGroup) mapView.getParent();
            if (parentViewGroup != null) {
                parentViewGroup.removeView(mapView);            
            }
        } else {
            mapView = new MapView(getActivity());
            mapView.onCreate(Bundle.EMPTY); //need if programmatically add 
        }    
    
        ((ViewGroup)view.findViewById(R.id.container)).addView(mapView);
    
        mapView.getExtendedMapAsync(new OnMapReadyCallback() {
            public void onMapReady(GoogleMap googleMap) {
                setUpMap(GoogleMap);
            }
        });    
    }    
    

    Or if we don't need any setup for reused mapView

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        View view = inflater.inflate(R.layout.fragment_map, container, false);
    
        boolean needSetupMap = true;
        if (mapView != null) {        
            ViewGroup parentViewGroup = (ViewGroup) mapView.getParent();
            if (parentViewGroup != null) {
                parentViewGroup.removeView(mapView);
                needSetupMap = false;
            }
        } else {
            mapView = new MapView(getActivity());
            mapView.onCreate(Bundle.EMPTY);
        }  
    
        ((ViewGroup)view.findViewById(R.id.container)).addView(mapView);
    
        if (needSetupMap) {
            mapView.getExtendedMapAsync(new OnMapReadyCallback() {
                public void onMapReady(GoogleMap googleMap) {
                    setUpMap(GoogleMap);
                }
            });
        }
    }