rxjava应用场景
##rxjava in retrofit
###未使用rxjava时,我们如何使用retrofit
以一个登录请求为例:
- 在一个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 + "");
}
});
}
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