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

Android AsyncTask使用问题:加载OpenWeatherMap JSON时应用崩溃

解决AsyncTask加载OpenWeatherMap API时的崩溃问题

嘿,作为Android开发新手遇到这种崩溃太正常了!别慌,咱们重点排查你怀疑的while循环,顺便梳理下AsyncTask使用中容易踩的坑。

先排查最可能的几个问题

1. 有没有加网络权限?

这是新手最容易忘的!如果你的AndroidManifest.xml里没加网络权限,点击按钮发起网络请求时会直接崩溃。赶紧加上:

<uses-permission android:name="android.permission.INTERNET"/>

2. while循环的IO异常没处理?

网络流读取属于IO操作,一定会抛出异常,如果没捕获,就会直接导致崩溃。给你看个正确的流读取写法:

@Override
protected String doInBackground(String... urls) {
    String result = "";
    HttpURLConnection urlConnection = null;
    InputStream inputStream = null;

    try {
        URL url = new URL(urls[0]);
        urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.connect();

        // 用BufferedReader比逐个字符读取更高效,也更稳妥
        inputStream = urlConnection.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuilder stringBuilder = new StringBuilder();
        String line;
        
        // 这里的while循环是正确的读取方式
        while ((line = reader.readLine()) != null) {
            stringBuilder.append(line);
        }
        result = stringBuilder.toString();
    } catch (IOException e) {
        // 必须捕获IO异常,打印日志方便排查
        e.printStackTrace();
        Log.e("DownloadTask", "加载失败:" + e.getMessage());
        return null;
    } finally {
        // 一定要关闭流和连接,避免资源泄漏
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (urlConnection != null) {
            urlConnection.disconnect();
        }
    }
    return result;
}

3. 是不是在后台线程操作UI了?

AsyncTask的doInBackground是在后台线程执行的,绝对不能在这里更新TextView、弹Toast这类UI操作!所有UI更新必须放在onPostExecute里,比如:

@Override
protected void onPostExecute(String s) {
    super.onPostExecute(s);
    if (s != null) {
        // 在这里解析JSON、更新UI
        Toast.makeText(MainActivity.this, "数据加载成功!", Toast.LENGTH_SHORT).show();
    } else {
        Toast.makeText(MainActivity.this, "加载失败,请检查网络或URL", Toast.LENGTH_SHORT).show();
    }
}

4. OpenWeatherMap的URL是不是正确?

要确认你的API URL里包含了正确的城市名、API Key,比如:

String weatherUrl = "https://api.openweathermap.org/data/2.5/weather?q=Beijing&appid=你的API_KEY";

如果URL无效(比如没带Key、拼写错误),连接时会抛出异常,没捕获就会崩溃。

完整示例代码

给你一个能跑通的完整Demo,你可以对照着改自己的代码:

public class MainActivity extends AppCompatActivity {

    Button weatherBtn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        weatherBtn = findViewById(R.id.btn_find_weather);
        weatherBtn.setOnClickListener(v -> findWeather());
    }

    private void findWeather() {
        // 替换成你自己的OpenWeatherMap API地址
        String apiUrl = "https://api.openweathermap.org/data/2.5/weather?q=Shanghai&appid=YOUR_API_KEY";
        new DownloadTask().execute(apiUrl);
    }

    private class DownloadTask extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... urls) {
            String result = "";
            HttpURLConnection connection = null;
            InputStream inputStream = null;

            try {
                URL url = new URL(urls[0]);
                connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.connect();

                inputStream = connection.getInputStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                StringBuilder sb = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
                result = sb.toString();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (connection != null) {
                    connection.disconnect();
                }
            }
            return result;
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            if (s != null) {
                // 这里可以添加JSON解析逻辑,把数据显示到UI上
                Log.d("WeatherData", s);
                Toast.makeText(MainActivity.this, "数据加载完成", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(MainActivity.this, "加载失败,请检查网络", Toast.LENGTH_SHORT).show();
            }
        }
    }
}

最后提醒下:AsyncTask其实已经被官方标记为过时了,等你熟悉基础后,可以学习用Coroutines(协程)或者Retrofit这类更现代的网络请求方案,会更简洁稳定~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:22:45