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

Android天气应用未搜索城市时SwipeRefreshLayout无限刷新如何修复

问题根因

你当前的代码核心问题是将SwipeRefreshLayout的刷新监听器注册逻辑写在了天气数据LiveData的观察回调中,只有当用户搜索过城市、LiveData首次返回数据后,刷新监听器才会被绑定。未搜索城市时下拉刷新,没有对应的停止刷新逻辑,才会出现动画无限加载的情况。另外你原有刷新逻辑只有停止动画的代码,没有实际触发重新请求天气数据的逻辑,下拉刷新功能实际无效。

实现方案

下面分别对应你提出的两个需求给出可直接复用的修改方案:

方案1:未搜索城市前完全禁止下拉刷新(更贴合你的业务逻辑)

修改逻辑:初始化刷新组件时默认禁用下拉功能,首次成功获取到天气数据后再启用刷新权限,同时将刷新监听器从LiveData回调中移到初始化层级,避免重复绑定。
修改后的代码示例:

public class FirstFragment extends Fragment {
    private WeatherDataViewModel viewModel;
    // 新增:保存当前搜索的城市名,用于刷新请求
    private String currentCityName;

    public FirstFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View rootView = inflater.inflate(R.layout.fragment_first, container, false);
        // ... 其他控件初始化代码保持不变
        final SwipeRefreshLayout realSwipe = rootView.findViewById(R.id.real_swipe);
        // 1. 默认禁用下拉刷新
        realSwipe.setEnabled(false);
        // 2. 在此处设置刷新监听器,不要放在LiveData的observe回调内
        realSwipe.setOnRefreshListener(() -> {
            // 触发刷新当前城市的天气数据
            viewModel.setCityName(currentCityName);
            // 增加3秒超时兜底,避免网络请求失败一直显示刷新动画
            new Handler().postDelayed(() -> {
                realSwipe.setRefreshing(false);
            }, 3000);
        });

        // Get our ViewModel instance
        viewModel = new ViewModelProvider(requireActivity()).get(WeatherDataViewModel.class);

        // And whenever the data changes, refresh the UI
        viewModel.getWeatherDataLiveData().observe(getViewLifecycleOwner(), data -> {
            // 数据加载完成后首先停止刷新动画
            realSwipe.setRefreshing(false);
            int drawableResource = -1;
            int soundResource = -1;

            if (data != null) {
                // 3. 成功获取到数据后,启用下拉刷新权限
                realSwipe.setEnabled(true);
                // ... 原有数据展示逻辑全部保持不变
            } else {
                Log.e("TAG", "No City found");
                // ... 原有无数据提示逻辑全部保持不变
            }
        });

        return rootView;
    }

    public void getWeatherData(String name) {
        // 保存当前搜索的城市名
        currentCityName = name;
        viewModel.setCityName(name);
    }
}

方案2:未搜索城市时限制刷新加载时长

不需要禁用下拉,只需要兜底停止刷新动画,直接将刷新监听器移到初始化位置,增加未搜索场景的判断即可:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // ... 其他初始化代码不变
    final SwipeRefreshLayout realSwipe = rootView.findViewById(R.id.real_swipe);
    realSwipe.setOnRefreshListener(() -> {
        // 判断是否已搜索过城市
        if (currentCityName == null || viewModel.getWeatherDataLiveData().getValue() == null) {
            // 未搜索场景,1秒后停止刷新并提示
            new Handler().postDelayed(() -> {
                realSwipe.setRefreshing(false);
                Toast.makeText(requireContext(), "请先搜索城市后再刷新", Toast.LENGTH_SHORT).show();
            }, 1000);
            return;
        }
        // 已有城市的正常刷新逻辑
        viewModel.setCityName(currentCityName);
        new Handler().postDelayed(() -> {
            realSwipe.setRefreshing(false);
        }, 3000);
    });
    // ... 后续逻辑不变
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 14:15:03