Android MVVM+RxJava+Retrofit 实战

361 阅读2分钟

什么是MVVM

MVVM(Model-View-ViewModel)是Android官方推荐的架构模式,相较于MVC和MVP,它通过数据绑定实现了更彻底的界面与逻辑分离。

image.png

组件职责对应Android实现
Model数据获取与业务逻辑Repository, DataSource
ViewUI展示与用户交互Activity/Fragment, XML
ViewModel界面状态管理ViewModel, LiveData

什么是Rxjava

RxJava 是响应式编程在 Android 上的核心实现

observable
    .subscribeOn(Schedulers.io()) 
    .observeOn(AndroidSchedulers.mainThread())
操作符作用阶段多次调用效果
subscribeOn数据发射阶段只有第一次生效
observeOn数据接收阶段每次都会改变线程

线程是怎么切换的

  • 通过Scheduler.Worker调度任务
  • observeOn使用队列+线程切换

image.png

主要调度器实现
调度器类型内部机制适用场景
Schedulers.io()动态扩容线程池(CachedThreadPool)网络/文件IO操作
Schedulers.computation()固定大小线程池(CPU核心数)计算密集型任务
AndroidSchedulers.mainThread()Handler(Looper.getMainLooper())Android UI更新

map 和 flatmap

特性mapflatMap
转换关系1:1 同步转换1:N 异步转换
返回值要求直接返回结果对象返回新的Observable
线程安全默认在调用线程执行可指定子Observable的调度线程
顺序保证严格保持源顺序结果顺序可能变化(除非用concatMap)
典型应用场景简单数据类型转换嵌套异步操作
Observable.just("apple", "banana")
    .map(String::toUpperCase) // 同步转换
    .subscribe(System.out::println);

// 输出(保持原顺序):
// APPLE
// BANANA
Observable.just("user1", "user2")
    .flatMap(username -> 
        queryUserDetail(username).subscribeOn(Schedulers.io())
    .subscribe(System.out::println);

// 可能输出(顺序不确定):
// user2_detail
// user1_detail

doOnNext 非侵入式观察:不影响原始数据流

observable
    .doOnNext(item -> System.out.println("收到数据: " + item))
    .map(...)
    .subscribe(...);

背压 (Backpressure)是响应式编程中处理生产者与消费者速度不匹配的核心机制

Flowable.range(1, 1000)
    .subscribe(new Subscriber<Integer>() {
        private Subscription subscription;
        private int count = 0;

        @Override
        public void onSubscribe(Subscription s) {
            this.subscription = s;
            s.request(10); // 初始请求10个
        }

        @Override
        public void onNext(Integer item) {
            process(item);
            if (++count % 5 == 0) {
                subscription.request(5); // 每处理5个再请求5个
            }
        }

        @Override public void onError(Throwable t) { t.printStackTrace(); }
        @Override public void onComplete() { System.out.println("完成"); }
    });
界面防抖
view.clicks()
    .toFlowable(BackpressureStrategy.LATEST)
    .onBackpressureDrop { showToast("操作过快") }
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe { updateUI() }
searchEditText.textChanges() // 使用RxBinding
    .debounce(500, TimeUnit.MILLISECONDS) // 停止输入500ms后触发
    .filter { it.isNotBlank() }
    .switchMap { query ->
        api.search(query).onErrorReturn { emptyList() }
    }
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe { results ->
        showSearchResults(results)
    }

wanandroid 注册登录MVVM 实践

github.com/luyuqin0115…

build.gradle 配置


// 网络请求相关依赖
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.retrofit2:adapter-rxjava3:2.9.0")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")

// RxJava相关依赖
implementation("io.reactivex.rxjava3:rxjava:3.1.8")
implementation("io.reactivex.rxjava3:rxandroid:3.0.2")

// JSON解析
implementation("com.google.code.gson:gson:2.10.1")

// ViewModel和LiveData
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0")
implementation("androidx.navigation:navigation-compose:2.7.6")

// Material Icons Extended
implementation("androidx.compose.material:material-icons-extended:1.5.4")