实现简单的 RxKotlin (中)

线程切换的操作在 Rx 里面非常常用,主要有 subscribeOn observeOn 他们都需要一个 Scheduler 参数,很明显这个是接口 可以实现各种 调度器。根据这个我们可以这样写...

//Scheduler.kt
abstract class Scheduler {

    abstract fun createWorker(): Worker

    abstract class Worker {
        abstract fun schedule(action: () -> Unit)
    }
}

Worker 是实际工作的,有个抽象方法 schedule 需要我们去实现
Executor 是 Java 里面线程池的执行器, Executors 里面有各种已经实现的线程池,至此 我们可以来实现一个ExecutorScheduler

//ExecutorScheduler.kt
class ExecutorScheduler(private var executor: Executor) : Scheduler() {

    override fun createWorker(): Worker {
        return WorkerImpl(executor)
    }

    private class WorkerImpl(private var executor: Executor) : Worker() {

        override fun schedule(action: () -> Unit) {
            executor.execute {
                action()
            }
        }
    }
}

参考 rxjava 建立一个 Schedulers 存放 Scheduler,这样就直接可以调用 Schedulers.io()

class Schedulers {
    companion object {

        private val io = ExecutorScheduler(Executors.newSingleThreadExecutor())
       
        fun io(): Scheduler {
            return io
        }
    }
}

实现 Android 特有 的 AndroidScheduler,主要利用 Looper

//LooperScheduler.kt
class LooperScheduler(looper: Looper) : Scheduler() {

    private  var handler : Handler = Handler(looper)

    override fun createWorker(): Worker = LooperSchedulerWorker(handler)

    private class LooperSchedulerWorker(private var handler : Handler) : Worker() {
        override fun schedule(action: () -> Unit) {
            handler.post {
                action()
            }
        }
    }

}
//AndroidSchedulers.kt
class AndroidSchedulers {

    companion object {

        private val mainThread = LooperScheduler(Looper.getMainLooper())

        fun mainThread(): Scheduler {
            return mainThread
        }
    }
}

实现 subscribeOn observeOn

//Observable.kt
fun <R> lift(operator: Operator<R, T>): Observable<R> {
    return create(OnSubscribeLift(onSubscribe!!, operator))
}

fun subscribeOn(scheduler: Scheduler): Observable<T> {
    return create(OperatorSubscribeOn(this, scheduler))
}

fun observeOn(scheduler: Scheduler): Observable<T> {
    return lift(OperatorObserveOn(scheduler))
}

interface Operator<T, R> {
    fun call(subscriber: Subscriber<T>) : Subscriber<R>
}

//OnSubscribeLift.kt
class OnSubscribeLift<T, R>(private var parent: Observable.OnSubscribe<T>, private var operator: Observable.Operator<R, T>) : Observable.OnSubscribe<R>{

    override fun call(subscriber: Subscriber<R>) {
        try {
            val st = operator.call(subscriber)
            st.onStart()
            parent.call(st)
        }catch (e: Exception) {
            subscriber.onError(e)
        }
    }
}

在 rxjava 里面 subscribeOn 只有调用的第一次起作用,而 observeOn 则是看最近的那次调用。
原因在于 subscribeOn 调度的是执行 OnSubscribe 因此多次调用最上游的还是 在 第一次的线程那里执行的,除非更改下游 观察者所在的线程 也就是 observeOn。如果不明白的,可以多看这部分代码或者 rxjava 的源码加深理解。

//OperatorSubscribeOn.kt
class OperatorSubscribeOn<T>(private var source: Observable<T> , private var scheduler: Scheduler) : Observable.OnSubscribe<T>{

    override fun call(subscriber: Subscriber<T>) {
        val worker = scheduler.createWorker()
        worker.schedule {
            source.subscribe(SubscribeOnSubscriber(subscriber))
        }
    }

    class SubscribeOnSubscriber<T>(private var actual: Subscriber<T>): Subscriber<T>() {
        override fun onCompleted() {
            actual.onCompleted()
        }

        override fun onError(t: Throwable) {
            actual.onError(t)
        }

        override fun onNext(t: T) {
            actual.onNext(t)
        }
    }
}

//OperatorObserveOn.kt
class  OperatorObserveOn<T>(private var scheduler: Scheduler): Observable.Operator<T, T> {

    override fun call(subscriber: Subscriber<T>): Subscriber<T> {
        val worker = scheduler.createWorker()
        return object : Subscriber<T>(){
            override fun onCompleted() {
                worker.schedule {
                    subscriber.onCompleted()
                }
            }

            override fun onError(t: Throwable) {
                worker.schedule {
                    subscriber.onError(t)
                }
            }

            override fun onNext(t: T) {
                worker.schedule {
                    subscriber.onNext(t)
                }
            }
        }
    }
}
//Test.kt
Observable.just("1", "2", "3")
                .subscribeOn(Schedulers.io())
                .map {
                    it.toInt() + 1
                }
                .filter {
                    it != 1
                }
                .map {
                    it
                }
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(object : Subscriber<Int>() {
                    override fun onCompleted() {

                    }

                    override fun onError(t: Throwable) {
                    }

                    override fun onNext(t: Int) {
                        System.out.println(t)
                    }
                })
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前言我从去年开始使用 RxJava ,到现在一年多了。今年加入了 Flipboard 后,看到 Flipboard...
    占导zqq阅读 9,205评论 6 151
  • 我从去年开始使用 RxJava ,到现在一年多了。今年加入了 Flipboard 后,看到 Flipboard 的...
    Jason_andy阅读 5,617评论 7 62
  • 引入依赖: implementation 'io.reactivex.rxjava2:rxandroid:2.0....
    为梦想战斗阅读 1,355评论 0 0
  • 最近项目里面有用到Rxjava框架,感觉很强大的巨作,所以在网上搜了很多相关文章,发现一片文章很不错,今天把这篇文...
    Scus阅读 6,907评论 2 50
  • 面试官:“如何制作一个菱形的Button,比如现在button的背景图是个菱形,如何实现点击图片中的菱形内有响应而...
    keyser_fayee阅读 2,019评论 0 0