RxJava
RxJava是啥?呵呵!?
關鍵是事件變換,線程調度,響應式編程
而怎麼實現這些呢:最關鍵的就是接口泛型!
實現這些有什麼用呢?
基本概念
Observable: 被觀察者
OnSubscrible: 觀察者
Operator: 觀察者
Subscriber: 訂閱者->其實也是一個觀察者
首先我們要搞懂這三者之間的關係,
其實很簡單
Action: Call方法無返回值
Func: Call方法有返回值
這是基本的對象概念。
這樣子看其實也挺抽象的,怎樣才能真正理解呢?
其實他們是有引入泛型的
然而+上泛型以後就複雜多了
接下來我們看看+上泛型的關係圖
具體化 舉個栗子
上面說的太抽象了–>接下來具體化一下來深入理解這裏的概念
Observable: 被觀察者
抽象的
OnSubscrible: 觀察者–>產品T
Operator< T, R> : 觀察者–>項目組
Subscriber: 訂閱者->其實也是一個觀察者–>抽象的技術
Action–>void call(T t): 產品技能–>提需求
Func< T, R>–>R call(T t): 需求–>轉化成–>功能
具體的
OnSubscribleImpl< T, R> implements OnSubscrible 技術的老大
MapSubscriber< T , R> 具體的技術
事件變換
接下來,咋們就看看事件變換是啥玩意!
其實也就是把< T >跟< R >做交換!
這麼6!?
那麼是怎樣把他們做交換的呢?
這時候我們就可以通過
實現 OnSubscrible: 與 Operator: 兩個接口來實現!
當然這裏面我們應該需要用到 Subscriber: 來幫助!
那麼怎麼搞法呢?!哈哈!
我們可以用心想想!
這裏其實是比較難的,我就直接貼代碼了!
怎麼理解呢?
其實關鍵在於接口對象的使用。
/**
* <b>Project:</b> ${file_name}<br>
* <b>Create Date:</b> 2017/5/29<br>
* <b>Author:</b> Tongson<br>
* <b>Description:</b> ObservableDistinctUntilChanged OnSubscrible對象交換者 供subscrible(Subscriber<? super T> subscriber)調用 <br>
* <b>Description:</b> 技術的老大-->分派任務 <br>
*/
public class OnSubscribleImpl<T, R> implements OnSubscrible<R> {
/**
* 產品
*/
OnSubscrible<T> onSubscrible;
/**
* 交換操縱者 -->需求換成-->具體的功能
* extends 返回類型的限定
* super 參數類型的限定
* T 需求
* R 功能
*/
Operator<? extends R, ? super T> operator;
public OnSubscribleImpl(OnSubscrible<T> onSubscrible, Operator<? extends R, ? super T> operator) {
this.onSubscrible = onSubscrible;
this.operator = operator;
}
/**
* 外部調用
* 讓交換操縱者 返回Subscriber<? super T> tSubscriber
* 老大 讓產品提需求給技術去做功能(分派任務)
*
* @param subscriber
*/
@Override
public void call(Subscriber<? super R> subscriber) {
/**
* operator 項目組
* tSubscriber 技術
*/
Subscriber<? super T> tSubscriber = operator.call(subscriber);
/**
* 老大 直接把產品分派給技術(分派任務)
*/
onSubscrible.call(tSubscriber);
}
}
/**
* <b>Project:</b> ${file_name}<br>
* <b>Create Date:</b> 2017/5/27<br>
* <b>Author:</b> Tongson<br>
* <b>Description:</b> 方法交換操縱者 項目組 具體的觀察者-->具體的項目組<br>
* 項目組
* T 需求
* R 功能
*/
public class OperatorMap<T, R> implements Operator<R, T> {
Func<? super T, ? extends R> transformer;
public OperatorMap(Func<? super T, ? extends R> transformer) {
this.transformer = transformer;
}
@Override
public Subscriber<? super T> call(Subscriber<? super R> subscriber) {
/**
* 返回 Subscriber<? super T> 對象
*/
return new MapSubscriber<>(subscriber, transformer);
}
/**
* 具體的技術
*
* @param <T>
* @param <R>
*/
private class MapSubscriber<T, R> extends Subscriber<T> {
private Subscriber<? super R> actual;
private Func<? super T, ? extends R> mapper;
public MapSubscriber(Subscriber<? super R> actual, Func<? super T, ? extends R> mapper) {
this.actual = actual;
this.mapper = mapper;
}
@Override
public void onNext(T t) {
/**
* Map中call方法的調用
*/
R r = mapper.call(t);
/**
* Subscriber<? super R> 對象中的方法的調用 技術-->做功能
*/
actual.onNext(r);
}
}
}
線程調度
然後我們就來看看
線程是怎樣去控制的?!
其實也不是很難(比起上面的事件變換容易)
主要是通過繼承OnSubscrible中也就是OnSubscrible的兒子提供的線程控制的方法
Schedulers
在call方法中我們用 Observable: subscrible()->調起訂閱的時候在裏面把這方法轉成想要的線程就可以了!
/**
* String 類型 代表需求
* Bitmap 代表 功能
* new OnSubscrible 產品
*/
Observable.create(new OnSubscrible<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
spannableStringBuilder.append("Observable -->Subscriber call:1" + "\n" + "currentThread:" + Thread.currentThread().getName() + "\n");
subscriber.onNext("http://www.baidu.com");
spannableStringBuilder.append("Observable -->Subscriber call:5" + "\n" + "currentThread:" + Thread.currentThread().getName() + "\n");
runOnUiThread(new Runnable() {
@Override
public void run() {
resultTv.setText(spannableStringBuilder);
}
});
}
}).subscribleOnIO().map(new Func<String, Bitmap>() {
//具體的轉換類型角色
//老大讓產品提需求給技術去做功能
@Override
public Bitmap call(String s) {
spannableStringBuilder.append("map-->OnSubscribleImpl call:" + "s:" + s + "\n");
spannableStringBuilder.append("currentThread:" + Thread.currentThread().getName() + "\n");
Bitmap bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.ic_launcher);
return bitmap;
}
}).subscrible(new Subscriber<Bitmap>() {
@Override
public void onNext(Bitmap bitmap) {
spannableStringBuilder.append("Subscriber onNext -->" + "\n" + "currentThread:" + Thread.currentThread().getName() + "\n");
}
});
被觀察者 Observable
/**
* <b>Project:</b> ${file_name}<br>
* <b>Create Date:</b> 2017/5/27<br>
* <b>Author:</b> Tongson<br>
* <b>Description:</b> 被觀察者 <br>
*/
public class Observable<T> {
/**
* 接口 回調
*/
private OnSubscrible<T> onSubscrible;
/**
* 構造器
*
* @param onSubscrible
*/
private Observable(OnSubscrible<T> onSubscrible) {
this.onSubscrible = onSubscrible;
}
/**
* 開始
*
* @param onSubscrible
* @param <T>
* @return
*/
public static <T> Observable<T> create(OnSubscrible<T> onSubscrible) {
return new Observable<>(onSubscrible);
}
/**
* 訂閱
*
* @param subscriber
*/
public void subscrible(Subscriber<? super T> subscriber) {
onSubscrible.call(subscriber);
}
/**
* 實例化 項目組
* 實例化 交換者
*
* @param func
* @param <R>
* @return
*/
public <R> Observable<R> map(Func<? super T, ? extends R> func) {
return lift(new OperatorMap<>(func));
}
/**
* 實例化 老大
* 實例化 對象交換者
*
* @param trOperatorMap
* @param <R>
* @return
*/
public <R> Observable<R> lift(OperatorMap<T, R> trOperatorMap) {
return new Observable<>(new OnSubscribleImpl<>(onSubscrible, trOperatorMap));
}
public Observable<T> subscribleOnIO() {
return create(new OnSubscribleOnIO<T>(this));
}
public Observable<T> subscribleMain() {
return create(new OnSubscrbleMain<T>(new Handler(Looper.getMainLooper()), this));
}
}
這個被觀察者貫穿所有的存在!
首先
create
訂閱
subscrible
map
lift
線程
subscribleOnIO
subscribleMain
return
Observable
這裏的方法都是返回Observable爲了可以繼續調用下去吧
響應式編程
/**
* 響應式編程
*/
spannableStringBuilder.append("btn_2-------------------\n");
Observable.create(new OnSubscrible<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
spannableStringBuilder.append("Observable -->Subscriber call:1" + "\n" + "currentThread:" + Thread.currentThread().getName() + "\n");
subscriber.onNext("http://www.baidu.com");
spannableStringBuilder.append("Observable -->Subscriber call:5" + "\n" + "currentThread:" + Thread.currentThread().getName() + "\n");
}
}).map(new Func<String, Bitmap>() {
//具體的轉換類型角色
@Override
public Bitmap call(String s) {
spannableStringBuilder.append("map-->OnSubscribleImpl call:" + "s:" + s + "\n");
spannableStringBuilder.append("currentThread:" + Thread.currentThread().getName() + "\n");
Bitmap bitmap = BitmapFactory.decodeResource(MainActivity.this.getResources(), R.mipmap.ic_launcher);
return bitmap;
}
}).subscrible(new Subscriber<Bitmap>() {
@Override
public void onNext(Bitmap bitmap) {
spannableStringBuilder.append("Subscriber onNext -->" + "\n" + "currentThread:" + Thread.currentThread().getName() + "\n");
}
});
spannableStringBuilder.append("btn_2-------------------\n\n");
resultTv.setText(spannableStringBuilder);
手寫RxJavaDemo
https://github.com/gepriniusce/TongsonPlay/tree/rxjava
RxJava2用法Demo
https://github.com/amitshekhariitbhu/RxJava2-Android-Samples
RxJava的思想很值得學習
而RxJava框架也是很好,對於複雜邏輯的代碼我們可以直接用Rx這樣子就算換一個同事來看這代碼也比較清晰。