欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
retrofit-helper 簡(jiǎn)潔的封裝retrofit,優(yōu)雅的取消請求

code小生,一個(gè)專(zhuān)注 Android 領(lǐng)域的技術(shù)平臺

公眾號回復 Android 加入我的安卓技術(shù)群

作者:xchengDroid

鏈接:https://github.com/xchengDroid/retrofit-helper

聲明:本文來(lái)自xchengDroid投稿,轉發(fā)等請聯(lián)系原作者授權

retrofit-helper

Retrofit是很多android開(kāi)發(fā)者都在使用的Http請求庫!他負責網(wǎng)絡(luò )請求接口的封裝,底層實(shí)現是OkHttp,它的一個(gè)特點(diǎn)是包含了特別多注解,方便簡(jiǎn)化你的代碼量,CallAdapter.Factory 和Converter.Factory可以很靈活的擴展你的請求。我們在使用的時(shí)候還是需要封裝一層便于我們使用,retrofit-helper的作用就是再次簡(jiǎn)化你的請求。

  • 1. Retrofit-helper擴展了那些功能

    描述相關(guān)類(lèi)和方法
    回調函數中直接處理請求結果,無(wú)需再次判斷是否成功Callback2.onSuccess(Call2<T> call2, T response)
    請求開(kāi)始和結束監聽(tīng)Callback2.onStart(Call2<T> call2)  和Callback2.onCompleted(Call2<T> call2, @Nullable Throwable t, boolean canceled);
    全局維護多個(gè)Retrofit實(shí)例RetrofitFactory.DEFAULTRetrofitFactory.OTHERS
    統一處理解析結果Callback2.parseResponse(Call2<T> call2, Response<T> response)和   Callback2.parseThrowable(Call2<T> call2, Throwable t)
    全局取消某個(gè)請求CallManager.getInstance().cancel( yourTag )
    攔截器監聽(tīng)下載和上傳進(jìn)度ProgressInterceptor 、ProgressListener
    單獨指定某個(gè)請求的日志級別HttpLoggingInterceptor
  • 2. 封裝邏輯解析

  • 2.1  RetrofitFactory全局管理retrofit實(shí)例

    DEFAULT 靜態(tài)變量管理默認常用的的retrofit對象,OTHERS 管理其他多個(gè)不同配置的retrofit

    /**
     * 創(chuàng )建時(shí)間:2018/4/3
     * 編寫(xiě)人: chengxin
     * 功能描述:管理全局的Retrofit實(shí)例
     */

    public final class RetrofitFactory {
        /**
         * 緩存不同配置的retrofit集合,如不同的url ,converter等
         */

        public static final Map<String, Retrofit> OTHERS = new ConcurrentHashMap<>(2);
        /**
         * 全局的Retrofit對象
         */

        public static volatile Retrofit DEFAULT;private RetrofitFactory() {
    }

    public static <T> create(Class<T> service) {
        //確保多線(xiàn)程的情況下retrofit不為空或者被修改了
        Retrofit retrofit = DEFAULT;
        Utils.checkState(retrofit != null"DEFAULT == null");
        return retrofit.create(service);
    }

    /**
     * @param name 獲取 OTHERS 中指定名字的retrofit
     */

    public static <T> create(String name, Class<T> service) {
        Utils.checkNotNull(name, "name == null");
        Retrofit retrofit = OTHERS.get(name);
        Utils.checkState(retrofit != null,
                String.format("retrofit named with '%s' was not found , have you put it in OTHERS ?", name));
        return retrofit.create(service);
    }
    }
  • 2.2  Call2接口繼承retrofit.Call 重載 enqueue(Callback<T> callback)方法

    enqueue(@Nullable Object tag, Callback2<T> callback2) 方法傳入請求的tag標記此請求,tag標簽就是取消請求所需要的

    /**
     * 創(chuàng )建時(shí)間:2018/4/8
     * 編寫(xiě)人: chengxin
     * 功能描述:添加重載方法{@link Call2#enqueue(Object, Callback2)}方法
     */

    public interface Call2<Textends retrofit2.Call<T{
        /**
         * @param tag       請求的tag,用于取消請求使用
         * @param callback2 請求的回調
         */

        void enqueue(@Nullable Object tag, Callback2<T> callback2);@Override
    Call2<T> clone();
    }
  • 2.3  Callback2 統一處理回調

    請求開(kāi)始、成功處理、失敗處理、成功回調、失敗回調、請求結束在此統一處理,各方法可以根據業(yè)務(wù)的不同自行重寫(xiě),例如:可以重寫(xiě)parseResponse方法根據不通的http code做不同的提示描述 或者

    重寫(xiě)parseThrowable方法處理各種Throwable

    @UiThread
    public abstract class Callback2<T{public abstract void onStart(Call2<T> call2);

    @NonNull
    public Result<T> parseResponse(Call2<T> call2, Response<T> response) {
        T body = response.body();
        if (response.isSuccessful()) {
            if (body != null) {
                return Result.success(body);
            } else {
                return Result.error(new HttpError("暫無(wú)數據", response));
            }
        }

        final String msg;
        switch (response.code()) {
            case 400:
                msg = "參數錯誤";
                break;
            case 401:
                msg = "身份未授權";
                break;
            case 403:
                msg = "禁止訪(fǎng)問(wèn)";
                break;
            case 404:
                msg = "地址未找到";
                break;
            default:
                msg = "服務(wù)異常";
        }
        return Result.error(new HttpError(msg, response));
    }

    /**
     * 統一解析Throwable對象轉換為HttpError對象。如果為HttpError,
     * 則為{@link retrofit2.Converter#convert(Object)}內拋出的異常
     *
     * @param call2 call
     * @param t     Throwable
     * @return HttpError result
     */

    @NonNull
    public HttpError parseThrowable(Call2<T> call2, Throwable t) {
        if (t instanceof HttpError) {
            //用于convert函數直接拋出異常接收
            return (HttpError) t;
        } else if (t instanceof UnknownHostException) {
            return new HttpError("網(wǎng)絡(luò )異常", t);
        } else if (t instanceof ConnectException) {
            return new HttpError("網(wǎng)絡(luò )異常", t);
        } else if (t instanceof SocketException) {
            return new HttpError("服務(wù)異常", t);
        } else if (t instanceof SocketTimeoutException) {
            return new HttpError("響應超時(shí)", t);
        } else {
            return new HttpError("請求失敗", t);
        }
    }

    public abstract void onError(Call2<T> call2, HttpError error);

    public abstract void onSuccess(Call2<T> call2, T response);


    /**
     * @param t        請求失敗的錯誤信息
     * @param canceled 請求是否被取消了
     */

    public abstract void onCompleted(Call2<T> call2, @Nullable Throwable t, boolean canceled);
    }
  • 2.4  HttpError 統一處理異常錯誤

    HttpError類(lèi)中有兩個(gè)成員屬性msg 被body,msg是保存錯誤的描述信息等,body可以保存異常的具體信息或者原始的json等,onError(Call2<T> call2, HttpError error)回調方法可以根據body的具體信息做二次處理。

    /**
     * 通用的錯誤信息,一般請求是失敗只需要彈出一些錯誤信息即可,like{@link retrofit2.HttpException}
     * Created by chengxin on 2017/6/22.
     */

    public final class HttpError extends RuntimeException {
        private static final long serialVersionUID = -134024482758434333L;
        /**
         * 展示在前端的錯誤描述信息
         */

        public String msg;/**
     * <p>
     * 請求失敗保存失敗信息,for example:
     * <li>BusiModel: {code:xxx,msg:xxx} 業(yè)務(wù)錯誤信息</li>
     * <li>original json:  原始的json</li>
     * <li>{@link retrofit2.Response}:錯誤響應體->Response<?></li>
     * <li>Throwable: 拋出的異常信息</li>
     * </p>
     */

    @Nullable
    public final transient Object body;

    public HttpError(String msg) {
        this(msg, null);
    }

    public HttpError(String msg, @Nullable Object body) {
        super(msg);
        if (body instanceof Throwable) {
            initCause((Throwable) body);
        }
        //FastPrintWriter#print(String str)
        this.msg = msg != null ? msg : "null";
        this.body = body;
    }

    /**
     * 保證和msg一致
     */

    @Override
    public String getMessage() {
        return msg;
    }

    @Override
    public String toString() {
        return "HttpError {msg="
                + msg
                + ", body="
                + body
                + '}';
    }
    }
  • 2.5  ExecutorCallAdapterFactory返回Call2請求適配器

    處理請求接口方法返回為Call2的請求適配器工廠(chǎng)類(lèi)

    public final class ExecutorCallAdapterFactory extends CallAdapter.Factory {public static final CallAdapter.Factory INSTANCE = new ExecutorCallAdapterFactory();

    private ExecutorCallAdapterFactory() {
    }

    /**
     * Extract the raw class type from {@code type}. For example, the type representing
     * {@code List<? extends Runnable>} returns {@code List.class}.
     */

    public static Class<?> getRawType(Type type) {
        return CallAdapter.Factory.getRawType(type);
    }

    @Override
    public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
        if (getRawType(returnType) != Call2.class) {
            return null;
        }
        if (!(returnType instanceof ParameterizedType)) {
            throw new IllegalArgumentException(
                    "Call return type must be parameterized as Call2<Foo> or Call2<? extends Foo>");
        }
        final Type responseType = getParameterUpperBound(0, (ParameterizedType) returnType);

        final Executor callbackExecutor = retrofit.callbackExecutor();
        if (callbackExecutor == nullthrow new AssertionError();

        return new CallAdapter<Object, Call<?>>() {
            @Override
            public Type responseType() {
                return responseType;
            }

            @Override
            public Call<Object> adapt(Call<Object> call) {
                return new ExecutorCallbackCall2<>(callbackExecutor, call);
            }
        };
    }
    }
  • 2.6  ExecutorCallbackCall2 繼承Call2代理OkHttpCall處理UI回調

    裝飾者模式代理OkHttpCall的所有方法,線(xiàn)程調度處理 Callback2 的回調方法在主線(xiàn)程執行

    final class ExecutorCallbackCall2<Timplements Call2<T{
        private final Executor callbackExecutor;
        private final Call<T> delegate;/**
     * The executor used for {@link Callback} methods on a {@link Call}. This may be {@code null},
     * in which case callbacks should be made synchronously on the background thread.
     */

    ExecutorCallbackCall2(Executor callbackExecutor, Call<T> delegate) {
        this.callbackExecutor = callbackExecutor;
        this.delegate = delegate;
    }

    @Override
    public void enqueue(final Callback<T> callback) {
        throw new UnsupportedOperationException("please call enqueue(Object tag, Callback2<T> callback2)");
    }

    @Override
    public void enqueue(@Nullable Object tag, final Callback2<T> callback2) {
        Utils.checkNotNull(callback2, "callback2==null");
        CallManager.getInstance().add(this, tag != null ? tag : "NO_TAG");
        callbackExecutor.execute(new Runnable() {
            @Override
            public void run() {
                if (!isCanceled()) {
                    callback2.onStart(ExecutorCallbackCall2.this);
                }
            }
        });

        delegate.enqueue(new Callback<T>() {
            @Override
            public void onResponse(Call<T> call, final Response<T> response) {
                callbackExecutor.execute(new Runnable() {
                    @Override
                    public void run() {
                        callResult(callback2, response, null);
                    }
                });
            }

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

    @UiThread
    private void callResult(Callback2<T> callback2, @Nullable Response<T> response, @Nullable Throwable failureThrowable) {
        try {
            if (!isCanceled()) {
                //1、獲取解析結果
                Result<T> result;
                if (response != null) {
                    result = callback2.parseResponse(this, response);
                    Utils.checkNotNull(result, "result==null");
                } else {
                    Utils.checkNotNull(failureThrowable, "failureThrowable==null");
                    HttpError error = callback2.parseThrowable(this, failureThrowable);
                    result = Result.error(error);
                }
                //2、回調成功失敗
                if (result.isSuccess()) {
                    callback2.onSuccess(this, result.body());
                } else {
                    callback2.onError(this, result.error());
                }
            }
            callback2.onCompleted(this, failureThrowable, isCanceled());
        } finally {
            CallManager.getInstance().remove(this);
        }
    }

    @Override
    public boolean isExecuted() {
        return delegate.isExecuted();
    }

    @Override
    public Response<T> execute() throws IOException {
        return delegate.execute();
    }

    @Override
    public void cancel() {
        delegate.cancel();
    }

    @Override
    public boolean isCanceled() {
        return delegate.isCanceled();
    }

    @SuppressWarnings("CloneDoesntCallSuperClone"// Performing deep clone.
    @Override
    public Call2<T> clone() {
        return new ExecutorCallbackCall2<>(callbackExecutor, delegate.clone());
    }

    @Override
    public Request request() {
        return delegate.request();
    }
    }
  • 2.7  CallManager統一管理請求,取消請求

    全局保存所有的請求,添加 、刪除請求,取消某個(gè)某些匹配tag的請求??梢栽贏(yíng)ctivity 或Fragment的銷(xiāo)毀方法中調用CallManager.getInstance().cancel( yourTag )

    /**
     * 創(chuàng )建時(shí)間:2018/5/31
     * 編寫(xiě)人: chengxin
     * 功能描述:全局管理Call請求管理,just like {@link okhttp3.Dispatcher}
     */

    public final class CallManager implements ActionManager<Call<?>> {
        @GuardedBy("this")
        private final List<CallTag> callTags = new ArrayList<>(4);
        private volatile static CallManager instance;private CallManager() {
    }

    public static CallManager getInstance() {
        if (instance == null) {
            synchronized (CallManager.class) {
                if (instance == null) {
                    instance = new CallManager();
                }
            }
        }
        return instance;
    }

    @Override
    public synchronized void add(Call<?> call, Object tag) {
        Utils.checkState(!contains(call), "Call<?>  " + call + " is already added.");
        callTags.add(new CallTag(call, tag));
    }

    /**
     * 當call結束時(shí)移除
     *
     * @param call Retrofit Call
     */

    @Override
    public synchronized void remove(Call<?> call) {
        if (callTags.isEmpty())
            return;
        for (int index = 0; index < callTags.size(); index++) {
            if (call == callTags.get(index).call) {
                //like okhttp3.Headers#removeAll(String name)
                //remove(int index) 方法優(yōu)于 remove(Object o),無(wú)需再次遍歷
                callTags.remove(index);
                break;
            }
        }
    }

    /**
     * 取消并移除對應tag的call,確保Call被取消后不再被引用,
     * 結合{@link #remove(Call)}方法雙保險
     *
     * @param tag call對應的tag
     */

    @Override
    public synchronized void cancel(final @Nullable Object tag) {
        if (callTags.isEmpty())
            return;
        if (tag != null) {
            for (int index = 0; index < callTags.size(); index++) {
                CallTag callTag = callTags.get(index);
                if (callTag.tag.equals(tag)) {
                    callTag.call.cancel();
                    callTags.remove(index);
                    index--;
                }
            }
        } else {
            for (CallTag callTag : callTags) {
                callTag.call.cancel();
            }
            callTags.clear();
        }
    }

    @Override
    public synchronized boolean contains(Call<?> call) {
        for (CallTag callTag : callTags) {
            if (call == callTag.call) {
                return true;
            }
        }
        return false;
    }

    /**
     * 保存call和tag
     */

    final static class CallTag {
        private final Call<?> call;
        private final Object tag;

        CallTag(Call<?> call, Object tag) {
            Utils.checkNotNull(call == null"call==null");
            Utils.checkNotNull(tag == null"tag==null");
            this.call = call;
            this.tag = tag;
        }
    }
    }
  • 2.8  ProgressInterceptor 攔截器監聽(tīng)下載和上傳進(jìn)度

    繼承okhttp3.Interceptor  ,構造方法中傳入ProgressListener監聽(tīng)進(jìn)度

    /**
     * 創(chuàng )建時(shí)間:2018/8/2
     * 編寫(xiě)人: chengxin
     * 功能描述:上傳或下載進(jìn)度監聽(tīng)攔截器
     */

    public class ProgressInterceptor implements Interceptor {private final ProgressListener mProgressListener;

    public ProgressInterceptor(ProgressListener progressListener) {
        Utils.checkNotNull(progressListener, "progressListener==null");
        this.mProgressListener = progressListener;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        RequestBody requestBody = request.body();
        //判斷是否有上傳需求
        if (requestBody != null && requestBody.contentLength() > 0) {
            Request.Builder builder = request.newBuilder();
            RequestBody newRequestBody = new ProgressRequestBody(requestBody, mProgressListener, request);
            request = builder.method(request.method(), newRequestBody).build();
        }

        Response response = chain.proceed(request);
        ResponseBody responseBody = response.body();
        if (responseBody != null && responseBody.contentLength() > 0) {
            Response.Builder builder = response.newBuilder();
            ResponseBody newResponseBody = new ProgressResponseBody(responseBody, mProgressListener, request);
            response = builder.body(newResponseBody).build();
        }
        return response;
    }
    }
  • 2.9  HttpLoggingInterceptor 可以單獨指定某個(gè)請求的日志級別

    構造OkhttpClient時(shí)添加此攔截器,在請求的服務(wù)方法中添加注解

    @Headers("LogLevel:NONE") 或 @Headers("LogLevel:BASIC") 或 @Headers("LogLevel:HEADERS") 或@Headers("LogLevel:BODY")

    @FormUrlEncoded
    @Headers("LogLevel:HEADERS")
    @POST("user/login")
    Call2<LoginInfo> getLogin(@Field("username") String username, @Field("password") String password);
  • 3.實(shí)戰

  • 3.1 初始化全局Retrofit對象

    Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("http://wanandroid.com/")
                    .callFactory(new OkHttpClient.Builder()
                            .addNetworkInterceptor(httpLoggingInterceptor)
                            .build())
                    //必須添加此adapter 用于構建處理回調
                    .addCallAdapterFactory(ExecutorCallAdapterFactory.INSTANCE)
                    //添加自定義json解析器 
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
     RetrofitFactory.DEFAULT = retrofit;

     //可以添加多個(gè),如:
     RetrofitFactory.OTHERS.put("other",otherRetrofit);
  • 3.2 添加請求服務(wù)接口

    下面為登錄的 post請求

    @FormUrlEncoded
    @POST("user/login")
    Call2<LoginInfo> getLogin(@Field("username") String username, @Field("password") String password);
  • 3.3 添加ILoadingView,用于開(kāi)啟和結束動(dòng)畫(huà)

    Activity 或者Fragment 可以繼承  ILoadingView接口實(shí)現開(kāi)始和結束動(dòng)畫(huà)

    public interface ILoadingView {
        /**
         * 顯示加載
         */

        void showLoading();/**
     * 隱藏加載
     */

    void hideLoading();
    }
  • 3.4 添加AnimCallback 處理動(dòng)畫(huà)

    這里重寫(xiě)parseThrowable處理一些Callback2中為未處理的異常

    public abstract class AnimCallback<Textends Callback2<T{
        private ILoadingView mLoadingView;public AnimCallback(@Nullable ILoadingView loadingView) {
        this.mLoadingView = loadingView;
    }

    @Override
    public void onStart(Call2<T> call2) {
        if (mLoadingView != null)
            mLoadingView.showLoading();
    }

    @Override
    public void onCompleted(Call2<T> call2, @Nullable Throwable t, boolean canceled) {
        if (canceled)
            return;
        if (mLoadingView != null)
            mLoadingView.hideLoading();
    }

    @NonNull
    @Override
    public HttpError parseThrowable(Call2<T> call2, Throwable t) {
        HttpError filterError;
        if (t instanceof JsonSyntaxException) {
            filterError = new HttpError("解析異常", t);
        } else {
            filterError = super.parseThrowable(call2, t);
        }
        return filterError;
    }
    }
  • 3.5 發(fā)起請求

    RetrofitFactory.create(ApiService.class)
            .getLogin("xxxxx""123456")
            .enqueue(hashCode(), new AnimCallback<LoginInfo>(this) {
                @Override
                public void onError(Call2<LoginInfo> call2, HttpError error) {
                    //處理失敗
                }        @Override
            public void onSuccess(Call2<LoginInfo> call2, LoginInfo response) {
               //處理成功 如保存登錄信息等
            }
        });
     //在onDestor中取消未結束的請求
       @Override
        protected void onDestroy() {
            super.onDestroy();
            //hashCode() 能保證唯一性,取消當前頁(yè)面所發(fā)起的所有請求,只要
            // enqueue(tag, callback2) 傳入的是對應的hashCode() 即可
            CallManager.getInstance().cancel(hashCode());
        }
  • 4.注意事項

  • 4.1 構建retrofit是需要ExecutorCallAdapterFactory實(shí)例,否則無(wú)法處理返回為Call2的服務(wù)接口

  • 4.2 Callback2的回調函數均在主線(xiàn)程執行,如果調用了Call2.cancel()方法,除了onCompleted()方法會(huì )執行外其他回調方法都不會(huì )執行

  • 5.下載

    implementation "com.xcheng:retrofit-helper:1.0.0"

retrofit-helper GitHub地址:
https://github.com/xchengDroid/retrofit-helper

Copyright 2019 xchengDroid

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Android中使用Retrofit的五種請求方式案例
Retrofit2文件上傳下載及其進(jìn)度顯示
andorid jar/庫源碼解析之retrofit2
清代<通真>
74張頂級照片剛剛傳來(lái),太壯觀(guān)了!給大家欣賞欣賞!
阿爾捷克少先隊夏令營(yíng)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久