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

基于RxSwift+MVVM实现列表页数据自动刷新的方案咨询

RxSwift + MVVM 实现列表页自动更新的正确姿势

首先明确:在RxSwift的响应式逻辑里,别直接在viewWillAppear里硬写刷新代码,得用ViewModel的可观察序列来驱动,既符合MVVM的分工,也能让数据流更清晰。

具体实现步骤

1. 改造你的ViewModel

给ViewModel加一个用来触发刷新的PublishSubject,把数据请求和这个信号绑定,同时保留初始加载的逻辑:

import RxSwift
import RxCocoa

class WinningListViewModel {
    let disposeBag = DisposeBag()
    // 存储列表数据,供ViewController绑定UI
    let winningList = BehaviorRelay<[WinningModel]>(value: [])
    // 刷新触发信号,外部发送事件即可触发数据请求
    let refreshTrigger = PublishSubject<Void>()
    
    init() {
        // 绑定刷新信号与数据请求逻辑
        refreshTrigger
            .flatMapLatest { _ in
                // 你的数据请求方法,返回Observable类型
                return store.getListEventWinning()
                    .catch { error in
                        // 处理请求失败场景,比如打印日志或返回空数组
                        print("拉取数据失败:\(error)")
                        return Observable.just([])
                    }
            }
            .bind(to: winningList)
            .disposed(by: disposeBag)
        
        // 页面初始化时自动触发一次数据加载
        refreshTrigger.onNext(())
    }
}

2. 在ViewController中绑定生命周期信号

利用RxSwift给UIViewController提供的rx.viewWillAppear信号,每次页面即将显示时,给ViewModel的refreshTrigger发送事件,触发数据刷新:

import RxSwift
import RxCocoa

class WinningListViewController: UIViewController {
    let disposeBag = DisposeBag()
    var viewModel: WinningListViewModel!
    @IBOutlet weak var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupBindings()
    }
    
    private func setupBindings() {
        // 将ViewModel的列表数据绑定到TableView
        viewModel.winningList
            .bind(to: tableView.rx.items(cellIdentifier: "WinningCell", cellType: WinningCell.self)) { index, model, cell in
                // 根据你的模型配置Cell内容
                cell.titleLabel.text = model.title
                cell.descLabel.text = model.description
            }
            .disposed(by: disposeBag)
        
        // 绑定页面生命周期信号到ViewModel的刷新触发点
        rx.viewWillAppear
            .map { _ in () } // 将事件转换为Void类型
            .bind(to: viewModel.refreshTrigger)
            .disposed(by: disposeBag)
    }
}

为什么这么做更靠谱?

  • 符合响应式编程思路:所有数据更新都由可观察序列驱动,避免命令式的手动调用,逻辑更顺畅。
  • 架构职责清晰:ViewModel负责数据的获取与管理,ViewController只处理UI绑定和生命周期事件传递,完全契合MVVM的设计原则。
  • 自动处理返回刷新:从详情页返回列表页时,viewWillAppear会自动触发,自然拉取最新数据,无需额外编写页面跳转回调逻辑。

额外优化建议

  • 若担心频繁切换页面导致重复请求,可添加防抖处理:
    refreshTrigger
        .debounce(.milliseconds(300), scheduler: MainScheduler.instance)
        .flatMapLatest { ... }
    
  • 可给ViewModel添加加载状态序列,用于控制加载动画的显示:
    let isLoading = BehaviorRelay<Bool>(value: false)
    
    // 在请求前后更新加载状态
    refreshTrigger
        .do(onNext: { _ in self.isLoading.accept(true) })
        .flatMapLatest { ... }
        .do(onNext: { _ in self.isLoading.accept(false) })
        .bind(to: winningList)
    

内容的提问来源于stack exchange,提问作者Tae Hun Yu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 18:09:25