Asked Oct 26th, 2018 3:49 a.m. 476 0 0
  • 476 0 0
+1

Các cách thay thế public progress của AsyncTask bằng RxJava

Share
  • 476 0 0

Hi mọi người, mình đang học thêm về RxJava/RxAndroid. Giả sử trong project của mình có 1 AsyncTask và mình cần phải convert nó sang Rx, mình có AsyncTask đếm từ 1 tới 10 sau mỗi giây như sau:

class MyAsyncTask : AsyncTask<Void, Int, Unit>() {

    override fun doInBackground(vararg params: Void?) {
        Util.log("doInBackground")
        (1..10).forEach {
            publishProgress(it)
            SystemClock.sleep(1000)
        }
    }

    override fun onProgressUpdate(vararg values: Int?) {
        Util.log("onProgressUpdate value = ${values[0]}")
    }

    override fun onPostExecute(result: Unit?) {
        Util.log("onPostExecute")
    }

    override fun onPreExecute() {
        Util.log("onPreExecute")
    }
}

Và kết quả log ra như vầy:

10-26 10:30:43.258 14892-14892/com.example.rxprogressasynctask E/TAG: [Main] onPreExecute
10-26 10:30:43.278 14892-14954/com.example.rxprogressasynctask E/TAG: [Background] doInBackground
10-26 10:30:43.308 14892-14892/com.example.rxprogressasynctask E/TAG: [Main] onProgressUpdate value = 1
10-26 10:30:44.278 14892-14892/com.example.rxprogressasynctask E/TAG: [Main] onProgressUpdate value = 2
10-26 10:30:45.278 14892-14892/com.example.rxprogressasynctask E/TAG: [Main] onProgressUpdate value = 3
10-26 10:30:46.278 14892-14892/com.example.rxprogressasynctask E/TAG: [Main] onProgressUpdate value = 4
10-26 10:30:47.278 14892-14892/com.example.rxprogressasynctask E/TAG: [Main] onProgressUpdate value = 5
10-26 10:30:48.288 14892-14892/com.example.rxprogressasynctask E/TAG: [Main] onProgressUpdate value = 6
10-26 10:30:49.288 14892-14892/com.example.rxprogressasynctask E/TAG: [Main] onProgressUpdate value = 7
10-26 10:30:50.288 14892-14892/com.example.rxprogressasynctask E/TAG: [Main] onProgressUpdate value = 8
10-26 10:30:51.288 14892-14892/com.example.rxprogressasynctask E/TAG: [Main] onProgressUpdate value = 9
10-26 10:30:52.288 14892-14892/com.example.rxprogressasynctask E/TAG: [Main] onProgressUpdate value = 10
10-26 10:30:53.288 14892-14892/com.example.rxprogressasynctask E/TAG: [Main] onPostExecute

Để convert AsyncTask này qua RxJava thì mình sẽ viết theo các cách sau: Cách 1: Sử dụng duy nhất 1 Observable với các hàm tương ứng: onNext() thay cho onProgressUpdate() và onComplete() thay cho onPostExecute()

class MyRxTask1 {

    fun execute() {
        Util.log("onPreExecute")
        Observable.just(arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
                .flatMap {
                    Util.log("doInBackground")
                    Observable.create<Int> { emitter ->
                        it.forEach {
                            emitter.onNext(it)
                            SystemClock.sleep(1000)
                        }
                        emitter.onComplete()
                    }
                }
                .applySchedulers()
                .subscribe({
                    // onNext
                    Util.log("onProgressUpdate value = $it")
                }, {
                    // onError
                }, {
                    // onComplete
                    Util.log("onPostExecute")
                })
    }

    private fun <T> Observable<T>.applySchedulers(): Observable<T> {
        return this.subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread())
    }
}

Cách 2: Sử dụng kết hợp Observable và 1 loại Observable khác là PublishSubject

class MyRxTask2 {

    fun execute() {
        val subject = PublishSubject.create<Int>()
        subject.observeOn(AndroidSchedulers.mainThread()).subscribe {
            Util.log("onProgressUpdate value = $it")
        }
        Util.log("onPreExecute")
        Observable.just(arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
                .doOnNext {
                    Util.log("doInBackground")
                    it.forEach {
                        subject.onNext(it)
                        SystemClock.sleep(1000)
                    }
                }
                .applySchedulers()
                .subscribe {
                    // onNext
                    Util.log("onPostExecute")
                }
    }

    private fun <T> Observable<T>.applySchedulers(): Observable<T> {
        return this.subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread())
    }

}

Câu hỏi là cách đầu tiền có phải cách tốt nhất? Cách thứ 2 có ổn không? Và có còn cách nào khác để implement việc convert từ AsyncTask nữa không? Thanks mọi người!

Viblo
Let's register a Viblo Account to get more interesting posts.