在android中调用TabHost +片段中的oncreateView时出错?

时间:2014-03-31 05:23:31

标签: android android-fragments lifecycle android-lifecycle

我正在开发一个包含4个标签的应用,1个标签是Google地图。

当用户点击它时,它可以正确地创建地图,但是,如果用户通过单击其他选项卡离开当前选项卡,并再次返回此选项卡,则会抛出错误膨胀布局XML的异常。

所以我记录了流程,我发现第二次在onCreateView上,rootview已经创建了,但是当我添加(rootView == null)时,它仍然会抛出错误"需要在子视图上删除View& #34; 。如何解决?感谢。

public class Map extends Fragment {
     // Google Map
    private GoogleMap googleMap;
    private boolean isShowRoute;
    private Database db;
    private ArrayList<Restaurant> rList;
    private ArrayList<Spot> sList;

    View rootView;

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        Log.d("test1","" + rootView);
        rootView = inflater.inflate(R.layout.map, container, false);
        return rootView;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        Log.d("test1","b");
        super.onActivityCreated(savedInstanceState);
        db = new Database (getActivity());
        rList = db.getRestaurant();
        sList = db.getSpot();
        try {
            initilizeMap();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * function to load map. If map is not created it will create it for you
     * */
    private void initilizeMap() {
        if (googleMap == null) {
            googleMap = ((MapFragment) getActivity().getFragmentManager().findFragmentById(R.id.map)).getMap();

            // check if map is created successfully or not
            if (googleMap == null) {
                Toast.makeText(getActivity().getApplicationContext(),"Sorry! unable to create maps", Toast.LENGTH_SHORT).show();
            } else {
                googleMap.setMyLocationEnabled(true);
                googleMap.getUiSettings().setCompassEnabled(true);
                googleMap.getUiSettings().setMyLocationButtonEnabled(true); 

                if (isShowRoute)
                    showRoute();
                else
                    pinMap();
            }
        }
    }


    private void showRoute() {
//       if (RunTracker.routePoints.size() > 1){
//          Polyline route = googleMap.addPolyline(new PolylineOptions()
//            .geodesic(true));
//          route.setPoints(RunTracker.routePoints);
//          
//          LatLng lastLatLng = RunTracker.routePoints.get(RunTracker.routePoints.size() - 1);
//          googleMap.addMarker(new MarkerOptions().position(lastLatLng).title("You are here"));
//          googleMap.moveCamera( CameraUpdateFactory.newLatLngZoom(lastLatLng, 16.0f) );
//         }
    }

    private void pinMap() {
        for (Restaurant r : rList) {
            MarkerOptions marker = new MarkerOptions().position(new LatLng(r.lat, r.lng)).title(r.name);
            marker.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE));
            googleMap.addMarker(marker);
        }

        for (Spot s : sList) {
            MarkerOptions marker = new MarkerOptions().position(new LatLng(s.lat, s.lng)).title(s.name);
            marker.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
            googleMap.addMarker(marker);
        }

        googleMap.moveCamera( CameraUpdateFactory.newLatLngZoom(new LatLng(22.3079136,114.1778376), 10.0f) ); // go to MK MTR station by default
    }

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

}

记录猫

03-31 14:53:56.669: E/AndroidRuntime(4611): android.view.InflateException: Binary XML file line #6: Error inflating class fragment

Caused by: java.lang.IllegalArgumentException: Binary XML file line #6: Duplicate id 0x7f050006, tag null, or parent id 0xffffffff with another fragment for com.google.android.gms.maps.MapFragment

布局

<?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.MapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

更新代码:

   @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onActivityCreated(savedInstanceState);
        db = new Database (getActivity());

        if (rList == null && sList == null) {
            rList = db.getRestaurant();
            sList = db.getSpot();
        }
    }

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

        rootView = inflater.inflate(R.layout.map, container, false);

        try {
            initilizeMap();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return rootView;
    }

3 个答案:

答案 0 :(得分:1)

您无法在片段中添加片段。来自Android document

  

注意:当布局包含a时,您无法将布局扩展为片段。只有动态添加到片段时才支持嵌套片段。

您从活动中获取MapFragment,但在更改标签后,您的片段的生命周期发生了变化,而不是活动。当您选择选项卡1(MapFragment)时,它将尝试再次获取MapFragment。 所以你应该试试

googleMap = ((MapFragment) getChildFragmentManager().findFragmentById(R.id.map)).getMap();

或者您应该从活动的片段管理器中删除MapFragment。

Link

答案 1 :(得分:1)

@Override
public void onDestroyView() {
    super.onDestroyView();
    if (mMap != null) {
        getActivity().getSupportFragmentManager().beginTransaction().remove(getActivity().getSupportFragmentManager().findFragmentById(R.id.map)).commit();
        mMap = null;
    }
}

必须从FragmentManager中删除mapfragment的id 或者如果相同,那么下次再传递 应用程序将崩溃

答案 2 :(得分:1)

user782104是正确的,解决了我同样的问题!我的情况是我使用了一个片段,所以:

@Override
public void onDestroyView() {
    super.onDestroyView();
    if(mMap != null)
    {
        getFragmentManager().beginTransaction().remove(getFragmentManager().findFragmentById(R.id.mapFrag)).commit();
        mMap = null;
    }
}