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

MVVM+DataBinding+RxJava架构下,ViewModel向Activity中RecyclerView传数据的正确方式?

MVVM+DataBinding+RxJava下,ViewModel向RecyclerView传数据的正确姿势

兄弟,这个问题问到点子上了——MVVM的核心就是ViewModel和View彻底解耦,绝对不能让ViewModel持有View引用,所以完全不用像MVP那样搞接口回调那套!咱们靠数据驱动就能完美解决,结合你用的DataBinding和RxJava,给你捋清楚步骤:

1. ViewModel只负责暴露可观察的数据源

ViewModel的职责是处理业务逻辑、获取数据,然后把结果放到一个可被观察的数据容器里——用RxJava的Observable/Subject,或者Android Jetpack的LiveData都可以,完全不用管View怎么处理这些数据。

用RxJava的示例:

public class YourViewModel extends ViewModel {
    // 用PublishSubject来发送数据列表的更新
    private final PublishSubject<List<ItemModel>> itemListSubject = PublishSubject.create();
    private final CompositeDisposable disposable = new CompositeDisposable();
    private final ItemRepository repo;

    public YourViewModel(ItemRepository repo) {
        this.repo = repo;
    }

    // 给外部提供订阅的入口
    public Observable<List<ItemModel>> getItemListObservable() {
        return itemListSubject;
    }

    // 触发加载数据的方法
    public void loadItems() {
        disposable.add(
            repo.fetchItemsFromNetwork()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                    itemList -> itemListSubject.onNext(itemList),
                    throwable -> {
                        // 这里可以处理错误,比如发送错误状态的Subject
                        Log.e("ViewModel", "加载数据失败", throwable);
                    }
                )
        );
    }

    @Override
    protected void onCleared() {
        super.onCleared();
        // ViewModel销毁时清理订阅,避免内存泄漏
        disposable.dispose();
    }
}

用LiveData(更贴合Android生命周期)的示例:

public class YourViewModel extends ViewModel {
    private final MutableLiveData<List<ItemModel>> itemListLiveData = new MutableLiveData<>();
    private final CompositeDisposable disposable = new CompositeDisposable();
    private final ItemRepository repo;

    public YourViewModel(ItemRepository repo) {
        this.repo = repo;
    }

    // 对外暴露不可变的LiveData,防止外部修改数据
    public LiveData<List<ItemModel>> getItemListLiveData() {
        return itemListLiveData;
    }

    public void loadItems() {
        disposable.add(
            repo.fetchItemsFromNetwork()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                    itemList -> itemListLiveData.setValue(itemList),
                    throwable -> Log.e("ViewModel", "加载数据失败", throwable)
                )
        );
    }

    @Override
    protected void onCleared() {
        super.onCleared();
        disposable.dispose();
    }
}

2. Activity订阅数据源,更新RecyclerView

Activity作为View层,只需要持有ViewModel的引用(通过ViewModelProvider获取),然后订阅ViewModel提供的可观察数据源,当数据变化时直接更新RecyclerView的Adapter即可——全程ViewModel不知道Activity的存在,完全解耦。

RxJava订阅的示例:

public class YourActivity extends AppCompatActivity {
    private YourViewModel viewModel;
    private ItemAdapter adapter;
    private final CompositeDisposable activityDisposable = new CompositeDisposable();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 初始化ViewModel
        viewModel = new ViewModelProvider(this, new ViewModelProvider.Factory() {
            @NonNull
            @Override
            public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
                return (T) new YourViewModel(new ItemRepository());
            }
        }).get(YourViewModel.class);

        // 初始化RecyclerView和Adapter
        RecyclerView recyclerView = findViewById(R.id.recycler_view);
        adapter = new ItemAdapter();
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        // 订阅ViewModel的数据源,更新Adapter
        activityDisposable.add(
            viewModel.getItemListObservable()
                .subscribe(itemList -> {
                    // 如果是用ListAdapter,用submitList更高效
                    adapter.submitList(itemList);
                    // 普通Adapter的话可以用adapter.setData(itemList)然后notifyDataSetChanged()
                }, throwable -> {
                    // 显示错误提示,比如Toast
                    Toast.makeText(this, "加载失败", Toast.LENGTH_SHORT).show();
                })
        );

        // 触发数据加载
        viewModel.loadItems();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 清理Activity的订阅
        activityDisposable.dispose();
    }
}

LiveData订阅的示例(更省心,自动感知生命周期):

// 替换上面的RxJava订阅部分
viewModel.getItemListLiveData().observe(this, itemList -> {
    adapter.submitList(itemList);
});

3. 结合DataBinding的进阶玩法

如果用DataBinding,还能把ViewModel和布局直接绑定,让数据更新更自动化:

  1. 在布局的<data>标签里引入ViewModel:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="viewModel"
            type="com.yourpackage.YourViewModel" />
    </data>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</layout>
  1. 在Activity里设置DataBinding:
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setViewModel(viewModel);
binding.setLifecycleOwner(this); // 让LiveData能感知生命周期

这样ViewModel的LiveData数据变化时,你只需要在Adapter里监听(或者直接在Activity里绑定),就能自动更新RecyclerView。

为什么不需要MVP的接口?

MVP里用接口是因为Presenter要主动命令View更新,是命令式的;而MVVM是数据驱动——ViewModel只负责生产数据,View通过订阅数据来被动更新,ViewModel完全不知道View的存在,自然不需要接口来传递消息。这种方式让ViewModel的复用性极强,不管是Activity、Fragment还是其他自定义View,只要订阅这个数据源就能用!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:33:53