0

I'm getting a Null Pointer Exception when trying to set the map type after committing the MapFragment and getting a reference to its map with getMap().

I think the cause of the error is that the fragment hasn't been initialized yet and therefore I can't set the map type.

How can I know when this fragment has been initialized and I am allowed to call its public methods? Is there an interface that I can implement in my MainActivity to know when the fragment has loaded?

Furthermore, why am I allowed to call getMap() on mMapFragment if it is not yet initialized? Is it actually just the GoogleMap object that's not properly initialized?

Here's my code:

public class MainActivity extends Activity {

    private static final String LOG_TAG = MainActivity.class.getSimpleName();
    private FragmentManager fm;
    private MapFragment mMapFragment;
    private GoogleMap mGoogleMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_container);

        fm = getFragmentManager();
        mMapFragment = MapFragment.newInstance();

        fm.beginTransaction().add(R.id.fragment_container, mMapFragment).commit();
        mGoogleMap = mMapFragment.getMap();

        mGoogleMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
    }
}

And the XML for main_container:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

</FrameLayout>

And here's the LogCat output:

10-09 11:17:16.457: E/AndroidRuntime(31679): FATAL EXCEPTION: main
10-09 11:17:16.457: E/AndroidRuntime(31679): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.matthewlogan.loopfinder/com.matthewlogan.loopfinder.MainActivity}: java.lang.NullPointerException
10-09 11:17:16.457: E/AndroidRuntime(31679):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2248)
10-09 11:17:16.457: E/AndroidRuntime(31679):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2298)
10-09 11:17:16.457: E/AndroidRuntime(31679):    at android.app.ActivityThread.access$600(ActivityThread.java:142)
10-09 11:17:16.457: E/AndroidRuntime(31679):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1285)
10-09 11:17:16.457: E/AndroidRuntime(31679):    at android.os.Handler.dispatchMessage(Handler.java:99)
10-09 11:17:16.457: E/AndroidRuntime(31679):    at android.os.Looper.loop(Looper.java:137)
10-09 11:17:16.457: E/AndroidRuntime(31679):    at android.app.ActivityThread.main(ActivityThread.java:5270)
10-09 11:17:16.457: E/AndroidRuntime(31679):    at java.lang.reflect.Method.invokeNative(Native Method)
10-09 11:17:16.457: E/AndroidRuntime(31679):    at java.lang.reflect.Method.invoke(Method.java:525)
10-09 11:17:16.457: E/AndroidRuntime(31679):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:974)
10-09 11:17:16.457: E/AndroidRuntime(31679):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:790)
10-09 11:17:16.457: E/AndroidRuntime(31679):    at dalvik.system.NativeStart.main(Native Method)
10-09 11:17:16.457: E/AndroidRuntime(31679): Caused by: java.lang.NullPointerException
10-09 11:17:16.457: E/AndroidRuntime(31679):    at com.matthewlogan.loopfinder.MainActivity.onCreate(MainActivity.java:36)
10-09 11:17:16.457: E/AndroidRuntime(31679):    at android.app.Activity.performCreate(Activity.java:5133)
10-09 11:17:16.457: E/AndroidRuntime(31679):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1098)
10-09 11:17:16.457: E/AndroidRuntime(31679):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2212)
10-09 11:17:16.457: E/AndroidRuntime(31679):    ... 11 more
4

2 回答 2

3

MapFragmentGoogleMap通过代码创建的 's在以下情况下准备就绪:

  1. onCreateView已经回来了
  2. Google Play 服务应用已安装且版本正确

GoogleMap如果你想在你的 中获得非空值Activity,请在onResume

if (mGoogleMap == null) {
    mGoogleMap = mMapFragment.getMap();
    if (mGoogleMap != null) {
        initMap();
    }
}

Double ifs ensure每个实例仅initMap调用一次,并且仅在准备好时调用。这是一种正确的处理方式,因为可以在用户安装 Google Play 服务并返回您的应用程序(第二次调用)后准备就绪。ActivityGoogleMapGoogleMaponResume

于 2013-10-09T20:31:01.340 回答
1

我怎么知道这个片段何时被初始化并且我被允许调用它的公共方法?

在其生命周期方法之一中配置地图片段,例如onActivityCreated().

或者,不使用 a ,而是在布局中FragmentTransaction使用<fragment>标签。

于 2013-10-09T18:35:30.923 回答