網(wǎng)絡(luò)框架-Retrofit(三)

簡單實(shí)現(xiàn)Retrofit(替代Okhttp)

1.定義注解參數(shù)

@Documented
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface Field {
    String value();
}
@Documented
@Target(METHOD)
@Retention(RUNTIME)
public @interface Get {
    String value() default "";
}
@Documented
@Target(METHOD)
@Retention(RUNTIME)
public @interface Post {

    String value() default "";
}

2.實(shí)現(xiàn)回調(diào)接口Call和Callback
MyCall .class

public interface MyCall {

     //執(zhí)行網(wǎng)絡(luò)請求(同步:在當(dāng)前網(wǎng)絡(luò))
     String execute() throws Exception;

    //在子線程請求網(wǎng)絡(luò)
    void enqueue(MyCallback callback);
}

MyCallback .class

/**
 * 網(wǎng)絡(luò)請求回調(diào)接口
 */
public interface MyCallback {
  void onResponse( String response);

  void onFailure( Exception e);
}

SystemHttpCall .class

/**
 * Created by Xionghu on 2017/8/14.
 * Desc: 具體的實(shí)現(xiàn)類發(fā)送請求
 */

public class SystemHttpCall implements MyCall {
    private MyServiceMethod serviceMethod;

    public SystemHttpCall(MyServiceMethod serviceMethod) {
        this.serviceMethod = serviceMethod;
    }

    @Override
    public String execute() throws Exception {
        if (serviceMethod.isPost()) {

            return HttpUtils.post(serviceMethod.baseUrl(), serviceMethod.getParam());
        } else {
            return HttpUtils.get(serviceMethod.baseUrl());
        }
    }

    @Override
    public void enqueue(MyCallback callback) {
        HttpTask httpTask = new HttpTask(this, callback);
        httpTask.execute();
    }

    public class HttpTask extends AsyncTask<Void, Void, String> {

        private SystemHttpCall httpCall;
        private MyCallback callback;

        private HttpTask(SystemHttpCall httpCall, MyCallback callback) {
            this.httpCall = httpCall;
            this.callback = callback;
        }

        @Override
        protected String doInBackground(Void... params) {
            try {
                return httpCall.execute();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
            if (this.callback != null) {
                if (result != null) {
                    this.callback.onResponse(result);
                } else {
                    this.callback.onFailure(new Exception("網(wǎng)絡(luò)異常!"));
                }
            }


        }
    }
}

3.解析注解方法獲取相應(yīng)參數(shù)

public class MyServiceMethod {
    private Builder builder;

    public MyServiceMethod(Builder builder) {
        this.builder = builder;
    }

    public boolean isPost() {
        return this.builder.isPost;
    }

    public Map<String, Object> getParam() {
        return this.builder.paramMap;
    }

    public String baseUrl() {
        StringBuffer buffer = new StringBuffer(
                this.builder.retrofit.getBaseUrl() + this.builder.relativeUrl);
        if (!isPost()) {
            // 如果你不是Post請求,是get請求,需要拼接參數(shù)地址
            if (this.builder.paramMap != null) {
                Set<String> keySet = this.builder.paramMap.keySet();
                if (keySet.size() > 0) {
                    buffer.append("?");
                }
                for (String key : keySet) {
                    Object value = this.builder.paramMap.get(key);
                    buffer.append(key);
                    buffer.append("=");
                    buffer.append(value);
                    buffer.append("&");
                }
                buffer.deleteCharAt(buffer.length() - 1);
            }
        }
        return buffer.toString();
    }

    static final class Builder {
        final MyRetrofit retrofit;
        final Method method;
        final Annotation[] methodAnnotations;
        final Annotation[][] parameterAnnotationsArray;

        String relativeUrl;
        // 參數(shù)集合
        Map<String, Object> paramMap;
        Object[] args;

        boolean isPost;

        public Builder(MyRetrofit retrofit, Method method, Object[] args) {
            this.retrofit = retrofit;
            this.method = method;
            // 方法注解列表(相當(dāng)于我們的LoginService中的: @POST和@FormUrlEncoded......)
            this.methodAnnotations = method.getAnnotations();
            // 方法參數(shù)注解列表(相當(dāng)于我們的LoginService中的: @Field......)
            this.parameterAnnotationsArray = method.getParameterAnnotations();
            this.args = args;

            this.paramMap = new HashMap<String, Object>();
        }

        public MyServiceMethod build() {
            // 循環(huán)遍歷方法注解列表
            for (Annotation annotation : methodAnnotations) {
                parseMethodAnnotation(annotation);
            }

            int parameterCount = parameterAnnotationsArray.length;
            for (int p = 0; p < parameterCount; p++) {
                Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
                parseParameterAnnotation(p, parameterAnnotations);
            }

            return new MyServiceMethod(this);
        }

        /**
         * 解析方法注解
         *
         * @param annotation
         */
        public void parseMethodAnnotation(Annotation annotation) {
            // 首先判斷注解類型(解析目的:獲取接口名稱,用于拼接地址)
            if (annotation instanceof Get) {
                this.relativeUrl = ((Get) annotation).value();
                isPost = false;
            } else if (annotation instanceof Post) {
                this.relativeUrl = ((Post) annotation).value();
                isPost = true;
            }
        }

        /**
         * 解析參數(shù)注解
         *
         * @param p
         * @param parameterAnnotations
         */
        private void parseParameterAnnotation(int p,
                                              Annotation[] parameterAnnotations) {
            // 方法參數(shù)值
            Object value = args[p];
            // 遍歷方法參數(shù)注解
            for (Annotation annotation : parameterAnnotations) {
                // 首先需要判斷該注解的類型
                if (annotation instanceof Field) {
                    Field field = (Field) annotation;
                    // 參數(shù)的名稱(接口參數(shù)名稱,服務(wù)器接口規(guī)定的)
                    String key = field.value();
                    paramMap.put(key, value);
                }
            }
        }

    }
}

4.定義MyRetrofit框架

public class MyRetrofit {
    // 緩存方法(為了避免重復(fù)加載方法注解,從而耗費(fèi)性能)
    private final Map<Method, MyServiceMethod> serviceMethodCache = new LinkedHashMap<Method, MyServiceMethod>();
    public String getBaseUrl() {
        return baseUrl;
    }

    public void setBaseUrl(String baseUrl) {
        this.baseUrl = baseUrl;
    }

    private String baseUrl;

   private MyRetrofit(String baseUrl){
       this.baseUrl = baseUrl;
   }

   public <T> T create(Class<T> service){
       //動態(tài)代理實(shí)現(xiàn)
       return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[]{service}, new InvocationHandler() {
           @Override
           public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
               MyServiceMethod serviceMethod = loadServiceMethod(method, args);
               SystemHttpCall httpCall = new SystemHttpCall(serviceMethod);
               return httpCall;
           }
       });

   }
    // 第一步:解析方法(說白了解析方法注解和方法參數(shù)注解)

    // 第二步:實(shí)現(xiàn)網(wǎng)絡(luò)請求

    protected MyServiceMethod loadServiceMethod(Method method, Object[] args) {
        MyServiceMethod result;
        synchronized (serviceMethodCache) {
            result = serviceMethodCache.get(method);
            if (result == null) {
                result = new MyServiceMethod.Builder(this, method, args)
                        .build();
                serviceMethodCache.put(method, result);
            }
        }
        return result;
    }

   public static final class Builder{
       private String baseUrl;

       public Builder baseUrl(String baseUrl){
           this.baseUrl = baseUrl;
           return this;
       }

       public MyRetrofit build(){
           if(baseUrl == null){
                throw new IllegalStateException("Base URL required.");
           }
           return new MyRetrofit(baseUrl);
       }
   }

}

5.具體實(shí)現(xiàn)網(wǎng)絡(luò)請求類
定義接口方法類

public interface MyRetrofitLoginService {
@Post("user/login?platform=android&city_id=101&type=pwd&channel=baiduxi&version=3.2.0&os_version=6.0.1&device_id=866622020797175")
    MyCall login(@Field("mobile") String name, @Field("password") String pwd);
}

簡單封裝請求工具類

public class MyRetrofitTest {
    private static String URL_SERVER = "http://api.cloud.test.haocaisong.cn/v2.0/";
    public static void login(String name, String pwd, final SimpleSystemLogin.OnHttpResultListener onHttpResultListener) {
        MyRetrofit myRetrofit = new MyRetrofit.Builder().baseUrl(URL_SERVER).build();
        MyRetrofitLoginService loginService = myRetrofit.create(MyRetrofitLoginService.class);
        MyCall myCall = loginService.login(name,pwd);
        myCall.enqueue(new MyCallback() {
            @Override
            public void onResponse(String response) {
                onHttpResultListener.onHttpResult(response);
            }

            @Override
            public void onFailure(Exception e) {

            }
        });
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容