本篇文章已受權微信公衆號 YYGeeker
獨家發佈轉載請標明出處緩存
CSDN學院課程地址bash
- RxJava2從入門到精通-初級篇:edu.csdn.net/course/deta…
- RxJava2從入門到精通-中級篇:edu.csdn.net/course/deta…
- RxJava2從入門到精通-進階篇:edu.csdn.net/course/deta…
- RxJava2從入門到精通-源碼分析篇:edu.csdn.net/course/deta…
應用場景:當用戶點擊發送驗證碼後,在倒計時的時間內是不能夠從新點擊發送驗證碼的,倒計時結束後,發送驗證碼的按鈕從新恢復點擊,這裏舉例子爲3s的倒計時服務器
public void verify(View view) {
final long count = 3;//倒計時時間
final Button button = (Button) view;//當前按鈕
Observable.interval(0, 1, TimeUnit.SECONDS)//定時器
.take(count + 1)//取定時器前4個,當前值:0,1,2,3
.map(new Function<Long, Long>() {
@Override
public Long apply(@NonNull Long aLong) throws Exception {
return count - aLong;//將值轉換下,當前值:3,2,1,0
}
})
.observeOn(AndroidSchedulers.mainThread())//主線程更新UI
.doOnSubscribe(new Consumer<Disposable>() {
@Override
public void accept(@NonNull Disposable disposable) throws Exception {
//監聽訂閱時,將按鈕設置爲不可點擊
button.setEnabled(false);
button.setTextColor(Color.BLACK);
}
})
.subscribe(new Observer<Long>() {
@Override
public void onSubscribe(Disposable d) {}
@Override
public void onNext(Long aLong) {
//設置倒計時文本
button.setText("剩餘" + aLong + "秒");
}
@Override
public void onError(Throwable e) {}
@Override
public void onComplete() {
//事件完成後恢復點擊
button.setEnabled(true);
button.setText("發送驗證碼");
}
});
}
複製代碼
應用場景:在某些應用場景中,用戶會屢次點擊同一個按鈕,致使有屢次點擊事件的產生,若是點擊事件中是網絡請求,那麼就會產生屢次網絡請求。正確的操做應該是,在必定時間內,用戶頻繁點擊屢次按鈕以後,只訪問一次網絡請求。下面針對所說的需求進行編寫微信
寫法一:網絡
/**
* 模擬用戶點擊防抖動
*/
public void query(View view) {
RxUtils.click(view, 2)
.subscribe(new Observer<Object>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Object o) {
System.out.println("onNext");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
System.out.println("onComplete");
}
});
}
//封裝工具
static class RxUtils {
static Observable<Object> click(final View view, long seconds) {
return new ViewClickObservable(view)
.throttleFirst(seconds, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnDispose(new Action() {
@Override
public void run() throws Exception {
if (view != null) {
view.setOnClickListener(null);
}
}
}
);
}
}
//建立一個觀察者
static class ViewClickObservable extends Observable<Object> {
private View view;
public ViewClickObservable(View view) {
this.view = view;
}
//當這個觀察者被訂閱的時候,會執行下面的回調
@Override
protected void subscribeActual(final Observer<? super Object> observer) {
if (view != null) {
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
observer.onNext(v);
}
});
}
}
}
複製代碼
寫法二:app
static class ViewClickObservableOnSubscribe implements ObservableOnSubscribe<Object> {
private ObservableEmitter<Object> emitter;
public ObservableEmitter<Object> getEmitter() {
return emitter;
}
@Override
public void subscribe(ObservableEmitter<Object> e) throws Exception {
this.emitter = e;
}
}
//封裝工具
static class RxUtils {
static Observable<Object> clicks(final View view, long seconds) {
final ViewClickObservableOnSubscribe viewClickObservableOnSubscribe = new ViewClickObservableOnSubscribe();
if (view != null) {
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ObservableEmitter<Object> emitter = viewClickObservableOnSubscribe.getEmitter();
if (emitter != null && !emitter.isDisposed()) {
emitter.onNext(1);
}
}
});
}
return Observable
.create(viewClickObservableOnSubscribe)
.throttleFirst(seconds, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnDispose(new Action() {
@Override
public void run() throws Exception {
if (view != null) {
view.setOnClickListener(null);
}
}
}
);
}
}
/**
* 模擬用戶點擊防抖動
*/
public void query(View view) {
RxUtils.clicks(view, 2)
.subscribe(new Observer<Object>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Object o) {
System.out.println("onNext");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
System.out.println("onComplete");
}
});
}
複製代碼
應用場景:假如咱們當前在好友聊天列表
界面中,客戶端須要經過好友列表的uid
去查詢好友列表中會員信息
,而後顯示會員圖標等信息。假如聊天列表界面中的好友數量有成千上百個,客戶端每次從後臺批量查詢用戶會員信息後,須要在本地作緩存,若是這時用戶在聊天列表中進入某個羣聊
界面,這個時候仍是須要去獲取羣聊中
的全部用戶的會員信息,若是羣聊界面
中也包含有本身的好友,那麼咱們就會去判斷,若是用戶的會員信息在緩存中存在,則從緩存中獲取,若是在緩存中不存在,則加入到一個請求集合中,批量查詢會員信息後,合併本地緩存的會員信息和新的服務器的會員信息,將信息返回給羣聊界面
ide
一、建立會員實體類工具
private HashMap<Long, Vip> mVipCache = new HashMap<>();//做爲緩存的類型
public static class Vip {
//會員信息實體類
}
複製代碼
二、模擬從本地獲取數據源碼分析
uid
參數,從緩存和網絡中獲取會員信息的數據vipInfo
uid
加入到請求列表mRequestList
/**
* 從本地緩存中獲取數據
*/
public Observable<HashMap<Long, Vip>> getVipFromCache(List<Long> uids) {
List<Long> mRequestList = new ArrayList<>();
HashMap<Long, Vip> vipInfo = new HashMap<>();
for (Long uid : uids) {
if (mVipCache.containsKey(uid)) {
Log.e("TAG", "從本地獲取數據:" + uid + "用戶");
vipInfo.put(uid, mVipCache.get(uid));//若是緩存中有數據,則從本地中取出
} else {
Log.e("TAG", "從網絡獲取數據:" + uid + "用戶");
mRequestList.add(uid);//若是緩存中沒有數據,則加入到網絡請求列表中
}
}
if (mRequestList.isEmpty()) {
//若是請求列表中爲空,則直接返回緩存的數據
return Observable.just(vipInfo);
}
//合併緩存的數據和網絡獲取的數據
return Observable.merge(Observable.just(vipInfo), getVipFromWeb(mRequestList));
}
複製代碼
三、模擬從服務器獲取數據ui
/**
* 從網絡上批量查詢Vip信息
*/
public Observable<HashMap<Long, Vip>> getVipFromWeb(List<Long> uids) {
//因爲這裏沒有對應的接口,因此模擬請求網絡數據
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//模擬返回的數據
HashMap<Long, Vip> vip = new HashMap<>();
for (Long uid : uids) {
//後臺返回的數據進行賦值
Vip vipInfo = new Vip();
//vipInfo.xxx = WebValue;
//vipInfo.xxx = WebValue;
vip.put(uid, vipInfo);
}
//緩存到本地
mVipCache.putAll(vip);
return Observable.just(vip);
}
複製代碼
四、模擬合併本地數據和服務器數據
/**
* 模擬合併本地信息和服務器信息
*/
public void vip(View view) {
List<Long> uids = new ArrayList<>();
Log.e("TAG", "第一次查詢,進入好友列表界面,查詢好友列表的會員信息");
uids.add(1L);
uids.add(2L);
getVipFromCache(uids);
uids.clear();
Log.e("TAG", "第二次查詢,進入羣聊界面,查詢羣聊中的會員信息");
uids.add(1L);
uids.add(3L);
uids.add(4L);
getVipFromCache(uids);
uids.clear();
Log.e("TAG", "第三次查詢,定時更新最新會員信息,更新全部緩存裏的數據");
uids.add(1L);
uids.add(2L);
uids.add(3L);
uids.add(4L);
mVipCache.clear();
getVipFromCache(uids);
}
複製代碼
五、輸出結果
達到咱們預期的設想和最優的解決方案
第一次查詢,進入好友列表界面,查詢好友列表的會員信息
從網絡獲取數據:1用戶
從網絡獲取數據:2用戶
第二次查詢,進入羣聊界面,查詢羣聊中的會員信息
從本地獲取數據:1用戶
從網絡獲取數據:3用戶
從網絡獲取數據:4用戶
第三次查詢,定時更新最新會員信息,更新全部緩存裏的數據
從網絡獲取數據:1用戶
從網絡獲取數據:2用戶
從網絡獲取數據:3用戶
從網絡獲取數據:4用戶
複製代碼