You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中Google Maps API的onMapReady方法无法获取经纬度值问题

问题原因分析

你遇到的这个问题核心在于异步操作的执行顺序不确定性:

  • getJSON() 里的 AsyncTask 是异步执行网络请求的,它会在后台线程拉取数据,只有请求完成后才会在 onPostExecute() 里给 latVal 和 longVal 赋值。
  • 同时,mapFragment.getMapAsync(this) 也是异步回调机制,Google Maps 需要时间完成初始化,之后才会触发 onMapReady()。

通常地图初始化的速度会比网络请求快,所以当 onMapReady() 执行时,网络请求还没结束,latVal 和 longVal 还没被赋值,自然是空的;而 onPostExecute() 里能拿到值,是因为此时网络请求已经完成了。

另外注意你原代码里的变量赋值搞反了:longVal = jsonObject.getString("lat");、latVal = jsonObject.getString("lng");,这会导致纬度和经度颠倒,记得修正!

解决方案

这里给你两种最直接的修复方案,按需选择:

方案一:等地图初始化完成后再发起网络请求

这种方法能确保网络请求返回数据时,地图已经准备就绪,可以直接更新:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_child_tracker_page);
    
    // 先初始化地图,不着急发网络请求
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
}

@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    // 地图准备好了,现在发起网络请求拿坐标
    getJSON("http://webgax.com/schoolapp/fetch.php");
}

// 修改getJSON里的onPostExecute,拿到数据后直接更新地图
private void getJSON(final String urlWebService) {
    class GetJSON extends AsyncTask<String, Void, String> {
        @Override
        public void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        public void onPostExecute(String s) {
            super.onPostExecute(s);
            try {
                JSONObject jsonObject = new JSONObject(s);
                // 修正变量赋值顺序
                latVal = jsonObject.getString("lat");
                longVal = jsonObject.getString("lng");
                
                // 地图已准备好,直接更新
                if (mMap != null) {
                    latNum = Double.parseDouble(latVal);
                    longNum = Double.parseDouble(longVal);
                    LatLng addr = new LatLng(latNum, longNum);
                    float zoomLevel = 16;
                    mMap.addMarker(new MarkerOptions().position(addr).title("WebGax"));
                    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(addr, zoomLevel));
                    
                    Toast.makeText(getApplicationContext(), "坐标已加载", Toast.LENGTH_LONG).show();
                }
            } catch (Exception e) {
                e.printStackTrace();
                Toast.makeText(getApplicationContext(), "解析数据出错", Toast.LENGTH_SHORT).show();
            }
        }

        @Override
        public String doInBackground(String... strings) {
            HashMap<String,String> hashMap=new HashMap<>();
            return myCon.postRequest(hashMap, "http://webgax.com/schoolapp/fetch.php");
        }
    }
    GetJSON getJSON = new GetJSON();
    getJSON.execute();
}

方案二:网络请求完成后检查地图状态

如果不想调整请求顺序,可以在 onPostExecute() 里判断地图是否初始化完成,已完成则直接更新,未完成则保存数据,等地图 ready 后再更新:

// 新增标记变量,记录是否已拿到坐标
private boolean hasGotLocation = false;

@Override
public void onPostExecute(String s) {
    super.onPostExecute(s);
    try {
        JSONObject jsonObject = new JSONObject(s);
        latVal = jsonObject.getString("lat");
        longVal = jsonObject.getString("lng");
        hasGotLocation = true;
        
        // 检查地图是否已初始化
        if (mMap != null) {
            updateMapWithLocation();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    // 如果已经拿到坐标,直接更新地图
    if (hasGotLocation) {
        updateMapWithLocation();
    } else {
        // 先显示默认标记,等数据加载后替换
        LatLng defaultAddr = new LatLng(22, 88);
        float zoomLevel = 16;
        mMap.addMarker(new MarkerOptions().position(defaultAddr).title("加载中..."));
        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(defaultAddr, zoomLevel));
    }
}

// 抽取出更新地图的方法,复用代码
private void updateMapWithLocation() {
    latNum = Double.parseDouble(latVal);
    longNum = Double.parseDouble(longVal);
    LatLng addr = new LatLng(latNum, longNum);
    float zoomLevel = 16;
    // 清除默认标记(如果有的话)
    mMap.clear();
    mMap.addMarker(new MarkerOptions().position(addr).title("WebGax"));
    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(addr, zoomLevel));
}
额外提示

AsyncTask 在 Android API 30 之后已被标记为废弃,如果你开发的是新版本应用,建议使用**协程(Coroutines)**或者 OkHttp + ViewModel + LiveData 的组合处理网络请求,代码会更简洁且符合现代 Android 开发规范。

内容的提问来源于stack exchange,提问作者benid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:48:43