【问题标题】:using google map in a fragment: onMapReady is never called在片段中使用谷歌地图:永远不会调用 onMapReady
【发布时间】:2017-11-06 12:09:53
【问题描述】:

我在另一个片段中使用了谷歌地图,效果很好。因此,当我不得不在同一个应用程序中为另一个片段执行此操作时,我复制/粘贴代码并调整充气机和 findviewbyid。但是永远不会调用 onMapReady(),因此 googlemap 保持为空。

我见过MapView.onMapReady never called in Fragment for load Google Map in MapView 案例,它看起来与我的相似,但我想了解“实现 OnMapReadyCallback”机制。

调用onMapReady的机制是什么?我想当对 mapView.getMapAsync(this) 的调用发生时?

    import android.app.Fragment;
    import android.content.Context;
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.Button;
    import android.widget.ScrollView;
    import android.widget.TextView;
    import android.widget.Toast;

    import com.google.android.gms.maps.CameraUpdateFactory;
    import com.google.android.gms.maps.GoogleMap;
    import com.google.android.gms.maps.MapView;
    import com.google.android.gms.maps.MapsInitializer;
    import com.google.android.gms.maps.OnMapReadyCallback;
    import com.google.android.gms.maps.model.BitmapDescriptorFactory;
    import com.google.android.gms.maps.model.CameraPosition;
    import com.google.android.gms.maps.model.LatLng;
    import com.google.android.gms.maps.model.MarkerOptions;


    public class LocalisationMonitoringFragment extends Fragment implements OnMapReadyCallback {
        private Context context;
        private static View view;

        private MapView mapView;

        static private GoogleMap googleMap;

        public LocalisationMonitoringFragment() {
            // Required empty public constructor
        }

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

            view = inflater.inflate(R.layout.localization_monitor, null);

            mapView = (MapView) view.findViewById(R.id.loc_mapView);
            mapView.onCreate(savedInstanceState);
            mapView.onResume();
            mapView.getMapAsync(this);
            try {
         MapsInitializer.initialize(getActivity().getApplicationContext());
            } catch (Exception e) {
                e.printStackTrace();
            }

            return (view);

        }

   @Override
    public void onMapReady(GoogleMap map) {
        googleMap = map;
        LatLng sydney = new LatLng(latitude, longitude);
        googleMap.addMarker(new MarkerOptions().position(sydney).title("Marker Title").snippet("Marker Description"));
        CameraPosition cameraPosition = new CameraPosition.Builder().target(sydney).zoom(12).build();
        googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
    }

在我拥有的布局文件中:

<com.google.android.gms.maps.MapView
        android:id="@+id/loc_mapView"
        android:layout_below="@id/loc_name_txt"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="20dp" />

【问题讨论】:

    标签: android google-maps


    【解决方案1】:

    首先,将View 存储到static 字段中绝不是一个好主意。这同样适用于您的 GoogleMap 变量。

    其次,我不明白为什么你应该在从mapView 拨打onCreate(Bundle) 之后立即拨打onResume()

    也许onResume() 电话可能已经是问题所在了。


    关于生命周期机制

    意思是(例如);片段中的onPause() 方法应该调用MapViewonPause() 方法。

    @Override protected void onPause() {
        super.onPause();
        this.mapView.onPause();
    }
    

    然后您应该使用相同的逻辑实现其他生命周期方法:

    • onDestroy()
    • onResume()
    • onLowMemory()
    • onSaveInstanceState()
    • onStop()
    • onCreate(Bundle)

    当然,如果您没有注册 Google Maps API 密钥,您的地图将不会显示。因此,请确保您也这样做了。你永远不知道...


    通过查看我的一个项目,该项目在Fragment 中具有完全工作的MapView,我发现我以这种方式覆盖了生命周期方法:

    @Override protected void onPause() {
        super.onPause();
        if (this.mapView != null)
            this.mapView.onPause();
    }
    

    不知道您的情况是否有必要。我遇到过一些MapView 未初始化并抛出NullPointerException 的情况。在没有它的情况下进行测试,然后如果有必要添加null 检查。

    此外,我实际上遗漏了以下方法:

    • onSaveInstanceState()
    • onStop()
    • onCreate(Bundle)

    它们都是我的应用程序崩溃的原因,所以我没有覆盖它们。

    不过,实现它就像the docs 说的那样。如果你遇到一些问题,你可以试试我做的。

    另外,在onCreateView(...)我打过电话

    MapsInitializer.initialize(getContext());
    

    之前

    this.mapView = (MapView) ...;
    

    我的onCreateView(...) 方法看起来像这样。

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        this.rootView = inflater.inflate(R.layout.fragment_location, container, false);
        MapsInitializer.initialize(getContext());
    
        this.mapView = (MapView) rootView.findViewById(R.id.map_view);
        this.mapView.onCreate(savedInstanceState);
        this.mapView.getMapAsync(this);
        // initialize other UI elements.
        return this.rootView;
    }
    

    虽然我对此表示怀疑,但我上面提到的问题可能是因为我使用了android.support.v4.app.Fragmentversion 而不是android.app.Fragment; 版本。

    【讨论】:

    • 我做了几个测试。感谢您的详细回答。我删除了 mapview.resume,静态定义,尝试应用您的建议。仍然没有调用onmapready??我将尝试更多简化。
    • 好的@narb你能告诉我你的目标是什么api级别以及最低级别是多少?您还确定在您的片段变得可见时,您在控制台中看不到任何关于地图视图的信息吗?即使您将过滤器设置为“无”?
    • 与您的讨论帮助我发现我的代码中没有疯狂的东西。事实上,调用 onMapReady 需要一些时间。因此,如果您尝试走得太快(发生在我身上的事情:)) googlemap 为空。谢谢你!
    • @narb 很高兴你自己做了。不过,您的 some time 似乎时间太多了。除非您使用极慢的互联网连接,否则最多应在几秒钟内调用onMapReady()
    • 我说的是微秒。我在 createview 中调用 getMapAsync 和 MapsInitializer,在 onactivitycreated 中调用 addmarker。
    【解决方案2】:

    在我的 Fragment 的 xml 文件中,我使用了以下内容:

    <com.google.android.gms.maps.MapView
        android:id="@+id/googleMap"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    

    在 Fragment.kt 文件中,我使用了以下内容:

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view: View = inflater.inflate(R.layout.fram_map_fragment, container, false)
        initMap(view, savedInstanceState)
        return view
    }
    
    private fun initMap(view: View?, savedInstanceState: Bundle?) {
        mapView = view?.findViewById(R.id.googleMap)
        mapView?.onCreate(savedInstanceState)
        mapView?.getMapAsync(this)
    }
    
    override fun onMapReady(map: GoogleMap?) {
        googleMap = map
        googleMap?.moveCamera(
            CameraUpdateFactory.newLatLngZoom(
                LatLng(lat, lng),
                17F
            )
        )
        googleMap?.mapType = GoogleMap.MAP_TYPE_SATELLITE
        googleMap?.setOnMapClickListener {
            // Create Marker
            drawMarkers(it)
        }
    }
    
    override fun onResume() {
        mapView?.onResume()
        super.onResume()
    }
    
    override fun onPause() {
        mapView?.onPause()
        super.onPause()
    }
    
    override fun onDestroy() {
        mapView?.onDestroy()
        super.onDestroy()
    }
    
    override fun onLowMemory() {
        mapView?.onLowMemory()
        super.onLowMemory()
    }
    

    而且它运行良好。

    【讨论】:

      猜你喜欢
      • 2021-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-21
      相关资源
      最近更新 更多