RxJava--Scheduler (線程控制 )

Scheduler調度器,相當於線程控制器
在不指定線程的情況下, RxJava 遵循的是線程不變的原則,即:在哪個線程調用 subscribe(),就在哪個線程生產事件;在哪個線程生產事件,就在哪個線程消費事件。如果需要切換線程,就需要用到 Scheduler (調度器)

Scheduler 的 API

  • Schedulers.immediate(): 直接在當前線程運行,相當於不指定線程。這是默認的 Scheduler
  • Schedulers.newThread(): 總是啓用新線程,並在新線程執行操作。
  • Schedulers.io(): I/O 操作(讀寫文件、讀寫數據庫、網絡信息交互等)所使用的 Scheduler。行爲模式和 newThread() 差不多,區別在於 io() 的內部實現是是用一個無數量上限的線程池,可以重用空閒的線程,因此多數情況下 io() 比 newThread() 更有效率。不要把計算工作放在 io() 中,可以避免創建不必要的線程。
  • Schedulers.computation(): 計算所使用的 Scheduler。這個計算指的是 CPU 密集型計算,即不會被 I/O 等操作限制性能的操作,例如圖形的計算。這個 Scheduler 使用的固定的線程池,大小爲 CPU 核數。不要把 I/O 操作放在 computation() 中,否則 I/O 操作的等待時間會浪費 CPU。
  • 另外, Android 還有一個專用的 AndroidSchedulers.mainThread(),它指定的操作將在 Android 主線程運行。

先看段代碼

//        代碼,數據"1""2""3"將在io線程中發出,在android主線程中接收數據
        Observable.just("1","2","3")
                .subscribeOn(Schedulers.io()) //用來確定數據發射所在的線程,位置放在哪裏都可以,但它是隻能調用一次的。
                .observeOn(AndroidSchedulers.mainThread())//指定 Subscriber 的回調發生在主線程
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        //所在主線程
                        textview.setText(s);
                    }
                });

上面這段代碼中,由於 subscribeOn(Schedulers.io()) 的指定,被創建的事件的內容 1、2、3將會在 IO 線程發出;而由於 observeOn(AndroidScheculers.mainThread()) 的指定,因此 subscriber 數字的打印將發生在主線程 。事實上,這種在 subscribe() 之前寫上兩句 subscribeOn(Scheduler.io())observeOn(AndroidSchedulers.mainThread()) 的使用方式非常常見,它適用於多數的 『後臺線程取數據,主線程顯示』的程序策略。

上面用到兩個方法:subscribeOn()observeOn()
使用 subscribeOn()observeOn() 兩個方法來對線程進行控制了。
subscribeOn(): 指定 subscribe() 所發生的線程,即 Observable.OnSubscribe 被激活時所處的線程。或者叫做事件產生的線程。
observeOn(): 指定 Subscriber 所運行在的線程。或者叫做事件消費的線程。

Scheduler 自由多次切換線程

Observable.just("a","b","c","d")
                .subscribeOn(Schedulers.io())//指定數據發射在哪個線程執行
                .observeOn(Schedulers.newThread())//observeOn方法決定他下面的方法執行在哪個線程中
                .map(func1)//一個新線程中執行
                .observeOn(Schedulers.io())//observeOn方法決定他下面的方法執行在哪個線程中
                .map(func2)//io線程執行
                .observeOn(AndroidSchedulers.mainThread())////observeOn方法決定他下面的方法執行在哪個線程中
                .subscribe(action1);//ui線程執行
 Func1 func1 = new Func1<String,String>() {
        @Override
        public String call(String o) {
            return o+"===newThread===";
        }
    };

    Func1 func2 = new Func1<String,String>() {
        @Override
        public String call(String o) {
            return o+"===io===";
        }
    };

    Action1 action1= new Action1() {
        @Override
        public void call(Object o) {
            Log.d("call",o.toString());
        }
    };

observeOn() 可以調用多次來切換線程,observeOn 決定他下面的方法執行時所在的線程。

subscribeOn() 用來確定數據發射所在的線程,位置放在哪裏都可以,但它是隻能調用一次的。

用於加載圖片:例

//被觀察者,發送的數據是Drawable
        Observable.create(new Observable.OnSubscribe<Drawable>() {
            @Override
            public void call(Subscriber<? super Drawable> subscriber) {
                Drawable drawable = SchedulerLoadImageDemo.this.getResources().getDrawable(R.drawable.ad_smail_3);
                subscriber.onNext(drawable);
                subscriber.onCompleted();
            }
        })
                .subscribeOn(Schedulers.io())//指定subscribe()發生在io線程
                .observeOn(AndroidSchedulers.mainThread())//指定subscribe的回掉發生在主線程
                .subscribe(new Observer<Drawable>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {
                        Toast.makeText(SchedulerLoadImageDemo.this, "Error!", Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onNext(Drawable drawable) {
                        imageView.setImageDrawable(drawable);
                    }
                });
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章