网络框架 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;}@Overridepublic String execute() throws Exception {if (serviceMethod.isPost()) {return HttpUtils.post(serviceMethod.baseUrl(), serviceMethod.getParam());} else {return HttpUtils.get(serviceMethod.baseUrl());}}@Overridepublic 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;}@Overrideprotected String doInBackground(Void... params) {try {return httpCall.execute();} catch (Exception e) {e.printStackTrace();}return null;}@Overrideprotected 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() {@Overridepublic 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() {@Overridepublic void onResponse(String response) {onHttpResultListener.onHttpResult(response);}@Overridepublic void onFailure(Exception e) {}});}
}
复制代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/539612.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Tomcat提示“XDB 的服务器 localhost 要求用户名和密码”

在地址栏输入http://localhost:8080/&#xff08;8080是TOMCAT的端口号)测试&#xff0c;系统提示“XDB 的服务器 localhost 要求用户名和密码”&#xff0c;并弹出输入用户、密码的窗口&#xff0c;查看代码没问题&#xff0c;不解&#xff0c;上网上查资料&#xff0c;是因为…

java jqgrid json格式_jqGrid 数据之 Json

Json数据需要定义jsonReader来跟服务器端返回的数据做对应&#xff0c;其默认值&#xff1a; jsonReader : { root: "rows", page: "page", total: "total", records: "records", repeatitems: true, c…

django 中静态文件项目加载问题

问题描述&#xff1a; django项目中创建了多个app后&#xff0c;每个app中都有对应的static静态文件。整个项目运行时这些静态文件的加载就是一个问题&#xff0c;因为整个项目我只参与了一部分&#xff0c;项目部署之类的并没有参与。我写的部分的js代码遇到点问题&#xff0c…

Erlang/OTP设计原则(文档翻译)

http://erlang.org/doc/design_principles/des_princ.html 图和代码皆源自以上链接中Erlang官方文档&#xff0c;翻译时的版本为20.1。 这个设计原则&#xff0c;其实是说用户在设计系统的时候应遵循的标准和规范。阅读前我一直以为写的是作者在设计 Erlang/OTP 框架时的一些原…

存储过程的参数可以使用sql的函数

系统已做成存储过程&#xff0c;调用方法如下&#xff1a; crh_entry(yyyymmdd,起始时间,结束时间); 示例1&#xff1a;进行2016年4月10日10时到12时的测试&#xff0c;应写为&#xff1a; exec crh_entry(20160410,10,11); 示例2&#xff1a;进行2016年4月8日14时到15时的…

java如何实例化集合_如何在java中实例化一个Queue对象?

Queue是一个接口&#xff0c;这意味着你不能直接构造一个Queue 。最好的select是构造一个已经实现Queue接口的类&#xff0c;如下所示&#xff1a; AbstractQueue &#xff0c; ArrayBlockingQueue &#xff0c; ConcurrentLinkedQueue &#xff0c; DelayQueue &#xff0c; D…

leetcode 121 股票买卖问题系列

描述&#xff1a; 给一些列数字&#xff0c;表示每条股票的价格&#xff0c;如果可以买卖一次&#xff08;不能同一天买和卖&#xff09;&#xff0c;求最大利益&#xff08;即差最大&#xff09;。 其他三道问题是&#xff0c;如果能买卖无限次&#xff0c;买卖两次&#xff0…

Mybatis-jar-lib

csdn的下载好像和我有仇&#xff0c;上传资源不断提示&#xff1a;请您先登录 下载&#xff1a;http://pan.baidu.com/s/1pL2BAzT asm-3.3.1.jar cglib-2.2.2.jar commons-logging-1.1.1.jar mybatis-3.1.1.jar ----以上mybatis的--- log4j-1.2.16.jar ----以上log4j日志--…

java使用队列实现栈思路_算法面试:队列实现栈的方案

声明&#xff1a;码字不易&#xff0c;转载请注明出处&#xff0c;欢迎文章下方讨论交流。前言&#xff1a;Java数据结构与算法专题会不定时更新&#xff0c;欢迎各位读者监督。本篇介绍的是如何用两个队列实现栈的问题。这道题作为上一篇文章算法面试&#xff1a;栈实现队列的…

Uber如何使用go语言创建高效的查询服务

在2015年初我们创建了一个微服务&#xff0c;它只做一件事&#xff08;也确实做得很好&#xff09;就是地理围栏查询。一年后它成了Uber高频查询&#xff08;QPS&#xff09;服务&#xff0c;本次要讲的故事就是我们为什么创建这个服务&#xff0c;以及编程语言新秀Go如何帮我们…

centos7:塔建pure_ftpd虚拟用户

2019独角兽企业重金招聘Python工程师标准>>> 1.下载pure_ftpd&#xff0c;上传服务器,目录路径:/usr/local/src/ 下载地址:https://pan.baidu.com/s/1kWe8FAn 2.安装pure_ftpd cd /usr/local/srctar -xjf pure-ftpd-1.0.36.tar.bz2cd pure-ftpd-1.0.36./configure -…

java.lang.module_如何修复“java.lang.module.FindException:module java.se.ee not found”错误

我正在尝试打包我的kivy应用程序(python3)&#xff0c;但是当我运行命令buildozer -v android debug时&#xff0c;看到这个错误# Cwd /home/javier/.buildozer/android/platform/android-sdkError occurred during initialization of boot layerjava.lang.module.FindExceptio…

寒武纪芯片——有自己的SDK,支持tf、caffe、MXNet

寒武纪芯片产品中心>智能处理器IP智能处理器IP MLU智能芯片 软件开发环境 Cambricon-1A 高性能硬件架构及软件支持兼容Caffe、Tensorflow、MXnet等主流AI开发平台&#xff0c;已多次成功流片 国际上首个成功商用的深度学习处理器IP产品&#xff0c;可广泛应用于计算机视觉、…

maven ssm框架 mysql_SSM框架(IDEA+Spring+SpringMVC+Maven+Mybatis+MySQL)

【实例简介】SSM框架(IDEASpringSpringMVCMavenMybatisMySQL),搭建SSM框架&#xff0c;利用mybatis-plus插件自动生成数据库相关代码。【实例截图】【核心代码】0d399d99-f108-4aaa-9c81-35b505c86e8a└── SSMManager├── pom.xml├── sql│ └── test.sql└── src…

spring框架的引入

spring框架给程序开发带来了春天&#xff0c;在很多项目里&#xff0c;可能不用struts&#xff0c;不用hibernate&#xff0c;但往往都有spring。 why&#xff1f; 因为每个项目都会涉及到对象的创建和对象之间的依赖。 一、传统的MVC开发 mvc的项目框架结构&#xff1a;Enti…

Java编程作业体会_Java作业的几点总结感想

本次博客主要是总结近几次作业&#xff0c;交流一下自己的感受。本次作业主要是对近几次Java课程的巩固作业&#xff0c;第一次作业主要是一些基础的题目&#xff0c;包括选择循环等一些基本语句&#xff0c;其目的在于掌握java一些基本知识&#xff0c;感受出Java与其他语言有…

基于百度语音识别API的Python语音识别小程序

一、功能概述 实现语音为文字&#xff0c;可以扩展到多种场景进行工作&#xff0c;这里只实现其基本的语言接收及转换功能。 在语言录入时&#xff0c;根据语言内容的多少与停顿时间&#xff0c;自动截取音频进行转换。 工作示例&#xff1a; 二、软件环境 操作系统&#xff1a…

spring专业术语了解

组件/框架设计 侵入式设计 引入了框架&#xff0c;对现有的类的结构有影响&#xff1b;即需要实现或继承某些特定类。 例如&#xff1a;Struts框架 非侵入式设计 引入了框架&#xff0c;对现有的类结构没有影响。 例如&#xff1a;Hibernate框架 / Spring框架 控制反转: In…

java修改ldap用户密码_LDAP 用户更改自己的密码

LDAP中采用了ACL的权限控制。在/etc/openldap/slapd.conf文件中&#xff1a;## See slapd.conf(5) for details on configuration options.# This file should NOT be world readable.#include/etc/openldap/schema/corba.schemainclude/etc/openldap/schema/core.schemainclud…

Spring第三篇【Core模块之对象依赖】

tags: Spring 前言 在Spring的第二篇中主要讲解了Spring Core模块的使用IOC容器创建对象的问题&#xff0c;Spring Core模块主要是解决对象的创建和对象之间的依赖关系&#xff0c;因此本博文主要讲解如何使用IOC容器来解决对象之间的依赖关系&#xff01; 回顾以前对象依赖 我…