rxjava应用场景
##rxjava in retrofit

###未使用rxjava时,我们如何使用retrofit

以一个登录请求为例:

  1. 在一个interface中声明一个接口请求
/**
 * 登陆账号
 */
@FormUrlEncoded
@POST("/maoyan/login")
Call<ApiResponse<Login>> login(@FieldMap Map<String, String> postMap);

2、构建一个Retrofit对象,通过Retrofit获取到Call

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(BETA_URL)
        .addConverterFactory(GsonConverterFactory.create(new Gson()))
        .build();
final ApiService apiService = retrofit.create(ApiService.class);
Map<String,String> params = new HashMap<>();
params.put("username","maoyan");
params.put("password","1313123");
apiService.login(params).enqueue(new Callback<ApiResponse<Login>>() {
    @Override
    public void onResponse(Call<ApiResponse<Login>> call, Response<ApiResponse<Login>> response) {
        
    }
 
    @Override
    public void onFailure(Call<ApiResponse<Login>> call, Throwable t) {
        
    }
});

这样就完成了一个登录请求。

###使用rxjava时,我们如何使用retrofit

retrofit的开发者为我们提供了Adapter,可以支持将 OkHttpCall 转换为 Observable。源码分析见后期的retrofit源码分析。

1、在一个interface中声明一个接口请求

/**
 * 登陆账号
 */
@FormUrlEncoded
@POST("/maoyan/login")
Observable<ApiResponse<Login>> login(@FieldMap Map<String, String> postMap);

2、构建一个Retrofit对象,通过Retrofit获取到Observable
!注意在构建时需要指定callAdapterFactory为RxJavaCallAdapterFactory

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(BETA_URL)
        .addConverterFactory(GsonConverterFactory.create(new Gson()))
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .build();
final ApiService apiService = retrofit.create(ApiService.class);
Map<String,String> params = new HashMap<>();
params.put("username","maoyan");
params.put("password","1121212");
apiService.login(params)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Subscriber<ApiResponse<Login>>() {
             
            @Override
            public void onNext(ApiResponse<Login> data) {
            }
 
            @Override
            public void onError(Throwable e) {

            }
             
            @Override
            public void onCompleted() {
 
            }
        });

可以看到执行网络请求和线程切换(网络请求执行在io线程、请求回调执行在UI主线程),以及请求结果的订阅回调,都是一个链式结构。
onNext是请求成功的回调;
onError是请求失败的回调;

##RxBinding
是Android界网红公司Square,Jake Wharton大牛开发的一套将Android UI控件的事件响应转为RxJava Api的形式框架,以一种优雅的方式来处理事件响应。

1.基本用法
Android原生方式

Button b = (Button)findViewById(R.id.button);
b.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {

    }
});

rxbinding方式

Button b = (Button)findViewById(R.id.button);
RxView.clicks(b).subscribe(new Action1<Void>() {
    @Override
    public void call(Void aVoid) {

    }
});

2.防止重复点击

button = (Button) findViewById( R.id.bt ) ;

     RxView.clicks( button )
             .throttleFirst( 2 , TimeUnit.SECONDS )   //两秒钟之内只取一个点击事件,防抖操作
             .subscribe(new Action1<Void>() {
                 @Override
                 public void call(Void aVoid) {
                     Toast.makeText(MainActivity.this, "点击了", Toast.LENGTH_SHORT).show();
                 }
             }) ;

其他如倒计时、表单验证上,采用rxbinding也很方便。

##rxlifecycle
为了解决rxjava引入导致的内存泄漏问题,我们一般的做法是在ondestory时,把请求取消订阅。

rxlifecycle可以很方便的解决这个问题。

class MyFragment extends RxFragment {
 void startHttpReq(){
 this.subscription = httpObservable()
 // 绑定声明周期,在界面退出后自动关闭
 .compose(bindToLifecycle()) 
 .subscribe(

 );
 }
}

也可以设定在特定的声明周期事件时关闭:

class MyFragment extends RxFragment {
 void startHttpReq(){
 this.subscription = httpObservable()
 // 当Fragment运行到onPause时候自动结束调用
 .compose(bindUntilEvent(FragmentEvent.PAUSE)) 
 .subscribe(
 );
 }
}

##rx-preferences
将Android中的sharepreference采用rxjava做了封装。

/创建sharedPreference实例  
SharedPreferences mySP = getApplicationContext().getSharedPreferences("rx_sp_test", Context.MODE_PRIVATE);  
mySP.edit().putString("test_string","this is test rx string").commit();  
  
mySP.edit().putBoolean("test_boolean",true).commit();  
//将sharedPreference作为参数转换成RxSharedPreferences实例  
RxSharedPreferences rxPreferences = RxSharedPreferences.create(mySP);  
  
//获取保存的值  
Preference<String> testString = rxPreferences.getString("test_string");  
Preference<Boolean> testBoolean = rxPreferences.getBoolean("test_boolean", false);  
  
//发射数据  
testString.asObservable()  
        .subscribe(new Action1<String>() {  
            @Override  
            public void call(String username) {  
                Log.e(TAG, "test_string: " + username);  
            }  
        });  
  
testBoolean.asObservable()  
        .subscribe(new Action1<Boolean>() {  
            @Override  
            public void call(Boolean aBoolean) {  
                Log.e(TAG, "test_boolean: " + aBoolean);  
            }  
        });

##RxPermissions

rxjava实现的权限申请。

.request(Manifest.permission.READ_CALENDAR)//这里填写所需要的权限
                        .subscribe(new Action1<Boolean>() {
                            @Override
                            public void call(Boolean aBoolean) {
                                if (aBoolean) {//true表示获取权限成功(注意这里在android6.0以下默认为true)
                                    Log.i("permissions", Manifest.permission.READ_CALENDAR + ":" + 获取成功);
                                } else {
                                    Log.i("permissions", Manifest.permission.READ_CALENDAR + ":" + 获取失败);
                                }
                            }
                        });
            }

public void test() {
        Observable.interval(3, 1, TimeUnit.SECONDS)
                .doOnNext(new Action1<Long>() {
                    @Override
                    public void call(Long aLong) {

                        CinemaAPI api = APIServiceProvider.create(CinemaAPI.class);
                        Observable<List<FocusCinema>> ob = api.getFocusList(true, MovieProApplication.movieProApplication.accountService.getToken());
                        ob.subscribeOn(Schedulers.io())
                                .observeOn(AndroidSchedulers.mainThread())
                                .subscribe(new Action1<List<FocusCinema>>() {
                                    @Override
                                    public void call(List<FocusCinema> focusCinemas) {

                                    }
                                }, new Action1<Throwable>() {
                                    @Override
                                    public void call(Throwable throwable) {

                                    }
                                });

                    }
                }).subscribe(new Observer<Long>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Long aLong) {
                Log.d("...:nht...", aLong + "");
            }
        });


    }

Rxjava开发文档 rxjava实战_Android

Android RxJava 实际应用讲解:(有条件)网络请求轮询(结合Retrofit)

//todo Test
    public void test() {
        CinemaAPI api = APIServiceProvider.create(CinemaAPI.class);
        Observable<List<FocusCinema>> ob = api.getFocusList(true, MovieProApplication.movieProApplication.accountService.getToken());
        ob.repeatWhen(new Func1<Observable<? extends Void>, Observable<?>>() {
            @Override
            public Observable<?> call(Observable<? extends Void> observable) {
                return observable.flatMap(new Func1<Void, Observable<?>>() {
                    @Override
                    public Observable<?> call(Void aVoid) {
                        if (retryCount1 > 3) {
                            return Observable.error(new Throwable("轮询结束"));
                        } else {
                            return Observable.just(1).delay(2000, TimeUnit.MILLISECONDS);
                        }
                    }
                });
            }
        })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<List<FocusCinema>>() {
                    @Override
                    public void call(List<FocusCinema> focusCinemas) {
                        retryCount1 = retryCount1 + 1;
                        Log.d(":nht...", "执行了");
                    }
                }, new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                        Log.d(":nht...", "error");
                    }
                });


    }
    
12-25 09:23:15.105 7237-7237/com.sankuai.moviepro D/:nht...: 执行了
12-25 09:23:16.889 7237-7237/com.sankuai.moviepro D/:nht...: 执行了
12-25 09:23:18.937 7237-7237/com.sankuai.moviepro D/:nht...: 执行了
12-25 09:23:20.969 7237-7237/com.sankuai.moviepro D/:nht...: 执行了
12-25 09:23:23.021 7237-7237/com.sankuai.moviepro D/:nht...: 执行了
12-25 09:23:23.025 7237-7237/com.sankuai.moviepro D/:nht...: error