Android MapView的getMap()方法返回null

17

MapViewgetMap()方法可能返回null。我知道这是Google有意为之的行为。

是否有人可以提供一个明确的描述,说明什么情况下以及在何种情况下getMap()方法会返回null?

我知道如果给定设备上无法使用Google服务,getMap()将返回null。这种情况已经相对较好地记录下来了。我更关心的是一种模糊的情况,即即使在设备上安装了Google服务,getMap()仍然可能返回null。

到目前为止,我的假设是,在底层地图系统初始化期间,您的代码可能会执行并获取空地图。

我的假设正确吗?

是否有特定的Activity或Fragment生命周期的某个特定位置,我们可以确定地获取非空的GoogleMap(如果我们假定已安装Google服务)?

我提出这个问题的目的是为了避免在我的代码中散布大量的if(mapView.getMap()!= null)检查。此外,这个问题似乎仍然经常在StackOverflow上出现,我想看看我们能否弄清楚MapViewgetMap()实际上发生了什么。


你应该尝试使用MapFragment而不是MapView。MapFragment可以处理其生命周期并防止返回空值。 - LoveMeSomeFood
Rani,我几乎总是需要在片段中操作地图。使用MapFragment将需要嵌入文档化问题的片段。这个问题是为了那些需要MapView的人而提出的。 - Studio4Development
3个回答

13
谷歌处理的场景 如果没有安装谷歌应用商店的apk文件,你会得到一个空值。但是它会以某种方式内置于从Play商店下载中。但是如果未安装Play商店,则会得到一个空映射。如果没有可用的互联网连接并且已安装了Play商店但未安装Google Play服务,则会得到一个空值,因为无法安装Google Play服务。但是这些场景的编码都已为您完成。 代码处理的场景 这就是你需要编码的内容。如果不按照地图示例中概述的模式进行编写,则会得到一个空地图。每个示例都以相同的方式执行。这样,如果onCreate中的第一个调用失败,则仍有第二次机会在onResume中获取地图。解决方案是只在一个地方调用getMap()并保存返回的地图对象。遵循地图示例使用的基本模式,在onCreate方法和onResume方法中调用setupmapifneeded,当地图对象不为空时调用setupmap
这是第一个地图示例。
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.gosylvester.testapp;


import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

/**
 * This shows how to create a simple activity with a map and a marker on the map.
 * <p>
 * Notice how we deal with the possibility that the Google Play services APK is not
 * installed/enabled/updated on a user's device.
 */
public class BasicMapActivity extends FragmentActivity {
    /**
     * Note that this may be null if the Google Play services APK is not available.
     */
    private GoogleMap mMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.basic_demo);
        setUpMapIfNeeded();
    }

    @Override
    protected void onResume() {
        super.onResume();
        setUpMapIfNeeded();
    }

    /**
     * Sets up the map if it is possible to do so (i.e., the Google Play services APK is correctly
     * installed) and the map has not already been instantiated.. This will ensure that we only ever
     * call {@link #setUpMap()} once when {@link #mMap} is not null.
     * <p>
     * If it isn't installed {@link SupportMapFragment} (and
     * {@link com.google.android.gms.maps.MapView MapView}) will show a prompt for the user to
     * install/update the Google Play services APK on their device.
     * <p>
     * A user can return to this FragmentActivity after following the prompt and correctly
     * installing/updating/enabling the Google Play services. Since the FragmentActivity may not have been
     * completely destroyed during this process (it is likely that it would only be stopped or
     * paused), {@link #onCreate(Bundle)} may not be called again so we should call this method in
     * {@link #onResume()} to guarantee that it will be called.
     */
    private void setUpMapIfNeeded() {
        // Do a null check to confirm that we have not already instantiated the map.
        if (mMap == null) {
            // Try to obtain the map from the SupportMapFragment.
            mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
                    .getMap();
            // Check if we were successful in obtaining the map.
            if (mMap != null) {
                setUpMap();
            }
        }
    }

    /**
     * This is where we can add markers or lines, add listeners or move the camera. In this case, we
     * just add a marker near Africa.
     * <p>
     * This should only be called once and when we are sure that {@link #mMap} is not null.
     */
    private void setUpMap() {
        mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
    }
}

如果地图将每个可用,那么您将在onCreate或onResume中获得引用?如果这两个引用都为空,则地图永远不会变得可用?此外,您是否知道什么原因会导致在onCreate中地图不可用,但稍后在onResume中变为可用? - Studio4Development
2
如果两者都未能获取地图,则地图将不可用。理论上,这种情况永远不会发生。一旦您使地图工作起来,它就非常稳定。如果应用程序在手机启动后立即启动,则可能在OnResume中获得地图。 - danny117

7

Google有一种更方便的方法来获取地图,可以使用以下方法,因为它可能依赖于设备来获取准备好的地图!在地图准备就绪时,请使用以下方法来获取地图。

myMapFragment.getMapAsync(new OnMapReadyCallback) {
     @Override
     public void onMapReady(GoogleMap googleMap) {
         myMap = googleMap;
     }
});

你从哪个事件调用它? - danny117
我认为这没有什么区别,只要mapFragment不为空,那么当地图准备好时,该块就会被调用。 - Exception

0

我有一台运行Android 4.2.2的Android Tab3,我所要做的就是更新谷歌地图,它就可以解决问题了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接