Android新手求助:天气API数据获取代码无输出问题排查
解决你的天气API请求无输出问题
兄弟,我仔细排查了你的代码,发现几个核心问题,这些就是导致请求无输出、Logcat没内容的关键原因:
1. 流读取的循环条件完全错误
在doInBackground方法里,你写了while (data !=1),但InputStreamReader.read()方法返回**-1**才代表到达流的末尾,返回1只是某个字符的ASCII值。这个错误会导致循环要么直接不执行,要么读取一个字符就终止,最终result是空字符串或不完整内容,后续JSON解析自然会失败。
正确的条件应该是:
while (data != -1)
2. 子线程调用Toast会导致崩溃
doInBackground运行在子线程中,而Toast.makeText必须在主线程执行,你在catch块里调用Toast会直接导致线程崩溃、任务终止,这也是你看不到任何输出的重要原因之一。Toast提示逻辑应该移到onPostExecute方法(该方法在主线程执行)中。
3. JSON解析路径错误
你调用的openweathermap forecast接口中,天气数据并不在weather字段下,而是嵌套在list数组的每个元素里的weather子数组中。原来的解析逻辑完全找错了数据路径,即使拿到了正确的API返回,也无法解析出内容。
4. 流读取效率优化(可选)
你逐个字符拼接字符串的方式效率极低,建议用BufferedReader+StringBuilder优化读取逻辑,避免内存浪费。
修改后的完整代码示例
下面是修正了所有关键问题的代码:
// 先修正类名拼写:DownloasTask → DownloadTask public class DownloadTask extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... urls) { String result = ""; URL url; HttpURLConnection urlConnection = null; try { url = new URL(urls[0]); urlConnection = (HttpURLConnection) url.openConnection(); InputStream in = urlConnection.getInputStream(); // 优化流读取方式 BufferedReader reader = new BufferedReader(new InputStreamReader(in)); StringBuilder sb = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { sb.append(line); } result = sb.toString(); return result; } catch (Exception e) { e.printStackTrace(); Log.i("Exception", "URL请求失败:" + e.getMessage()); // 子线程禁止弹Toast,仅打印日志 return null; } finally { // 关闭连接,避免资源泄漏 if (urlConnection != null) { urlConnection.disconnect(); } } } @Override protected void onPostExecute(String result) { super.onPostExecute(result); // 先判断返回结果是否为空 if (result == null || result.isEmpty()) { Toast.makeText(getApplicationContext(), "无法获取天气数据", Toast.LENGTH_SHORT).show(); return; } try { JSONObject jsonObject = new JSONObject(result); // 正确获取forecast接口的天气数据数组 JSONArray listArr = jsonObject.getJSONArray("list"); String message = ""; for (int i = 0; i < listArr.length(); i++) { JSONObject listItem = listArr.getJSONObject(i); // 每个list项中的weather子数组 JSONArray weatherArr = listItem.getJSONArray("weather"); if (weatherArr.length() > 0) { JSONObject weatherObj = weatherArr.getJSONObject(0); String main = weatherObj.getString("main"); String description = weatherObj.getString("description"); if (!main.isEmpty() && !description.isEmpty()) { message += main + ": " + description + "\r\n"; } Log.i("main", main); Log.i("description", description); } } if (!message.isEmpty()) { textView2.setText(message); } else { Toast.makeText(getApplicationContext(), "未找到天气详情", Toast.LENGTH_SHORT).show(); } } catch (Exception e) { e.printStackTrace(); Log.i("JSON解析错误", "解析天气数据失败:" + e.getMessage()); Toast.makeText(getApplicationContext(), "解析天气数据失败", Toast.LENGTH_SHORT).show(); } } } public void getWeather(View view) { String city = editText.getText().toString().trim(); // 先判断输入是否为空 if (city.isEmpty()) { Toast.makeText(getApplicationContext(), "请输入城市名称", Toast.LENGTH_SHORT).show(); return; } DownloadTask task = new DownloadTask(); // 注意:确保你的appid是有效的,示例id可能有访问限制 task.execute("https://openweathermap.org/data/2.5/forecast?q=" + city + "&appid=b1b15e88fa797225412429c1c50c122a1"); InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(editText.getWindowToken(), 0); }
额外注意事项
- 别忘了在
AndroidManifest.xml中添加网络权限:<uses-permission android:name="android.permission.INTERNET" />,否则网络请求会直接失败。 - AsyncTask在Android 11及以上版本已被废弃,建议后续学习使用
Coroutines或Retrofit等主流网络请求方案。 - 你使用的appid看起来是示例id,建议注册一个自己的有效openweathermap账号获取appid,避免请求被限制。
内容的提问来源于stack exchange,提问作者gouri panda
相关产品推荐
相关产品推荐

