简单实现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) {
}
});
}
}