RxJava2.0线程控制(二)

正常情况下, Observable和Observer是工作在同一个线程中的, 也就是说Observable在哪个线程发事件, Observer就在哪个线程接收事件.
当我们在主线程中去创建一个Observable来发送事件, 则这个Observable默认就在主线程发送事件.当我们在主线程去创建一个Observer来接收事件, 则这个Observer默认就在主线程中接收事件.

以Android为例:

@Override                                                                                       
protected void onCreate(Bundle savedInstanceState) {                                            
    super.onCreate(savedInstanceState);                                                         
    setContentView(R.layout.activity_main);                                                     
                                                                          
    Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() {   
        @Override                                                                               
        public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {            
            Log.d(TAG, "Observable thread is : " + Thread.currentThread().getName());           
            Log.d(TAG, "emit 1");                                                               
            emitter.onNext(1);                                                                  
        }                                                                                       
    });                                                                                         
                                                                                                
    Consumer<Integer> consumer = new Consumer<Integer>() {                                      
        @Override                                                                               
        public void accept(Integer integer) throws Exception {                                  
            Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());              
            Log.d(TAG, "onNext: " + integer);                                                   
        }                                                                                       
    };                                                                                          
                                                                                                
    observable.subscribe(consumer);                                                             
}   

运行结果为:

D/TAG: Observable thread is : main
D/TAG: emit 1                     
D/TAG: Observer thread is :main   
D/TAG: onNext: 1 

RxJava内置的线程调度器

在子线程中做耗时的操作, 然后回到主线程中来操作UI

@Override                                                                                       
protected void onCreate(Bundle savedInstanceState) {                                            
   super.onCreate(savedInstanceState);                                                         
   setContentView(R.layout.activity_main);                                                     
                                                                                               
   Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() {   
       @Override                                                                               
       public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {            
           Log.d(TAG, "Observable thread is : " + Thread.currentThread().getName());           
           Log.d(TAG, "emit 1");                                                               
           emitter.onNext(1);                                                                  
       }                                                                                       
   });                                                                                         
                                                                                               
   Consumer<Integer> consumer = new Consumer<Integer>() {                                      
       @Override                                                                               
       public void accept(Integer integer) throws Exception {                                  
           Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());              
           Log.d(TAG, "onNext: " + integer);                                                   
       }                                                                                       
   };                                                                                          
                                                                                               
   observable.subscribeOn(Schedulers.newThread())                                              
           .observeOn(AndroidSchedulers.mainThread())                                          
           .subscribe(consumer);                                                               
}                              

运行结果:

D/TAG: Observable thread is : RxNewThreadScheduler-2  
D/TAG: emit 1                                         
D/TAG: Observer thread is :main                       
D/TAG: onNext: 1  

增加了两行代码:

.subscribeOn(Schedulers.newThread())                                              
.observeOn(AndroidSchedulers.mainThread())   

subscribeOn() 指定的是Observable发送事件的线程, observeOn() 指定的是Observer接收事件的线程.

*注 多次指定Observable的线程只有第一次指定的有效, 也就是说多次调用subscribeOn() 只有第一次的有效, 其余的会被忽略.多次指定Observer的线程是可以的, 也就是说每调用一次observeOn() , observe的线程就会切换一次.

在RxJava中, 已经内置了很多线程选项供我们选择, 例如有

  • Schedulers.io() 代表io操作的线程, 通常用于网络,读写文件等io密集型的操作

  • Schedulers.computation() 代表CPU计算密集型的操作, 例如需要大量计算的操作

  • Schedulers.newThread() 代表一个常规的新线程

  • AndroidSchedulers.mainThread() 代表Android的主线程

这些内置的Scheduler已经足够满足我们开发的需求, 因此我们应该使用内置的这些选项, 在RxJava内部使用的是线程池来维护这些线程, 所有效率也比较高.

实际应用

Android开发中, 经常会将一些耗时的操作放在线程中, 比如网络请求、读写文件、操作数据库等等,耗时操作完成之后回到主线程去更新UI

1. 网络请求

要使用Retrofit,先添加Gradle配置:

	//retrofit
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    //Gson converter
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    //RxJava2 Adapter
    compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
    //okhttp
    compile 'com.squareup.okhttp3:okhttp:3.4.1'
    compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'

随后定义Api接口:

public interface Api {
    @GET
    Observable<LoginResponse> login(@Body LoginRequest request);

    @GET
    Observable<RegisterResponse> register(@Body RegisterRequest request);
}

接着创建一个Retrofit客户端:

private static Retrofit create() {
            OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
            builder.readTimeout(10, TimeUnit.SECONDS);
            builder.connectTimeout(9, TimeUnit.SECONDS);

            if (BuildConfig.DEBUG) {
                HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
                interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
                builder.addInterceptor(interceptor);
            }

            return new Retrofit.Builder().baseUrl(ENDPOINT)
                    .client(builder.build())
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .build();
}

发起请求:

		Api api = retrofit.create(Api.class);
        api.login(request)
             .subscribeOn(Schedulers.io())               //在IO线程进行网络请求
             .observeOn(AndroidSchedulers.mainThread())  //回到主线程去处理请求结果
            .subscribe(new Observer<LoginResponse>() {
                @Override
                public void onSubscribe(Disposable d) {}

                @Override
                public void onNext(LoginResponse value) {}

                @Override
                public void onError(Throwable e) {
                    Toast.makeText(mContext, "登录失败", Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onComplete() {
                    Toast.makeText(mContext, "登录成功", Toast.LENGTH_SHORT).show();
                }
            });

*注 如果在请求的过程中Activity已经退出了, 这个时候如果回到主线程去更新UI, 那么APP就会崩溃,如何解决这个问题?调用dispose()方法时就会切断Observable和Observer, 使得Observer收不到事件, 既然收不到事件, 那么也就不会再去更新UI了.可以在Activity中将这个Disposable 保存起来, 当Activity退出时, 切断它即可.

RxJava中已经内置了一个容器CompositeDisposable
每当得到一个Disposable时就调用CompositeDisposable.add()将它添加到容器中, 在退出的时候, 调用CompositeDisposable.clear() 即可切断所有的Observable和Observer的关联.

2.读写数据库

public Observable<List<Record>> readAllRecords() {
        return Observable.create(new ObservableOnSubscribe<List<Record>>() {
            @Override
            public void subscribe(ObservableEmitter<List<Record>> emitter) throws Exception {
                Cursor cursor = null;
                try {
                    cursor = getReadableDatabase().rawQuery("select * from " + TABLE_NAME, new String[]{});
                    List<Record> result = new ArrayList<>();
                    while (cursor.moveToNext()) {
                        result.add(Db.Record.read(cursor));
                    }
                    emitter.onNext(result);
                    emitter.onComplete();
                } finally {
                    if (cursor != null) {
                        cursor.close();
                    }
                }
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值