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

SwipeRefreshLayout进度条完成后无法隐藏问题求助

解决SwipeRefreshLayout下拉刷新后进度条持续显示的问题

嗨,这个问题其实很常见——你只是漏掉了在刷新流程完成(不管成功还是失败)后,手动通知SwipeRefreshLayout停止刷新状态!它的进度条不会自动消失,必须调用特定方法来关闭。

核心问题分析

SwipeRefreshLayout的刷新状态完全由开发者控制:调用setRefreshing(true)会启动刷新动画,而只有调用setRefreshing(false)才能让进度条停下来。你的代码里只触发了数据请求,但没有在请求/数据库操作完成后执行这个关键步骤。

具体修改方案

我们可以通过回调接口让UserRepository在数据操作完成后通知MainActivity,从而关闭刷新动画。

第一步:给UserRepository添加回调接口

修改UserRepository.java,新增一个回调接口,并在数据操作的成功/失败回调里通知外部:

// 新增回调接口,用于通知刷新结果
public interface OnUserListLoadedListener {
    void onSuccess();
    void onError(String errorMessage);
}

public void getUserList(final OnUserListLoadedListener listener){
    Retrofit retrofit = RetrofitClient.getInstance();
    ApiService apiService = retrofit.create(ApiService.class);
    Call<List<User>> userList = apiService.getUser();
    userList.enqueue(new Callback<List<User>>() {
        @Override
        public void onResponse(Call<List<User>> call, final Response<List<User>> response) {
            Completable.fromAction(new Action() {
                @Override
                public void run() throws Exception {
                    if(response.body() != null) {
                        List<User> list = response.body();
                        for (int i = 0; i < list.size(); i++) {
                            String id = list.get(i).get_id();
                            String names = list.get(i).getName();
                            String age = list.get(i).getAge();
                            User user = new User(id,names,age);
                            userDb.userDao().Insert(user);
                        }
                    }
                }
            }).subscribeOn(Schedulers.io())
              .observeOn(AndroidSchedulers.mainThread())
              .subscribe(new CompletableObserver() {
                  @Override
                  public void onSubscribe(Disposable d) {
                  }
                  @Override
                  public void onComplete() {
                      Toast.makeText(context,"Data inserted",Toast.LENGTH_SHORT).show();
                      // 通知MainActivity:数据插入成功,可停止刷新
                      listener.onSuccess();
                  }
                  @Override
                  public void onError(Throwable e) {
                      Toast.makeText(context,e.getMessage(),Toast.LENGTH_LONG).show();
                      // 通知MainActivity:数据插入失败
                      listener.onError(e.getMessage());
                  }
              });
        }
        @Override
        public void onFailure(Call<List<User>> call, Throwable t) {
            Toast.makeText(context,t.getMessage(),Toast.LENGTH_LONG).show();
            // 通知MainActivity:网络请求失败
            listener.onError(t.getMessage());
        }
    });
}

第二步:在MainActivity中处理回调,停止刷新

修改MainActivity.java的刷新监听,在回调里调用setRefreshing(false):

refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
    @Override
    public void onRefresh() {
        userRepository.getUserList(new UserRepository.OnUserListLoadedListener() {
            @Override
            public void onSuccess() {
                // 停止刷新动画
                refresh.setRefreshing(false);
                // 可选:这里可以重新从数据库获取数据,更新RecyclerView的适配器
                // 比如:userAdapter.setData(newUserList); userAdapter.notifyDataSetChanged();
            }

            @Override
            public void onError(String errorMessage) {
                // 即使请求/插入失败,也要停止刷新,避免进度条一直转
                refresh.setRefreshing(false);
            }
        });
    }
});

更贴合MVVM的优化建议

如果想更符合MVVM的解耦思想,推荐使用LiveData代替回调:

  1. 在UserRepository中返回LiveData,封装数据请求的状态(成功/失败/加载中)
  2. 在ViewModel中持有这个LiveData,并处理业务逻辑
  3. 在MainActivity中观察ViewModel的LiveData,收到状态更新后停止刷新动画

这种方式能避免回调嵌套,让代码更清晰易维护。

内容的提问来源于stack exchange,提问作者Digvijay Singh Thakur

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:37:04