/ retrofit  设计模式  okhttp 

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

单例,观察者(也可以说是回调)

发布评论

热门评论区: