Yêu cầu thg 10 26, 2018 3:49 SA 539 0 0
  • 539 0 0
+1

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

Chia sẻ
  • 539 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
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí