android 网络框架-Retrofit(三)
16lz
2022-07-30
简单实现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和CallbackMyCall .classpublic 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) { } }); }}
更多相关文章
- 浅谈Java中Collections.sort对List排序的两种方法
- mybatisplus的坑 insert标签insert into select无参数问题的解决
- Python技巧匿名函数、回调函数和高阶函数
- Python list sort方法的具体使用
- python list.sort()根据多个关键字排序的方法实现
- android上一些方法的区别和用法的注意事项
- android实现字体闪烁动画的方法
- Android中dispatchDraw分析
- Android四大基本组件介绍与生命周期