以下基于Rxjava1.x氢橙, 主要面向目標(biāo)是有多種Callback的改造沃测。
現(xiàn)有功能
假設(shè)現(xiàn)有功能如下:
public class MockService {
void getName(String url, StringCallBack stringCallBack){
stringCallBack.callString("Hello world!");
}
void getAge(String url, IntCallback intCallback){
intCallback.callInt(18);
}
}
public abstract class IntCallback {
public abstract void callInt(int value);
}
public abstract class StringCallback {
public abstract void callString(String string);
}
現(xiàn)在希望可以把這些callback
方式遂铡,變成返回Observable<T>
的方式器仗。
思考
下面的Observable 都指Rxjava中的Observable
方案一
Callback與Observable的結(jié)合就是需要在Callback調(diào)用Observable綁定Observer的onNext之類(lèi)的方法。所以我們需要生成兩部分內(nèi)容漱抓,一個(gè)特殊的Callback和一個(gè)特殊的Observable表锻。用一個(gè)類(lèi)來(lái)存儲(chǔ)這兩個(gè)信息:
public class ResultHolder<T, R> {
public Observable<T> observable;
public R callback;
}
// 使用的時(shí)候大概這種感覺(jué)
public static void main(String[] args){
MockService mockService = new MockService();
ResultHolder<MockData, StringCallback> holder = ...;
mockService.getName("xxxx", holder.callback);
holder.observable.subscribe(mockData -> {});
}
下面思考如何生成這個(gè)holder。我們有多種Callback返回的類(lèi)型也是多種的所以需要設(shè)計(jì)一個(gè)如下的東西:
public <T,R> ResultHolder<T,R> create(Type resultType, Type callbackType){
...
}
我們需要得到返回Observable<T>
和R表示的callback
,這兩個(gè)類(lèi)型是不確定的乞娄。所以需要在參數(shù)中傳入這兩個(gè)類(lèi)型瞬逊,這樣函數(shù)內(nèi)部就可以確定外部想要的期望結(jié)果,并進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換补胚。
public <T,R> ResultHolder<T,R> create(Type resultType, Type callbackType){
ResultHolder<T, R> resultHolder = new ResultHolder<>();
PublishSubject<T> subject = PublishSubject.create();
resultHolder.observable = subject;
TypeAdapter<T> typeAdapter = getAdapter(callbackType);
resultHolder.callback = typeAdapter.getCallback(getConverter(resultType), subject);
return resultHolder;
}
Observable就使用Subject對(duì)象, 這樣它既是Observable又是Observer码耐。為了能讓Observable和Callback做出關(guān)聯(lián)追迟,需要把Observer傳入到Callback的具體實(shí)現(xiàn)中溶其,這里Callback的具體實(shí)現(xiàn)是有限個(gè)的。所以可以把有限的Callback實(shí)現(xiàn)先存起來(lái)敦间,用的時(shí)候再找到使用就可以了瓶逃。根據(jù)這個(gè)要求完成該類(lèi):
public class RxJavaCallbackHelper {
private final Converter.Factory mConverterFactory;
private Map<TypeToken<?>, TypeAdapter<?>> mCached;
public RxJavaCallbackHelper(Converter.Factory factory){
mConverterFactory = factory;
mCached = new HashMap<>();
mCached.put(TypeToken.get(StringCallback.class), new StringCallbackAdapter<>());
}
public <T,R> ResultHolder<T,R> create(Type resultType, Type callbackType){
ResultHolder<T, R> resultHolder = new ResultHolder<>();
PublishSubject<T> subject = PublishSubject.create();
resultHolder.observable = subject;
TypeAdapter<T> typeAdapter = getAdapter(callbackType);
resultHolder.callback = typeAdapter.getCallback(getConverter(resultType), subject);
return resultHolder;
}
@SuppressWarnings("unchecked")
public <T> TypeAdapter<T> getAdapter(Type type){
return (TypeAdapter<T>) mCached.get(TypeToken.get(type));
}
@SuppressWarnings("unchecked")
public <T> Converter<T> getConverter(Type type){
return (Converter<T>) mConverterFactory.createConverter(type);
}
}
public interface TypeAdapter<T>{
<R> R getCallback(Converter<T> converter, Observer<T> observer);
}
public interface Converter<T> {
T convert(String str);
interface Factory{
Converter<?> createConverter(Type type);
}
}
TypeToken是Gson里的類(lèi),使用TypeToken是因?yàn)槠鋵?shí)現(xiàn)了判斷兩個(gè)Type是否相等的方法廓块。這里有兩處使用了強(qiáng)制類(lèi)型轉(zhuǎn)換厢绝,不過(guò)這兩個(gè)地方都通過(guò)參數(shù)傳入了期望的Type所以強(qiáng)制類(lèi)型轉(zhuǎn)換也是按預(yù)期進(jìn)行的。
public class GsonConverterFactory implements Converter.Factory {
private Gson mGson;
public GsonConverterFactory(Gson gson){
mGson = gson;
}
@Override
public Converter<?> createConverter(Type type) {
return new GsonConverter<>(mGson, type);
}
}
public class GsonConverter<T> implements Converter<T> {
private final Gson mGson;
private final Type mType;
public GsonConverter(Gson gson, Type type){
mGson = gson;
mType = type;
}
@Override
public T convert(String str) {
return mGson.fromJson(str, mType);
}
}
public class StringCallbackAdapter<T> implements TypeAdapter<T> {
@SuppressWarnings("unchecked")
@Override
public <R> R getCallback(Converter<T> converter, Observer<T> observer) {
return (R) new StringCallbackWrapped<>(converter, observer);
}
}
class StringCallbackWrapped<T> extends StringCallback {
private final Converter<T> mConverter;
private final Observer<T> mObserver;
StringCallbackWrapped(Converter<T> converter, Observer<T> observer){
mConverter = converter;
mObserver = observer;
}
@Override
public void callString(String string) {
try {
mObserver.onNext(mConverter.convert(string));
mObserver.onCompelete();
}catch (Exception e){
mObserver.onError(e);
}
}
}
寫(xiě)個(gè)Test測(cè)試下:
public static void main(String[] args){
MockService mockService = new MockService();
RxJavaCallbackHelper helper = new RxJavaCallbackHelper(new GsonConverterFactory(new Gson()));
ResultHolder<MockData, StringCallback> holder = helper.create(MockData.class, StringCallback.class);
mockService.getName("", holder.callback);
holder.observable.subscribe(mockData -> System.out.println("mock data code:" + mockData.code),
(e)->{}, ()->System.out.println("completed!"));
}
然后沒(méi)有結(jié)果輸出带猴,因?yàn)檫@里的MockService是同步操作昔汉,在Observable訂閱之前就已經(jīng)結(jié)束操作了。需要對(duì)上面的代碼進(jìn)行一些改動(dòng)
// RxJavaCallbackHelper
public <T,R> ResultHolder<T,R> create(Type resultType, Type callbackType){
ResultHolder<T, R> resultHolder = new ResultHolder<>();
BehaviorSubject<T> subject = BehaviorSubject.create(); // 可以把最近一次的結(jié)果發(fā)送給訂閱者
resultHolder.observable = rx.Observable.defer(() -> subject.take(1));// 訂閱的時(shí)候才創(chuàng)建一個(gè)只能發(fā)送一次數(shù)據(jù)的Observable
TypeAdapter<T> typeAdapter = getAdapter(callbackType);
resultHolder.callback = typeAdapter.getCallback(getConverter(resultType), subject);
return resultHolder;
}
// StringCallbackWrapped
public void callString(String string) {
try {
mObserver.onNext(mConverter.convert(string));
// mObserver.onCompleted(); 刪除這行拴清,結(jié)束通過(guò)上面的take(1) 處理
}catch (Exception e){
mObserver.onError(e);
}
}
方案二
//直接返回一個(gè)Observable
public <T, R> CallbackObservable<T, R> create(Type resultType, Type callbackType){
...
}
//獲取Callback用來(lái)實(shí)際執(zhí)行
CallbackObservable<T, R> callbackObservable;
Callback callback = callbackObservable.getCallback();
需要看看如何從Subject類(lèi)里進(jìn)行擴(kuò)展吧靶病,還沒(méi)研究
方案三
public <T,R> rx.Observable<T> create(Type resultType, Type callbackType, OnCallbackCreated<R> onCallbackCreated){
...
}
在OnCallbackCreated里把封裝好的Callback傳出來(lái),這種形式還有個(gè)好處是口予,可以真正做到在subscribe的時(shí)候才去執(zhí)行娄周,上面兩種只適合拿到Observable就馬上訂閱的, 不適合先持有等到某個(gè)時(shí)間再訂閱沪停。
結(jié)語(yǔ)
主要就是為了封裝細(xì)節(jié)煤辨,減小外部調(diào)用時(shí)的學(xué)習(xí)成本裳涛。