网络框架-Retrofit(三)

简单实现Retrofit(替代Okhttp)

1.定义注解参数

@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.实现回调接口Call和Callback
MyCall .class

public interface MyCall {

     //执行网络请求(同步:在当前网络)
     String execute() throws Exception;

    //在子线程请求网络
    void enqueue(MyCallback callback);
}

MyCallback .class

/**
 * 网络请求回调接口
 */
public interface MyCallback {
  void onResponse( String response);

  void onFailure( Exception e);
}

SystemHttpCall .class

/**
 * Created by Xionghu on 2017/8/14.
 * Desc: 具体的实现类发送请求
 */

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("网络异常!"));
                }
            }


        }
    }
}

3.解析注解方法获取相应参数

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请求,需要拼接参数地址
            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;
        // 参数集合
        Map<String, Object> paramMap;
        Object[] args;

        boolean isPost;

        public Builder(MyRetrofit retrofit, Method method, Object[] args) {
            this.retrofit = retrofit;
            this.method = method;
            // 方法注解列表(相当于我们的LoginService中的: @POST和@FormUrlEncoded......)
            this.methodAnnotations = method.getAnnotations();
            // 方法参数注解列表(相当于我们的LoginService中的: @Field......)
            this.parameterAnnotationsArray = method.getParameterAnnotations();
            this.args = args;

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

        public MyServiceMethod build() {
            // 循环遍历方法注解列表
            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;
            }
        }

        /**
         * 解析参数注解
         *
         * @param p
         * @param parameterAnnotations
         */
        private void parseParameterAnnotation(int p,
                                              Annotation[] parameterAnnotations) {
            // 方法参数值
            Object value = args[p];
            // 遍历方法参数注解
            for (Annotation annotation : parameterAnnotations) {
                // 首先需要判断该注解的类型
                if (annotation instanceof Field) {
                    Field field = (Field) annotation;
                    // 参数的名称(接口参数名称,服务器接口规定的)
                    String key = field.value();
                    paramMap.put(key, value);
                }
            }
        }

    }
}

4.定义MyRetrofit框架

public class MyRetrofit {
    // 缓存方法(为了避免重复加载方法注解,从而耗费性能)
    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){
       //动态代理实现
       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;
           }
       });

   }
    // 第一步:解析方法(说白了解析方法注解和方法参数注解)

    // 第二步:实现网络请求

    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.具体实现网络请求类
定义接口方法类

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) {

            }
        });
    }
}
    原文作者:香沙小熊
    原文地址: https://www.jianshu.com/p/67a07f898cf5
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞