照葫蘆畫瓢寫RxViewModel

​ 公司項目中的網絡請求是用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)
    }

}
複製代碼

而後上面那段代碼就能夠改寫成下面:app

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) {

                    }
            })
    }
    
}
複製代碼
相關文章
相關標籤/搜索