關於RxJava原理分析,請參考仍物線寫的文章—-給 Android 開發者的 RxJava 詳解。本文不對原理作過多的分析,從最快上手的角度,讓開發者使用起來,當我們有實踐經驗後回過頭來看原理分析會更清晰。
本系列共有三篇文章,分別關於Rxjava的基礎使用(最快,最實用),Retrofit使用(Github上star達22k+,安卓領域排名第一),最後是RxCache緩存(大部分app都支持離線查看功能)。
安卓開發進階之RxJava在實際項目中使用–第二篇
本文是第一篇,從防止重複點擊,監聽內容變化,延遲操作,週期性操作,RxJava的生命週期管理,監聽網絡狀態和權限管理七個方面介紹,這些都是我在實際項目使用到的,不是理論上的介紹。
先來看完整的運行效果
一、防止重複點擊
首先添加引用
compile 'com.jakewharton.rxbinding2:rxbinding:2.0.0'
添加代碼
RxView.clicks(tv1).throttleFirst(2, TimeUnit.SECONDS)
.subscribe(new Consumer<Object>() {
@Override
public void accept(Object o) throws Exception {
Log.d("tvClick","2秒內只能點擊一次");
Toast.makeText(MainActivity.this,"2秒內只能點擊一次",Toast.LENGTH_LONG).show();
}
});
運行效果
二、監聽內容變化
不需要重寫EditText控件的textWacher,然後寫一大堆代碼了,看看下面是如何優雅的實現的。
監聽單個輸入框內容
RxTextView.textChanges(et1).skip(1).subscribe(new Consumer<CharSequence>() {
@Override
public void accept(CharSequence charSequence) throws Exception {
if (TextUtils.isEmpty(charSequence.toString())) enableButton(btn1,false,0.2f);
else enableButton(btn1,true,1f);
}
});
監聽多個輸入框內容
Observable<CharSequence> ob1= RxTextView.textChanges(et2).skip(1);
Observable<CharSequence> ob2= RxTextView.textChanges(et3).skip(1);
Observable.combineLatest(ob1, ob2, new BiFunction<CharSequence, CharSequence, Boolean>() {
@Override
public Boolean apply(CharSequence charSequence, CharSequence charSequence2) throws Exception {
return !TextUtils.isEmpty(charSequence) && !TextUtils.isEmpty(charSequence2);//返回值可以自定義,比如至少6位
}
}).subscribe(new Consumer<Boolean>() {
@Override
public void accept(Boolean aBoolean) throws Exception {//aBoolean值來源於上面apply方法的返回值
if (aBoolean) enableButton(btn2,true,1f);
else enableButton(btn2,false,0.2f);
}
});
三、延遲操作
Observable.timer(3,TimeUnit.SECONDS).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception { Toast.makeText(MainActivity.this,"RxJava延遲3秒操作",Toast.LENGTH_LONG).show();
}
});
四、週期性操作
週期性操作再也不用自帶的Timer,不用new Timer(), new TimeTask(),這樣寫的零零散散,使用RxJava,讓一切優雅起來。。。
Observable.interval(3,TimeUnit.SECONDS).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Toast.makeText(MainActivity.this,"RxJava間隔3秒週期性操作,當前時間:"+System.currentTimeMillis(),Toast.LENGTH_LONG).show();
}
});
如果上面代碼中沒有設置運行所在的線程subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
則會報錯
io.reactivex.exceptions.OnErrorNotImplementedException: Can’t create handler inside thread that has not called Looper.prepare()
從上面的運行效果可以看到退出app後該定時操作沒有被取消,所以就有了下面對RxJava的生命週期管理工–RxLifeCycle。
五、LifeCycle生命週期管理(針對上面的週期性操作
先添加Maven庫
maven { url "https://www.jitpack.io" }
然後添加引用
compile 'com.github.nekocode.rxlifecycle:rxlifecycle:1.1'
@Override
public void accept(Long aLong) throws Exception {
Toast.makeText(MainActivity.this,"RxJava間隔3秒週期性操作,RxLifeCycle進行生命週期管理",Toast.LENGTH_LONG).show();
}
});
第四、五兩種週期性操作的區別在於Activity銷燬後此操作是否能被取消,很明顯,後者可以,這也是LifeCycle存在的意義。
六、監聽網絡狀態
compile 'com.github.pwittchen:reactivenetwork-rx2:0.9.1'
ReactiveNetwork.observeNetworkConnectivity(MainActivity.this).subscribe(new Consumer<Connectivity>() {
@Override
public void accept(@NonNull Connectivity connectivity) throws Exception {
if (connectivity.getState() == NetworkInfo.State.CONNECTED) {
Toast.makeText(MainActivity.this,"RxJava檢測到網絡已連接",Toast.LENGTH_LONG).show();
}
else{
Toast.makeText(MainActivity.this,"RxJava檢測到網絡已斷開",Toast.LENGTH_LONG).show();
}
}
});
看了這種實現,你還會去繼承BroadcastReciver,然後去Manifests.xml裏面註冊嗎?然後通過接口回調?太麻煩了。去試試這種簡單明瞭的方式吧。
七、權限管理管理
compile 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.4@aar'
RxPermissions rxPermissions=new RxPermissions(this);
RxView.clicks(findViewById(R.id.getPermissionBtn))
.compose(rxPermissions.ensure(Manifest.permission.WRITE_EXTERNAL_STORAGE))
.subscribe(
new Consumer<Boolean>() {
@Override
public void accept(@NonNull Boolean aBoolean) throws Exception {
if (aBoolean) Toast.makeText(MainActivity.this,"已獲取該權限",Toast.LENGTH_LONG).show();
else Toast.makeText(MainActivity.this,"無法獲取該權限",Toast.LENGTH_LONG).show();
}
}
);
演示中之所以“無法獲取該權限”,是因爲沒有在配置文件Manifests.xml中申請權限,一旦配置了該權限即返回true。另外,RxPermissions的主要用於Android6.0動態申請權限,通過對話框獲取用戶授權,而演示模擬器低於Android6.0,所以沒有彈出對話框。
至此 ,上面所有的代碼及其效果都給大家展示了,相信大家都學會了使用。如果有什麼疑問,可以查看我提供的源碼Demo。下一篇,我將介紹安卓領域網絡請求框架中的宇宙大帝–Retrofit。拭目以待吧。。。