【问题标题】:SupportMapFragment null on SECOND loadSupportMapFragment 在第二次加载时为空
【发布时间】:2014-12-31 00:20:00
【问题描述】:

我试图解决这个问题已经很长时间了。我已经阅读了很多关于 stackoverflow 和其他来源的类似问题的问题,我无法一一列举。

我的问题与我自第一次以来读过的其他问题不同,我尝试使用地图加载片段所有工作正常...在第二次我尝试使用地图访问片段而不重新启动它崩溃并带有空指针的应用程序:

googleMap = map.getMap();

因为地图为空:

 map = (SupportMapFragment) myContext.getSupportFragmentManager().
           findFragmentById(R.id.map);

主要区别在于:

  • 第一次正常使用
  • 第二次findFragmentById返回null,但没有错误

我无法调试它,因为 AVD 模拟器没有安装 Google Play 服务。

MainActivity 有一个 NavigationDrawer,根据选择的选项,选择一个 Fragment 或另一个。这里有一些与这个问题相关的代码:

fragment_map.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">

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

</RelativeLayout>

MyFragment.java:

...
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
...
public class MyFragment extends Fragment implements
        GooglePlayServicesClient.ConnectionCallbacks,
        GooglePlayServicesClient.OnConnectionFailedListener {

    private GoogleMap googleMap;
    private View fragmentView;
    private static WorldFragment fragment;
    private FragmentActivity myContext;
    ...

    public static MyFragment getInstance() {
        if (fragment == null) {
            fragment = new MyFragment();
        }
        return fragment;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        myContext = (FragmentActivity) activity;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        try {
            GlobalState gs = (GlobalState) getActivity().getApplication(); 
            // recover View from previous use
            fragmentView = gs.getWorldFragmentView(); 
            if (fragmentView == null) {
                fragmentView = inflater.inflate(R.layout.fragment_map, 
                                    container, false);
                // save View for next use
                gs.setFragmentView(fragmentView); 
            } else {
                ViewGroup parent = (ViewGroup) fragmentView.getParent();
                parent.removeView(fragmentView);
            }
        } catch (InflateException e) {
            // map is already there, just return view as it is
        }
        return fragmentView;
    }

    ...

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

        // Set up the map fragment
        SupportMapFragment map = (SupportMapFragment) myContext.
             getSupportFragmentManager().findFragmentById(R.id.map);
        /*  // If I active this code, no crash, but fragment remains 
            // in gray background without map.
            // At least, if the app crashes, it restarts and the map 
            // gets loaded the first time
        if (map == null) {
            Toast.makeText(getActivity(), getString(R.string.maps_not_supported), 
                   Toast.LENGTH_LONG).show();
            return;
        } */
        googleMap = map.getMap();
        if (googleMap != null) {
            // Enable the current location "blue dot"
            googleMap.setMyLocationEnabled(true);
            ...
        } else {
            Toast.makeText(getActivity(), getString(R.string.maps_not_supported), 
                   Toast.LENGTH_LONG).show();
        }
    }

    ...
}

MainActivity.java:

public class MainActivity extends FragmentActivity implements
    NavigationDrawerFragment.NavigationDrawerCallbacks {

    @Override
    public void onNavigationDrawerItemSelected(int position) {
        Fragment contentFragment;
        switch (selectedOption) {
            case MAP:
                contentFragment = MyFragment.getInstance();
                break;
            case XXX:
                ...
                break;
            default:
                contentFragment = new OtherFragment(); 
        }
        // update the main content by replacing fragments
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.container, contentFragment)
                .commit();
    }
}

堆栈跟踪:

java.lang.NullPointerException
   at xxx.xxxxx.xxx.fragments.MyFragment.onActivityCreated(MyFragment.java:193)
   at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1508)
   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:958)
   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1115)
   at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
   at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1478)
   at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:446)
   at android.os.Handler.handleCallback(Handler.java:725)
   at android.os.Handler.dispatchMessage(Handler.java:92)
   at android.os.Looper.loop(Looper.java:153)
   at android.app.ActivityThread.main(ActivityThread.java:5297)
   at java.lang.reflect.Method.invokeNative(Method.java)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
   at dalvik.system.NativeStart.main(NativeStart.java)

如果您需要更多信息,请告诉我。

非常感谢您的时间和关注。

30/12/2014:MainActivity 的 onCreate() 方法源代码

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    GlobalState applicationContext = (GlobalState) getApplicationContext();
    applicationContext.updateLocale();

    NavigationDrawerFragment.setItems(applicationContext.getMenuItems());
    setContentView(R.layout.activity_main);

    mNavigationDrawerFragment = (NavigationDrawerFragment)
            getFragmentManager().findFragmentById(R.id.navigation_drawer);
    mTitle = getTitle();

    // Set up the drawer.
    mNavigationDrawerFragment.setUp(
            R.id.navigation_drawer,
            (DrawerLayout) findViewById(R.id.drawer_layout));

    // Treating incoming notifications
    Intent intent = getIntent();
    String action = intent.getAction();
    if (action != null && !action.isEmpty()) {
        ItemType itemType = ItemType.valueOf(action);
        String title = applicationContext.getMenuItemByType(itemType).getTitle();
        String itemId = null;
        try {
            JSONObject json = new JSONObject(intent.getExtras().getString("com.parse.Data"));
            itemId = json.getString(EXTRA_ITEM_ID);
        } catch (JSONException e) {
            Crashlytics.logException(e);
        }
        launchFragment(itemType, null, title, itemId);
    }
}

【问题讨论】:

    标签: android google-maps null navigation-drawer supportmapfragment


    【解决方案1】:

    您必须在 MyFragment 类的 onDestroyView() 方法中删除片段。

    要删除的示例代码:

    @Override
       public void onDestroyView() {
           SupportMapFragment f = (SupportMapFragment)myContext.getSupportFragmentManager().findFragmentById(R.id.map);
    
           if (f != null) {
               try {
                   myContext.getSupportFragmentManager().beginTransaction().remove(f).commit();
               }
               catch (Exception e) {
                   e.printStackTrace();
               }
           }
           super.onDestroyView();
       }
    

    【讨论】:

    • 您好,谢谢您,但它不起作用。我在 onDestroy 查看 java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1354) at ... .enqueueAction(FragmentManager.java: 1372) 在 ... .BackStackRecord.commitInternal(BackStackRecord.java:595) 在 ... .commit(BackStackRecord.java:574) 在 ... .fragments.MyFragment.onDestroyView(MyFragment.java:183) ...然后,和以前一样的 pb onActivityCreated
    • 能否提供您的 MainActivity 的 onCreate() 方法的源代码?
    • 编辑主帖添加的MainActivity的onCreate()方法源码
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多