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

Fragment中Google Map同时显示当前位置与服务端站点问题排查

问题根因

这个需求完全可以实现,你现在看不到火车站点是代码存在多个逻辑错误,核心问题如下:

  • 权限判断写反:get_stations()里你写的是if(checkLocationPermission()) { 仅打印日志 } else { 才发起网络请求拉站点 },等于用户授权后根本不会执行拉取站点的逻辑,没权限的时候反而去发请求。
  • 重复绑定地图回调:你在getcurrentlocatiom()和get_stations()里各找了一次SupportMapFragment、各绑定了一次getMapAsync,同一个地图实例被重复初始化,回调执行顺序完全混乱。
  • 错误清空地图:onMapReady里加完当前位置标记后直接调用gMap.clear(),之前添加的所有标记、折线都会被直接清除。
  • 无效重复请求:位置回调里每次收到位置更新都重新调用get_stations(),无限重复发网络请求,还会重复添加标记。
  • JSON解析逻辑残缺:解析站点响应时直接调用stations.getString(),但没有遍历服务端返回的站点数组,解析直接抛异常中断。
  • 初始化时序错误:onCreateView里页面刚加载就同时调用定位、拉站点方法,这时候地图还没初始化完成、权限也可能没授予,调用必然出问题。
修改步骤

1. 统一地图初始化入口

删掉其他地方重复绑定地图的逻辑,只在视图加载时初始化一次地图:

@Override
public View onCreateView(@NonNull @NotNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_maps_line, container, false);
    // 仅初始化一次地图,不要在其他方法里重复find Fragment绑定回调
    SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
    return rootView;
}

2. 修正onMapReady逻辑

去掉错误的clear操作,等地图加载完成、权限校验通过后,再执行开启定位、拉取站点的操作:

@SuppressLint("MissingPermission")
@Override
public void onMapReady(@NonNull GoogleMap googleMap) {
    gMap = googleMap;
    if(checkLocationPermission()){
        gMap.setMyLocationEnabled(true);
        // 地图就绪+权限OK再拉站点,仅调用一次
        get_stations();
        startLocationUpdates();
    }
}

3. 重写get_stations()方法

把写反的权限判断改回来,补全JSON解析逻辑,不要重复绑定地图:

public void get_stations(){
    if(gMap == null) return;
    // 修正权限判断:有权限才拉取数据
    if(checkLocationPermission()) {
        List<LatLng> routeArray = new ArrayList<>();
        JSONObject requestParam = new JSONObject();
        String GET_STATIONS = "https://help.php";
        try {
            requestParam.put("sid", sid_user);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        JsonObjectRequest req = new JsonObjectRequest(
                Request.Method.POST,
                GET_STATIONS,
                requestParam,
                response -> {
                    try {
                        // 补全站点数组遍历,数组key按你实际接口返回的字段修改
                        JSONArray stationsArray = response.getJSONArray("stations");
                        for (int i = 0; i < stationsArray.length(); i++) {
                            JSONObject stations = stationsArray.getJSONObject(i);
                            String name = stations.getString("sname");
                            String lat = stations.getString("lat");
                            String lon = stations.getString("lon"); // 补上你之前漏取的经度字段
                            // 用Double解析经纬度,避免Float精度损失导致位置偏移
                            LatLng latLng = new LatLng(Double.parseDouble(lat), Double.parseDouble(lon));
                            gMap.addMarker(new MarkerOptions().position(latLng).title("站点:" + name));
                            if (!routeArray.contains(latLng)) {
                                routeArray.add(latLng);
                            }
                        }
                        drawLine(routeArray);
                        // 调整视角同时包含当前位置和所有站点,不要每次移动到单个站点
                        LatLngBounds.Builder builder = new LatLngBounds.Builder();
                        builder.include(new LatLng(latitude, longitude));
                        for (LatLng point : routeArray) {
                            builder.include(point);
                        }
                        gMap.animateCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 120));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                },
                error -> Log.e("StationFetch", "拉取站点失败", error)
        );
        if(getActivity() != null) {
            MainActivity.requestQueue.add(req);
        }
    }
}

4. 修正位置回调逻辑

删掉回调里重复调用get_stations()的代码,收到位置更新只刷新经纬度变量即可,避免无限发请求:

@Override
public void onLocationResult(LocationResult locationResult) {
    if (locationResult == null) {
        Log.d("main_activiyt_maps", "location request is null");
        return;
    }
    // 删掉此处的get_stations()调用
    for (Location location : locationResult.getLocations()) {
        latitude = location.getLatitude();
        longitude = location.getLongitude();
        currentLocation = location;
    }
}

5. 修正权限申请回调

权限通过后如果地图已经就绪,直接执行后续逻辑,不要重复初始化定位客户端:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSION_REQUEST_ACCESS_FINE_LOCATION: {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                if(gMap != null) {
                    gMap.setMyLocationEnabled(true);
                    get_stations();
                    startLocationUpdates();
                }
            }
            break;
        }
    }
}

6. 补全drawLine方法

之前的方法没有把点位添加到折线配置里,补上逻辑:

public void drawLine(List<LatLng> points) {
    if (points == null || points.size() < 2) {
        return;
    }
    gMap.addPolyline(new PolylineOptions().addAll(points).width(5).color(Color.RED));
}
额外优化建议
  • 位置更新间隔1秒过于频繁,非导航场景建议改成10秒(10000ms),降低耗电。
  • 所有调用getActivity()、getContext()的地方加非空判断,避免Fragment销毁后触发空指针。
  • 经纬度解析统一用Double.parseDouble(),不要用Float,避免精度损失导致点位偏移。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 05:57:12