retrofit基本使用和源码设计模式分析
基本使用
GitHub网址:https://github.com/square/retrofit
添加依赖:
compile ‘com.squareup.retrofit2:retrofit:2.3.0’ compile ‘com.squareup.retrofit2:converter-gson:+’ compile ‘com.squareup.okhttp3:logging-interceptor:+’
ServiceApi接口
public interface ServiceApi { @GET("is_login")//Query代表你要查询的字段名字 Call<UserLoginResult> userlogin(@Query("username") String userName,@Query("password")String password); }
RetrofitClient进行封装
public class RetrofitClient { private static final ServiceApi mServiceApi; static { OkHttpClient okHttpClient = new OkHttpClient(); Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://app.ahhuabang.com:8088/server/index.php/user/") // 添加解析转换工厂,Gson 解析,Xml解析,等等 .addConverterFactory(GsonConverterFactory.create()) //不设置默认的是okHttp .client(okHttpClient) .build(); mServiceApi = retrofit.create(ServiceApi.class); } public static ServiceApi getServiceApi() { return mServiceApi; } }
UserLoginResult:返回的结果
public class UserLoginResult { private String msg; private String token; @Override public String toString() { return "UserInfo{" + "msg='" + msg + '\'' + ", token='" + token + '\'' + '}'; } }
测试
final Call<UserLoginResult> userlogin = RetrofitClient.getServiceApi().userlogin("测试专用", "HB654321"); userlogin.enqueue(new Callback<UserLoginResult>() { @Override public void onResponse (Call < UserLoginResult > call, Response < UserLoginResult > response) { Log.e("TAG", response + ""); UserLoginResult userLoginResult = response.body(); Log.e("TAG", userLoginResult.toString()); } @Override public void onFailure (Call < UserLoginResult > call, Throwable t){ t.printStackTrace(); } });
常见问题1:没有打印,想知道Url等参数,这时候可以通过okhttp添加拦截器
OkHttpClient okHttpClient = new OkHttpClient.Builder(). addInterceptor(new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() { @Override public void log(String message) { //默认是Log.d修改成Log.e Log.e("Retorfit", message); } }).setLevel(HttpLoggingInterceptor.Level.BODY)).build();
2. 数据格式不一致,我们这里成功 没有data,但是有时候我们返回的是有data,而data成功的时候可能是个对象,但是失败的时候返回的是String类型
userInfo
public class UserInfo { private String msg; private String token; @Override public String toString() { return "UserInfo{" + "msg='" + msg + '\'' + ", token='" + token + '\'' + '}'; } }
BaseResult
public class BaseResult { private String msg; private String code; public String getMsg() { return msg; } public String getCode() { return code; } public boolean isOk() { return "0".equals(code); } }
Result
public class Result<T> extends BaseResult{ public Object data; }
修改ServiceApi
public interface ServiceApi { @GET("is_login") //Query代表你要查询的字段名字 Call<Result<UserInfo>> userlogin(@Query("username") String userName, @Query("password") String password); }
HttpCallback封装
public abstract class HttpCallback<T> implements Callback<Result<T>> { @Override public void onResponse(Call<Result<T>> call, Response<Result<T>> response) { Result<T> result = response.body(); if (!result.isOk()) { onError(result.getCode(), result.getMsg()); return; } //解析上面泛型的类 Class<T> dataClass = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()) .getActualTypeArguments()[0]; Gson gson = new Gson(); if (result.data != null) { T data = gson.fromJson(result.data.toString(), dataClass); onSucceed(data); } } @Override public void onFailure(Call<Result<T>> call, Throwable t) { } public abstract void onSucceed(T result); public abstract void onError(String code, String msg); }
测试
Call<Result<UserInfo>> userlogin = RetrofitClient.getServiceApi().userlogin("测试专用", "HB654321"); userlogin.enqueue(new HttpCallback<UserInfo>() { @Override public void onSucceed(UserInfo result) { Log.e("TAG", result.toString()); } @Override public void onError(String code, String msg) { } });
源码设计模式分析
Builder 设计模式
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://app.ahhuabang.com:8088/server/index.php/user/") .addConverterFactory(GsonConverterFactory.create()) .client(okHttpClient) .build();
retrofit.create(ServiceApi.class)动态代理设计模式
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() { private final Platform platform = Platform.get(); @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable { // If the method is a method from Object then defer to normal invocation. if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } if (platform.isDefaultMethod(method)) { return platform.invokeDefaultMethod(method, service, proxy, args); } ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method); OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); //适配器模式 return serviceMethod.adapt(okHttpCall); } });
用作解耦,体现的形式有很多,插件化绕过 AndroidManifest.xml 主要是用作 Hook 拦截方法,MVP 主要用作 AOP 切面,总之采用的原理其实还是方法的拦截
工厂方法模式:简单工厂模式,抽象工厂模式,方法工厂模式
方法工厂模式
public static GsonConverterFactory create(Gson gson) { if (gson == null) throw new NullPointerException("gson == null"); return new GsonConverterFactory(gson); }
抽象方法工厂模式
GsonConverterFactory extends Converter.Factory
简单工厂设计模式
private static Platform findPlatform() { try { Class.forName("android.os.Build"); if (Build.VERSION.SDK_INT != 0) { return new Android(); } } catch (ClassNotFoundException ignored) { } try { Class.forName("java.util.Optional"); return new Java8(); } catch (ClassNotFoundException ignored) { } return new Platform(); }
adapter设计模式
serviceMethod.adapt(okHttpCall)
如果不采用rxjava直接返回okhttpCall对象,而采用rxjava返回的应该是Observable对象,这里作用就是将Call对象转换成Observable对象
模板设计模式ParameterHandler
abstract void apply(RequestBuilder builder, @Nullable T value) throws IOException; static final class RelativeUrl extends ParameterHandler<Object> { @Override void apply(RequestBuilder builder, @Nullable Object value) { checkNotNull(value, "@Url parameter is null."); builder.setRelativeUrl(value); } }
parameterHandlers = new ParameterHandler<?>[parameterCount]; for (int p = 0; p < parameterCount; p++) { Type parameterType = parameterTypes[p]; if (Utils.hasUnresolvableType(parameterType)) { throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s", parameterType); } Annotation[] parameterAnnotations = parameterAnnotationsArray[p]; if (parameterAnnotations == null) { throw parameterError(p, "No Retrofit annotation found."); } parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
private ParameterHandler<?> parseParameterAnnotation(){ if (type == HttpUrl.class || type == String.class || type == URI.class || (type instanceof Class && "android.net.Uri".equals(((Class<?>) type).getName()))) { return new ParameterHandler.RelativeUrl(); } return new ParameterHandler.Path<>(name, converter, path.encoded());return new ParameterHandler.Query<>(name, converter, encoded).array(); }
制定通用的流程,具体的算法细节由不同的子类去实现,确定Retrofit请求流程 ,解析方法参数注解,但是其具体的各个参数细节由子类去实现
还可以衍生另一种设计模式叫做策略,不同的参数注解采用不同的添加策略
ServiceMethod<?, ?> loadServiceMethod(Method method) { ServiceMethod<?, ?> result = serviceMethodCache.get(method); if (result != null) return result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null) { result = new ServiceMethod.Builder<>(this, method).build(); serviceMethodCache.put(method, result); } } return result; }
原型设计模式
public interface Call<T> extends Cloneable { }
单例,观察者(也可以说是回调)
发布评论
热门评论区: