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

如何在不使用sleep的情况下,等待异步任务获取数据库数据后再加载地图?

解决方案:移除Sleep,异步协调地图加载与数据获取

核心问题分析

你的代码问题根源在于异步任务并行执行时的时序混乱,以及错误地在后台线程操作UI组件:

  1. AsyncTask 是后台线程,主线程调用 getJSON() 后立刻执行 sleep,但后台请求仍在异步进行,导致日志顺序错乱;
  2. doInBackground() 中直接操作 gMap(清除标记、添加标记)属于UI操作,会触发线程安全异常;
  3. 固定时长的 sleep 完全不可靠——网络慢时10秒不够,网络快时纯浪费时间,还会阻塞主线程导致UI卡顿甚至ANR。

优化方案:异步任务协调(无Sleep)

通过标志位+回调的方式,等待「地图加载完成」和「数据获取完成」两个异步操作都就绪后,再统一更新地图。

完整优化代码

import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.app.restaurant.bowzers.R;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import android.os.AsyncTask;

public class TruckFragment2 extends Fragment {
    private double mylocationLong = -82.83;
    private double mylocationLat = 39.9;
    private GoogleMap gMap;
    // 标志位:记录地图和数据是否就绪
    private boolean isMapReady = false;
    private boolean isDataLoaded = false;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_truck, container, false);

        // 1. 初始化地图并监听就绪状态
        SupportMapFragment supportMapFragment = (SupportMapFragment)
                getChildFragmentManager().findFragmentById(R.id.truck_map);
        supportMapFragment.getMapAsync(new OnMapReadyCallback() {
            @Override
            public void onMapReady(@NonNull GoogleMap googleMap) {
                gMap = googleMap;
                isMapReady = true;
                Log.i("STEP 5", mylocationLong + "," + mylocationLat);
                // 检查是否可以更新地图
                updateMapIfReady();
            }
        });

        // 2. 异步获取服务器数据
        getJSON("https://bowzershotdogstand.com/app/get_location.php");

        return view;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
    }

    private void getJSON(final String urlWebService) {
        class GetJSON extends AsyncTask<Void, Void, String> {

            @Override
            protected String doInBackground(Void... voids) {
                Log.i("STEP 1", urlWebService);
                try {
                    URL url = new URL(urlWebService);
                    HttpURLConnection con = (HttpURLConnection) url.openConnection();
                    StringBuilder sb = new StringBuilder();
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(con.getInputStream()));
                    String json;
                    while ((json = bufferedReader.readLine()) != null) {
                        sb.append(json).append("\n");
                    }
                    Log.i("STEP 2", sb.toString());
                    return sb.toString().trim();
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            }

            @Override
            protected void onPostExecute(String s) {
                super.onPostExecute(s);
                if (s != null) {
                    try {
                        JSONArray JA = new JSONArray(s);
                        if (JA.length() > 0) {
                            JSONObject JO = JA.getJSONObject(0);
                            mylocationLong = Double.parseDouble(JO.getString("longitude"));
                            mylocationLat = Double.parseDouble(JO.getString("lattitude"));
                            Log.i("STEP 3", mylocationLat + "," + mylocationLong);
                            isDataLoaded = true;
                            // 检查是否可以更新地图
                            updateMapIfReady();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        new GetJSON().execute();
    }

    // 核心协调方法:只有地图和数据都就绪时才更新地图
    private void updateMapIfReady() {
        if (isMapReady && isDataLoaded) {
            Log.i("STEP 4", mylocationLong + "," + mylocationLat);
            LatLng latLng = new LatLng(mylocationLat, mylocationLong);
            MarkerOptions markerOptions = new MarkerOptions()
                    .position(latLng)
                    .title(latLng.latitude + ": " + latLng.longitude);
            gMap.clear();
            gMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 16));
            gMap.addMarker(markerOptions);
        }
    }
}

优化说明

  1. 移除Sleep:彻底删除主线程的 sleep 调用,避免UI阻塞;
  2. 线程安全修正:将地图操作(添加标记、移动相机)移到UI线程执行,doInBackground() 只负责网络请求和数据解析;
  3. 异步协调:用 isMapReady 和 isDataLoaded 两个标志位,只有两者都为 true 时,才执行地图更新逻辑;
  4. 时序可控:日志顺序会变为 STEP1→STEP2→STEP3→STEP5→STEP4(或地图先就绪则 STEP5 先出现),最终都会触发地图更新。

进阶优化:用协程替代AsyncTask

由于 AsyncTask 已被官方废弃,推荐使用 Kotlin协程(Java也可调用)实现更简洁的异步逻辑:

// 需先添加协程依赖
import kotlinx.coroutines.CoroutineScope;
import kotlinx.coroutines.Dispatchers;
import kotlinx.coroutines.launch;
import kotlinx.coroutines.withContext;

// 替换原getJSON方法
private void getJSON(final String urlWebService) {
    CoroutineScope(Dispatchers.IO).launch {
        Log.i("STEP 1", urlWebService);
        try {
            URL url = new URL(urlWebService);
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            StringBuilder sb = new StringBuilder();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String json;
            while ((json = bufferedReader.readLine()) != null) {
                sb.append(json).append("\n");
            }
            Log.i("STEP 2", sb.toString());
            final String response = sb.toString().trim();
            // 切换回主线程处理UI和数据解析
            withContext(Dispatchers.Main) {
                try {
                    JSONArray JA = new JSONArray(response);
                    if (JA.length() > 0) {
                        JSONObject JO = JA.getJSONObject(0);
                        mylocationLong = Double.parseDouble(JO.getString("longitude"));
                        mylocationLat = Double.parseDouble(JO.getString("lattitude"));
                        Log.i("STEP 3", mylocationLat + "," + mylocationLong);
                        isDataLoaded = true;
                        updateMapIfReady();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

协程版本避免了 AsyncTask 的生命周期泄漏问题,代码结构更清晰,是目前Android异步编程的推荐方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 09:35:55