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

Android开发:ArrayList数据被覆盖,RecyclerView仅显天气API最后一项

解决RecyclerView仅显示最后一条天气数据的问题

问题场景

从天气API获取包含日期时间数组、温度、风速等信息的JSON数据,尝试构建Condition列表关联天气状况与对应时间,期望RecyclerView展示所有时段的天气数据,但目前仅能显示列表的最后一个元素。

错误原因

问题出在WeatherActivity的循环逻辑中:

  • 每次循环都会新建ArrayList<Condition>,导致之前添加的数据被丢弃
  • 每次循环都重新初始化RecyclerView的适配器并设置给RecyclerView,最终只有最后一次循环的单元素列表被展示

修复方案

将ArrayList<Condition>的初始化移到循环外部,循环内仅向列表添加Condition对象;待所有数据解析完成后,再在UI线程中配置RecyclerView并设置适配器。同时修复代码中其他潜在问题(如switch分支漏写break)。

修改后的WeatherActivity代码

public class WeatherActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_weather);
        int District = getIntent().getIntExtra("District", -1);
        String latitude = "";
        String longitude = "";
        switch (District) {
            case 0:
                latitude = "55.753600";
                longitude = "37.621184";
                break;
            case 1:
                latitude = "55.838390";
                longitude = "37.525774";
                break;
            case 2:
                latitude = "55.854875";
                longitude = "37.632565";
                break;
            case 3:
                latitude = "55.787715";
                longitude = "37.775631";
                break;
            case 4:
                latitude = "55.692019";
                longitude = "37.754592";
                break;
            case 5:
                latitude = "55.622014";
                longitude = "37.678065";
                break;
            case 6:
                latitude = "55.662735";
                longitude = "37.576187";
                break; // 修复漏写的break
            case 7:
                latitude = "55.778003";
                longitude = "37.443533";
                break;
            case 8:
                latitude = "55.829370";
                longitude = "37.451555";
                break;
            case 9:
                latitude = "55.987583";
                longitude = "37.194250";
                break;
            case 10:
                latitude = "55.355802";
                longitude = "37.146999";
                break;
            case 11:
                latitude = "55.594351";
                longitude = "37.371452";
                break;
            default:
                break;
        }
        String address = "https://api.open-meteo.com/v1/forecast?latitude=" + latitude + "&longitude=" + longitude + "&hourly=temperature_2m,relative_humidity_2m,apparent_temperature,precipitation_probability,snowfall,cloud_cover,wind_speed_10m&wind_speed_unit=ms&timezone=Europe%2FMoscow&forecast_days=1";

        new Thread(() -> {
            try {
                URL url = new URL(address);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");

                InputStream stream = connection.getInputStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
                StringBuilder buffer = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    buffer.append(line).append("\n");
                }
                String result = buffer.toString();
                if (reader != null) {
                    try {
                        JSONObject object = new JSONObject(result);
                        JSONArray timeArray = object.getJSONObject("hourly").getJSONArray("time");
                        JSONArray temperatureArray = object.getJSONObject("hourly").getJSONArray("temperature_2m");
                        JSONArray humidityArray = object.getJSONObject("hourly").getJSONArray("relative_humidity_2m");
                        JSONArray precipitationArray = object.getJSONObject("hourly").getJSONArray("precipitation_probability");
                        JSONArray cloudArray = object.getJSONObject("hourly").getJSONArray("cloud_cover");
                        JSONArray windSpeedArray = object.getJSONObject("hourly").getJSONArray("wind_speed_10m");
                        JSONArray snowArray = object.getJSONObject("hourly").getJSONArray("snowfall");

                        // 将列表初始化移到循环外部
                        ArrayList<Condition> conditions = new ArrayList<>();
                        // 提前初始化日期格式化对象,避免重复创建
                        SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm");
                        SimpleDateFormat outputFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm");

                        for (int i = 0; i < timeArray.length(); i++) {
                            String time = timeArray.getString(i);
                            Date date = null;
                            try {
                                date = inputFormat.parse(time);
                            } catch (ParseException e) {
                                e.printStackTrace();
                            }
                            String outputString = outputFormat.format(date);
                            String temperature = temperatureArray.getString(i);
                            String humidity = humidityArray.getString(i);
                            double precipitation = precipitationArray.getDouble(i);
                            double cloud = cloudArray.getDouble(i);
                            String windSpeed = windSpeedArray.getString(i);
                            String snowfall = snowArray.getString(i);

                            // 仅向已有列表添加元素
                            conditions.add(new Condition(outputString, temperature, humidity, precipitation, cloud, windSpeed, snowfall));
                        }

                        // 循环结束后,统一在UI线程配置RecyclerView
                        runOnUiThread(() -> {
                            RecyclerView rcView = findViewById(R.id.recyclerView2);
                            // 仅设置一次LayoutManager(如果布局中没设置的话)
                            if (rcView.getLayoutManager() == null) {
                                rcView.setLayoutManager(new LinearLayoutManager(WeatherActivity.this, LinearLayoutManager.VERTICAL, false));
                            }
                            WeatherAdapter adapter = new WeatherAdapter(conditions);
                            rcView.setAdapter(adapter);
                        });

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }

                connection.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

额外优化建议

  1. 线程安全问题:SimpleDateFormat不是线程安全的,建议使用Java 8+的DateTimeFormatter替代,或者将格式化对象放在循环内(但会增加对象创建开销)。
  2. 网络请求优化:建议使用Retrofit、OkHttp等成熟的网络库替代原生HttpURLConnection,简化网络请求代码并提升稳定性。
  3. RecyclerView性能:可以给WeatherAdapter添加数据更新方法,避免每次都创建新的适配器实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 21:10:54