retrofit如何配合Rxjava封裝程式碼

czZ__czZ發表於2020-12-29

如何使用Retrofit+RxJava框架的簡單封裝使用

掌握之前需要了解以下知識相關知識

retrofit原始碼解析

OkHttp原理解析

RXJava原始碼詳解

上述文章只是講了一下基本的原理,那麼在實際應用裡的如何和RXJAVA配合使用呢

一、怎麼搭配Rxjava使用

我們知道,在使用retrofit的時候可以配置網路請求、日誌、執行緒的介面卡,其中有一個方法addCallAdapterFactory,這個方法就是為我們新增rxjava執行緒排程的介面卡。

 //建立Retrofit物件
        mRetrofit = new Retrofit
                .Builder()
                .client(mOkHttpClientBuilder.build())
                .baseUrl(host)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();

如果我們不進行配置那麼系統會為我們提供一個預設的介面卡defaultCallAdapterFactory

   */
    public Retrofit build() {
       ...........
      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

     ...........
      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }

在這裡層層走下去,會給我們返回一個Response的物件,在實際業務裡,我們需要利用rxjava來進行一些請求的封裝,實現整體程式碼架構更加簡潔

    @Override public void enqueue(final Callback<T> callback) {
      checkNotNull(callback, "callback == null");

      delegate.enqueue(new Callback<T>() {
        @Override public void onResponse(Call<T> call, final Response<T> response) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              if (delegate.isCanceled()) {
                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
              } else {
                callback.onResponse(ExecutorCallbackCall.this, response);
              }
            }
          });
        }

        @Override public void onFailure(Call<T> call, final Throwable t) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              callback.onFailure(ExecutorCallbackCall.this, t);
            }
          });
        }
      });
    }

所以引入了rxjava的封裝,好在retrofit也是支援這種新增,我們加入了RxJava2CallAdapterFactory,最後封裝返回了一個Observable的觀察者物件。

@Override public Object adapt(Call<R> call) {
    Observable<Response<R>> responseObservable = isAsync
        ? new CallEnqueueObservable<>(call)
        : new CallExecuteObservable<>(call);

    Observable<?> observable;
    if (isResult) {
      observable = new ResultObservable<>(responseObservable);
    } else if (isBody) {
      observable = new BodyObservable<>(responseObservable);
    } else {
      observable = responseObservable;
    }

    if (scheduler != null) {
      observable = observable.subscribeOn(scheduler);
    }

    if (isFlowable) {
      return observable.toFlowable(BackpressureStrategy.LATEST);
    }
    if (isSingle) {
      return observable.singleOrError();
    }
    if (isMaybe) {
      return observable.singleElement();
    }
    if (isCompletable) {
      return observable.ignoreElements();
    }
    return observable;
  }

這就是我們使用rxjava的原理,為什麼可以使用以及使用後返回了什麼

當前我們有一個api

public interface ApiService {
//獲取使用者資訊
    @POST(RetrofitManager.ACCOUNT)
    Observable<TextUserInfo> getTextUserInfo(@Body UserInfoRequest userInfoRequest);
}

第一步 :呼叫獲得observable物件

 Observable<TextUserInfo> observable = RetrofitManager.getInstance(activity).create(ApiService.class).
                getTextUserInfo(updateUserInfoRequest).map((new HttpResultFunc<TextUserInfo>()));

 

RetrofitManager封裝對retrofit的初始化,包括對rxjava的執行緒新增,

create就是呼叫retrofit的create,貼上部分程式碼

public class RetrofitManager {
  
    /**
     * 單例模式,建立RetrofitManager物件
     */
    public static RetrofitManager getInstance(Context activity) {
        if (instance == null) {
            synchronized (RetrofitManager.class) {
                instance = new RetrofitManager(activity);
            }
        }
//        instance.setRsa();
        return instance;
    }

    private RetrofitManager(Context context) {
        File cacheFile = new File(context.getCacheDir(), "cache");
        Cache cache = new Cache(cacheFile, 1024 * 1024 * 50); //50Mb
        mOkHttpClientBuilder = new OkHttpClient.Builder();
        mOkHttpClientBuilder.connectTimeout(CONNECT_OUTTIME, TimeUnit.MILLISECONDS);
        mOkHttpClientBuilder.readTimeout(CONNECT_OUTTIME, TimeUnit.MILLISECONDS);
        mOkHttpClientBuilder.writeTimeout(CONNECT_OUTTIME, TimeUnit.MILLISECONDS);
        mOkHttpClientBuilder.retryOnConnectionFailure(true);

        //Logger攔截器,設定列印等級,可以列印請求日誌
        if (LogUtils.LOG_FLAG) {
            mHttpLoggingInterceptor = new HttpLoggingInterceptor();
            mHttpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

            mOkHttpClientBuilder.addInterceptor(mHttpLoggingInterceptor);
        }

        //設定公共攔截器
        mHttpCommonInterceptorBuilder = new HttpCommonInterceptor.Builder();
        try {
            mHttpCommonInterceptorBuilder
                    .addHeaderParams("xd-version-name", OSUtils.getVersionCodeName(context))
                    .addHeaderParams("xd-version-code", OSUtils.getVersionCode(context) + "")
                    .addHeaderParams("xd-agent", "Android");
        } catch (Exception e) {
            e.printStackTrace();
        }
        setAccessToken();
        mOkHttpClientBuilder.addInterceptor(mHttpCommonInterceptorBuilder.build());
        mOkHttpClientBuilder.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                // 以攔截到的請求為基礎建立一個新的請求物件,然後插入Header
                Request request = null;
                try {
                    request = chain.request().newBuilder()
                            .addHeader("antiKey", RsaKeyUtil.encryptByPublicKey(CLIENT_SECRET + ":" + System.currentTimeMillis(), PUBLIC_KEY))
                            .addHeader("xd-request-id", RsaKeyUtil.createRandomCharData(6))
                            .build();
                    if (BuildConfig.DEBUG) {
                        Log.e("TAG", "請求頭==" + request.headers().toString());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                // 開始請求
                return chain.proceed(request);
            }
        });
        //設定快取攔截器
        mHttpCacheInterceptor = new HttpCacheInterceptor();
        gson = new GsonBuilder().registerTypeAdapterFactory(new NullStringToEmptyAdapterFactory()).serializeNulls().create();
        mOkHttpClientBuilder.addNetworkInterceptor(mHttpCacheInterceptor);
        mOkHttpClientBuilder.cache(cache);


        //建立Retrofit物件
        mRetrofit = new Retrofit
                .Builder()
                .client(mOkHttpClientBuilder.build())
                .baseUrl(host)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
    }

    private void setRsa() {
        try {
            mHttpCommonInterceptorBuilder.addHeaderParams("antiKey", RsaKeyUtil.encryptByPublicKey(CLIENT_SECRET + ":" + System.currentTimeMillis(), PUBLIC_KEY));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void setAccessToken() {
        String token = Paper.book().read("access_token");
        if (!TextUtils.isEmpty(token)) {
            mHttpCommonInterceptorBuilder.addHeaderParams("authorization", "bearer " + token);
        } else {
            mHttpCommonInterceptorBuilder.addHeaderParams("authorization", "");
        }
    }

    public <T> T create(Class<T> service) {
        if (api == null) {
            T t = mRetrofit.create(service);
            api = t;
        }
        return (T) api;
    }

    /**
     * rx訂閱 rx1.0的
     */
//    public <T> void toSubscribe(Observable<T> o, Subscriber<T> s) {
//        o.subscribeOn(Schedulers.io())
//                .unsubscribeOn(Schedulers.io())
//                .observeOn(AndroidSchedulers.mainThread())
//                .subscribe(s);
//    }

    /**
     * rx訂閱 rx2.0的
     */
    public <T> void toSubscribe(Observable<T> o, DisposableObserver disposableObserver) {
        o.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(disposableObserver);
    }


    //如果需要存在依賴關係請求使用map或者flatmap
}

create我們知道是呼叫了動態代理,serviceMethod.adapt就是呼叫了RxJava2CallAdapter的adapt,返回了oservable的物件

 public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.adapt(okHttpCall);
          }
        });
  }

通過map裡面的攔截,我們又可以對返回的引數進行定製化的操作,使其能夠適配不同型別的引數返回,如何排程,請參考rxjava的內容,使用map,在apply裡面進行操作.

至此,獲得了應有的物件

二:使用rxjava開啟執行緒排程

建立被觀察者執行緒

DisposableObserver disposable = new ProgressSubscriber<Bean>(new SubscriberOnResponseListenter<Bean>() {

            @Override
            public void next(Bean bean) {
                baseView.getNetWorkSuccess(Bean);
            }

            @Override
            public void error(String e) {
                baseView.showError(e);

            }
        }, activity, false);

 RetrofitManager.getInstance(activity).toSubscribe(observable, disposable);
    /**
     * rx訂閱 rx2.0的
     */
    public <T> void toSubscribe(Observable<T> o, DisposableObserver disposableObserver) {
        o.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(disposableObserver);
    }

 

其實到這裡基本就結束了,我們拿到了網路請求引數的回撥,在這種結構裡,將網路請求,引數設定,方法呼叫完全分開,適用於mvp mvc ,mvvc等各種解耦性質的架構設計.

最後,記得使用完要解綁訂閱者

public class BasePresenter<V> {
    private CompositeDisposable mCompositeDisposable;
    private WeakReference<V> mViewRef;

    public void attachModelView(V pView) {
        mViewRef = new WeakReference<>(pView);
    }
    public V getView() {
        if (isAttach()) {
            return mViewRef.get();
        } else {
            return null;
        }
    }

    private boolean isAttach() {
        return null != mViewRef && null != mViewRef.get();
    }
    //增加訂閱者
    protected void addSubscrebe(Disposable disposable) {
        if (null == mCompositeDisposable) {
            mCompositeDisposable = new CompositeDisposable();
        }
        mCompositeDisposable.add(disposable);

    }

    //解綁訂閱者
    public void unSubscribe() {
        if (null != mCompositeDisposable) {
            mCompositeDisposable.clear();
        }

    }
}

 

 

 

 

 

 

 

相關文章