findFragmentById always returns a null

2019-02-25 06:36发布

问题:

I'm using an actionbar in navigation mode in the mainActivity. Different tabs has different layouts, and on one of these tabs, I embed a layout which has a MapFragment inside. With the following code, the app works well, the mapFragments works fine, the tabs works fine. However, once I want to get access the mapFragment embeded in myFragment use getFragmentManager().findFragmentById(R.id.map_add), I always get null.

I've tried using FragmentManager and FragmentTransaction to add myfragment and the MapFragment, but still get null from findFragmentById(R.id.map_add). Please help...

The MainActivity initialized like this:

protected void onCreate(Bundle bundle) {
    super.onCreate(bundle);
    setContentView(R.layout.main);

    // ActionBar gets initiated
    ActionBar actionbar = getActionBar();
    // Tell the ActionBar we want to use Tabs.
    actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    // initiating the tabs and set text to it.
    ActionBar.Tab myTab = actionbar.newTab().setText("hey");

    // create the fragments we want to use for display content
    Fragment myFragment = new myFragment();

    // set the Tab listener. Now we can listen for clicks.
    myTab.setTabListener(new MyTabsListener(myFragment));


    // add the tabs to the actionbar
    actionbar.addTab(myTab);
    map=((MapFragment)getFragmentManager().findFragmentById(R.id.map_add)).getMap();//line 103

}

the layout of the MainActivity, main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
</RelativeLayout>

the code of the tablistener:

    class MyTabsListener implements ActionBar.TabListener {
    public Fragment fragment;

    public MyTabsListener(Fragment fragment) {
        this.fragment = fragment;
    }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {

    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        ft.replace(R.id.fragment_container, fragment);           
    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        ft.remove(fragment);
    }

}

the code of myFragment:

public static class AddAliasFragment extends Fragment {

    private static View view;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        if (view != null) {
            ViewGroup parent = (ViewGroup) view.getParent();
            if (parent != null)
                parent.removeView(view);
        }
        try {
            view = inflater.inflate(R.layout.myfragment_layout, container, false);
        } catch (InflateException e) {
            /* map is already there, just return view as it is */
        }
        return view;
    }

    public MapFragment getMapFragment(){
        return (MapFragment)getFragmentManager().findFragmentById(R.id.map_add);
    } 

}

the layout of myFragment: myfragment_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/map_add_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<EditText
    android:id="@+id/search"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:hint="@string/searchhint"
    />

<Button
    android:id="@+id/searchbtn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignBottom="@+id/search"
    android:layout_toRightOf="@id/search"
    android:text="@string/go" />

<fragment 
      android:id="@+id/map_add"
      android:tag="add"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:layout_below="@id/search"
      android:name="com.google.android.gms.maps.MapFragment"/>

the Logcat output: the nullpointer exception refers to line 103, which is the getMap() line, I have comment after it in the aforementioned code

04-02 21:23:12.122: E/AndroidRuntime(3672): FATAL EXCEPTION: main
04-02 21:23:12.122: E/AndroidRuntime(3672): java.lang.RuntimeException: Unable to start     activity ComponentInfo{com.test.test/com.test.test.MainActivity}:     java.lang.NullPointerException
04-02 21:23:12.122: E/AndroidRuntime(3672):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2307)
04-02 21:23:12.122: E/AndroidRuntime(3672):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2357)
04-02 21:23:12.122: E/AndroidRuntime(3672):     at android.app.ActivityThread.access$600(ActivityThread.java:153)
04-02 21:23:12.122: E/AndroidRuntime(3672):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1247)
04-02 21:23:12.122: E/AndroidRuntime(3672):     at android.os.Handler.dispatchMessage(Handler.java:99)
04-02 21:23:12.122: E/AndroidRuntime(3672):     at android.os.Looper.loop(Looper.java:137)
04-02 21:23:12.122: E/AndroidRuntime(3672):     at android.app.ActivityThread.main(ActivityThread.java:5226)
04-02 21:23:12.122: E/AndroidRuntime(3672):     at java.lang.reflect.Method.invokeNative(Native Method)
04-02 21:23:12.122: E/AndroidRuntime(3672):     at java.lang.reflect.Method.invoke(Method.java:511)
04-02 21:23:12.122: E/AndroidRuntime(3672):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
04-02 21:23:12.122: E/AndroidRuntime(3672):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
04-02 21:23:12.122: E/AndroidRuntime(3672):     at dalvik.system.NativeStart.main(Native Method)
04-02 21:23:12.122: E/AndroidRuntime(3672): Caused by: java.lang.NullPointerException
04-02 21:23:12.122: E/AndroidRuntime(3672):     at     com.test.test.MainActivity.onCreate(MainActivity.java:103)
04-02 21:23:12.122: E/AndroidRuntime(3672):     at android.app.Activity.performCreate(Activity.java:5104)
04-02 21:23:12.122: E/AndroidRuntime(3672):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
04-02 21:23:12.122: E/AndroidRuntime(3672):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2261)
04-02 21:23:12.122: E/AndroidRuntime(3672):     ... 11 more

回答1:

This happens because the MapFragment has not finished loading the google map object. To fix this try overriding onActivityCreated when you create the map fragment. From your implementation of onActivityCreated then do all of your map accesses and modifications.

myMapFragment=new SupportMapFragment(){
    @Override
    public void onActivityCreated(Bundle savedInstanceState){
        //modify your map here
    }
}


回答2:

In mi case the problem was not specify SupportMapFragment. I have uses like this:

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.MapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    class="com.google.android.gms.maps.SupportMapFragment" />

As explained here https://stackoverflow.com/a/16663713/2411379 for Google Map V2 use.