SupportMapFragment's getMap() returns null
Asked Answered
P

3

10

I'm trying to create a SupportMapFragment dynamically and to put it in a FrameLayout container.

My issue is that mMapFragment.getMap() returns null...

Anybody can help?

CenterMapFragment.java

public class CenterMapFragment extends Fragment {

    private SupportMapFragment mMapFragment;

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

        return inflater.inflate(R.layout.center_map_fragment, container, false);
    }

    @Override
    public void onActivityCreated (Bundle savedInstanceState){
        super.onActivityCreated(savedInstanceState);

        if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity()) == ConnectionResult.SUCCESS) {
            setUpMapIfNeeded();
        }
    }


    private void setUpMapIfNeeded() {

        if (mMapFragment == null) {

            mMapFragment = SupportMapFragment.newInstance();
            FragmentTransaction fragmentTransaction =
                            getChildFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.map, mMapFragment);
            fragmentTransaction.commit(); 

            setUpMap();
        }
    }

    private void setUpMap() {       

        GoogleMap map = mMapFragment.getMap();  

        // map is null!

    }

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

center_map_fragment.xml

<?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" >

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

    <Button
        android:id="@+id/btn_loc"
        android:layout_width="60dp"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:background="@drawable/locbtn" />

</RelativeLayout>
Pren answered 1/5, 2013 at 16:17 Comment(0)
H
8

commit() on a FragmentTransaction does not perform its operations immediately. By the time you call setUpMap(), onCreateView() will not have been called on the SupportMapFragment, and hence there will not yet be a map.

One approach is to not use nested fragments, electing instead to have CenterMapFragment extend SupportMapFragment, in which case getMap() should work any time after onCreateView() (e.g., onActivityCreated()).

Hippomenes answered 1/5, 2013 at 16:24 Comment(4)
If CenterMapFragment extends SupportMapFragment, how can I set the map to the FrameLayout? I have to change the layout?Pren
@jul: One approach would have CenterMapFragment implement an onCreateView() that called super.onCreateView() first, to get whatever SupportMapFragment creates. Then it would create the FrameLayout and add the super-created View as a child of the FrameLayout. Then it would return the FrameLayout from onCreateView(). This wraps SupportMapFragment's content in whatever CenterMapFragment wants. Or, have CenterMapFragment be just an ordinary Fragment and use MapView instead of SupportMapFragment. Or, find a better time to call setUpMap() with your current code.Hippomenes
@CommonsWare's first approach above is easier than trying to work with MapView directly. MapView requires that you forward it all lifecycle methods to it and run the MapsInitializer.initialize(...) code yourself.Bigotry
extending SupportMapFragment and calling super from onCreateView() is not working. Still NullPointerException~!Robinett
P
2

In the following link MapView is used as CommonsWare suggests in the last part of his comment:

http://ucla.jamesyxu.com/?p=287

public class MapFragment extends Fragment {

    MapView m;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
            Bundle savedInstanceState) {
        // inflat and return the layout
        View v = inflater.inflate(R.layout.map_fragment, container, false);
        m = (MapView) v.findViewById(R.id.mapView);
        m.onCreate(savedInstanceState);

        return v;
    }

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

    @Override
    public void onPause() {
        super.onPause();
        m.onPause();
    }

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

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

I hope these will be helpful.

Phew answered 29/9, 2013 at 15:50 Comment(0)
O
1

Calling

fragmentTransaction.commit();

is asynchronous, the map won't be ready yet when you return from it. Simply call

getFragmentManager().executePendingTransactions();

as the next line, that will make it synchronous and will execute it for the next instruction to pick up the finished map all right. If you're worried about the time it takes, put the whole initialization into an AsyncTask and show a progress indicator to the user while the map is initializing.

Odaniel answered 18/12, 2014 at 10:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.