照葫芦画瓢写RxViewModel

1,073 阅读2分钟

​ 公司项目中的网络请求是用Retrofit + RxJava2 + RxLifeCycle来封装的,因为之前项目中MVP架构与MVVM架构都有使用,项目结构显得很乱,现在就要求统一使用MVVM架构,然后就带来了一些问题。之前在ViewModel中做网络请求时,会将Activity传入到网络请求方法中,用RxLifeCycle来做网络请求与生命周期的绑定,在Activity或者Fragment destroy时取消网络请求,比如:

class ExampleViewModel : ViewModel() {
    
    fun download(activity: RxAppCompatActivity, url: String) {
        ExampleApi.getNetService()
        	.download(url)
        	.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
        	.compose(activity.bindUtilEvent(ActivityEvent.Destroy))
        	.subscribe(object: Observer<ResponseBody> {
                    override fun onNext(responseBody: ResponseBody) {
        				//doSomething

			}

                    override fun onSubscribe(d: Disposable) {
                        
                    }

                    override fun onComplete() {
                        
                    }

                    override fun onError(e: Throwable) {

                    }
            })
    }
    
}

​ 当然上面那段代码可以通过Kotlin的扩展方法,变得简练些。经过讨论,决定不再像ViewModel中的方法传入ActivityFragment实例,然后又需要某些网络请求在ActivityFragment销毁时取消请求来释放资源。看了ViewModelRxLifeCycle源码之后,发现Activity或者Fragment会在destroy时调用VIewModelonCancel()方法,然后就有了监听ViewModel取消时自动取消网络请求的想法。下面是具体实现:

//ViewModelEvent.kt

enum class ViewModelEvent {

    ACTIVE,
    CANCEL

}
//RxLifecycleViewModel.kt

class RxLifecycleViewModel private constructor() {

    init {
        throw AssertionError("No instances")
    }

    companion object {

        @CheckResult
        fun <T> bindViewModel(lifecycle: Observable<ViewModelEvent>): LifecycleTransformer<T> {
            return bind(lifecycle, VIEW_MODEL_LIFECYCLE)
        }

        // Figures out which corresponding next lifecycle event in which to unsubscribe, for ViewModels
        private val VIEW_MODEL_LIFECYCLE = Function<ViewModelEvent, ViewModelEvent> { lastEvent ->
            when (lastEvent) {
                ViewModelEvent.ACTIVE -> ViewModelEvent.ACTIVE
                ViewModelEvent.CANCEL -> throw OutsideLifecycleException("Cannot bind to view model lifecycle when outside of it.")
            }
        }
    }
}
//RxViewModel.kt

abstract class RxViewModel : ViewModel(), LifecycleProvider<ViewModelEvent> {

    private val lifecycleSubject = BehaviorSubject.create<ViewModelEvent>().apply {
        onNext(ViewModelEvent.ACTIVE)
    }

    override fun lifecycle(): Observable<ViewModelEvent> {
        return lifecycleSubject.hide()
    }

    override fun <T : Any?> bindUntilEvent(event: ViewModelEvent): LifecycleTransformer<T> {
        return RxLifecycle.bindUntilEvent<T, ViewModelEvent>(lifecycleSubject, event)
    }

    override fun <T : Any?> bindToLifecycle(): LifecycleTransformer<T> {
        return RxLifecycleViewModel.bindViewModel(lifecycleSubject)
    }

    override fun onCleared() {
        super.onCleared()
        lifecycleSubject.onNext(ViewModelEvent.CANCEL)
    }

}

然后上面那段代码就可以改写成下面:

class ExampleViewModel : RxViewModel() {
    
    fun download(url: String) {
        ExampleApi.getNetService()
        	.download(url)
        	.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
        	.compose(this.bindUtilEvent(ActivityEvent.Destroy))
        	.subscribe(object: Observer<ResponseBody> {
                    override fun onNext(responseBody: ResponseBody) {
        				//doSomething
    				}

                    override fun onSubscribe(d: Disposable) {
                        
                    }

                    override fun onComplete() {
                        
                    }

                    override fun onError(e: Throwable) {

                    }
            })
    }
    
}