公司项目中的网络请求是用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
中的方法传入Activity
或Fragment
实例,然后又需要某些网络请求在Activity
或Fragment
销毁时取消请求来释放资源。看了ViewModel
与RxLifeCycle
源码之后,发现Activity
或者Fragment
会在destroy时调用VIewModel
的onCancel()
方法,然后就有了监听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) {
}
})
}
}