Android片段生命周期和Google地图

时间:2015-10-17 18:23:27

标签: android google-maps android-fragments

我有一个嵌套片段,可以显示谷歌地图。首次创建活动时,将添加主片段,然后实例化嵌套的地图片段。这工作正常。

但是,如果用户离开应用程序(将其放入后台),然后又返回到该应用程序,则不再显示嵌套的地图片段。好像有人在其上打电话给map.setVisibility(View.INVISIBLE)(而不是View.GONE)(除了这个没有被调用 - 我只是说它将问题放在上下文中)。< / p>

以下是第一个片段的相关代码(请注意,我已经遗漏了大量代码,所以请不要担心是否有任何变量未在您的内容中初始化看到这里):

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

        Log.d("resume", "today onCreateView");
        view = inflater.inflate(R.layout.fragment_today, container, false);    
        fragmentManager = getFragmentManager();
        return view;
    }

    @Override
    public void onResume() {
        super.onResume();
        addMapFragment(new LatLng(location.getLatitude(), location.getLongitude()), location.getLocationName());
    }

    private void addMapFragment(LatLng latLng, String marker_name) {

        Log.d("resume", Double.toString(latLng.latitude));

        Bundle mapBundle = new Bundle();
        mapBundle.putDouble("lat", latLng.latitude);
        mapBundle.putDouble("lng", latLng.longitude);
        mapBundle.putString("marker_title", marker_name);

        // capture this for use in getting directions if requested
        destinationLatLng = new LatLng(latLng.latitude, latLng.longitude);

        mMapFragment = new MapFragment();
        mMapFragment.setArguments(mapBundle);

        fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.add(R.id.map_today, mMapFragment);
        fragmentTransaction.commitAllowingStateLoss();

        Log.d("resume", "map added");
    }

fragment_today.xml

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.mysite.myapp.Activities.ViewControllers.TodayFragment"
    android:id="@+id/today_background"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

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

        <FrameLayout
            android:id="@+id/map_today"
            android:layout_width="match_parent"
            android:layout_height="150dp"
            android:paddingLeft="15dp"
            android:paddingRight="15dp" />

       <!-- lots of other textviews follow. omitted for brevity-->

    </LinearLayout>

</RelativeLayout>

fragment_map.xml

<?xml version="1.0" encoding="utf-8"?>
<fragment 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:map="http://schemas.android.com/apk/res-auto"
    android:id="@+id/fragment_map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    map:mapType="normal"
    map:uiCompass="true"
    map:uiRotateGestures="true"
    map:uiScrollGestures="true"
    map:uiTiltGestures="true"
    map:uiZoomControls="true"
    map:uiZoomGestures="true" />

然后,最后,在地图片段中,我有这个代码。我已经把我放置代码的地方用来生成地图(在onCreateView和onResume之间切换)。我尽可能多地在onResume中输入代码。请注意,当用户将应用程序放入后台以及何时返回应用程序时,所有值都不会发生变化,因此这不是问题:

MapFragment.java

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

        Log.d("resume", "map oncreateview");

        view = inflater.inflate(R.layout.fragment_map, container, false);

        // set the title text (if given by parent fragment)
        Bundle bundle = getArguments();

        if (bundle != null) {

            if (bundle.containsKey("lat") && bundle.containsKey("lng")) {    
                myLocation = new LatLng(bundle.getDouble("lat"), bundle.getDouble("lng"));
            }

            if (bundle.containsKey("marker_title"))
                markerTitle = bundle.getString("marker_title");

        }

        return view;
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d("resume", "map onResume");

        if (myLocation != null && markerTitle != null) {
            CameraPosition cameraPosition = new CameraPosition.Builder()
                    .target(workoutLocation)
                    .zoom(12)
                    .tilt(30)
                    .build();

            GoogleMap map = ((SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.fragment_map)).getMap();

            Marker marker = map.addMarker(new MarkerOptions()
                            .position(workoutLocation)
                            .title(markerTitle)
            );
            marker.showInfoWindow();

            map.setBuildingsEnabled(true);
            map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
        }
    }

在运行时,这都会生成以下输出:

初始实例化

  

今天onResume
当前   
44.915647
已添加地图
地图oncreateview
map onResume

应用程序进入后台时

  

今天onPause
onStop

当应用程序回到前面时 今天onCreateView

  


map oncreateview
今天onCreateView   
Activity.onPostResume()今天称为onResume
当前   
44.915647
地图添加
地图onResume
今天onResume   
当前
44.915647
已添加地图
地图oncreateview
地图   onResume
地图oncreateview
地图onResume

我觉得这一切看起来都不错,虽然很奇怪,这就是'oncreateview&#39;并且&#39; map onResume&#39;出现两次(我不认为这是一个问题)。

很长的帖子,但是一个有趣的困境。感谢任何到目前为止的人!

1 个答案:

答案 0 :(得分:0)

尝试使用新的API来异步获取地图。

引用您的Google地图对象。在onResume()中,检查它是否为null然后获取地图。

另外,我建议您像添加常规片段一样添加子地图。也就是说,不使用布局中的片段,而是使用FrameLayout并向其添加(支持)MapFragment。我在片段中使用嵌套子片段时发现了很多问题。

所以,我建议这样的事情:

private GoogleMap googleMap;

private void setUpMapIfNeeded(){
    if(googleMap == null){
        SupportMapFragment mapFragment = SupportMapFragment.newInstance();
        // mapContainerLayout would be some FrameLayout to replace the <fragment> you use for map
        getChildFragmentManager.beginTransaction.replace(R.id.mapContainerLayout, mapFragment, "MapTag").commit;
        mapFragment.getMapAsync(this);
    }
}

@Override
public void onMapReady(GoogleMap map) {
    this.googleMap = map;
    // Do other stuff as needed
}

然后只需在onResume()中调用setUpMapIfNeeded()。

编辑:将fragmentManager更改为getChildFragmentManager();