一.基本用法
1.创建Retrofit对象
public class HttpRetrofit {
private static Retrofit mRetrofit;
public static Retrofit getService(){
if (mRetrofit == null) {
synchronized (HttpRetrofit.class) {
if (mRetrofit == null) {
mRetrofit = new Retrofit.Builder()
.baseUrl(ApiUrl.BASE_URL)
.client(WBHttpClient.getHttpClient())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
}
}
return mRetrofit;
}
}
2.retrofit各种网络请求的用法
/************************************GET网络请求方式******************************************************/
//作用:GET请求最简单的写法,无Path参数和Query参数 */
// @GET("article/list/latest?page=1") Call<ResponseBody> getLatestString();
//作用:GET请求,指定Path参数和Query参数
//@GET("article/list/{type}?") Call<QiushiModel> getInfoList(@Path("type") String type, @Query("page") int page);
//作用:GET请求提交数据
// @GET("MyWeb/RegServlet") Call<ResponseBody> getRegInfo(@QueryMap Map<String, String> map);
//作用:GET请求,指定URL参数
//@GET Call<QiushiModel> getInfoList(@Url String urlString);
//访问网络,下载大文件。 * 默认情况下,Retrofit在处理结果前会将服务器端的Response全部读进内存
//@Streaming @GET Call<ResponseBody> getNetworkDataAsync(@Url String urlString);
/************************************POST网络请求方式******************************************************/
//作用:post网络请求,向服务器提交表单域数据
//@FormUrlEncoded @POST("MyWeb/RegServlet") Call<ResponseBody> postFormFields(@Field("username") String username, @Field("password") String password, @Field("age") String age);
// @FormUrlEncoded @POST("MyWeb/RegServlet") Call<ResponseBody> postFormFieldMap(@FieldMap Map<String , String> map);
//作用:POST网络请求,上传单个文件,上传后的文件名称已经被指定
//@Multipart @POST("MyWeb/UploadServlet") Call<ResponseBody> postUploadFile(@Part("uploadfile\";filename=\"myuploadimg.png") RequestBody requestBody);
//作用:POST网络请求,上传多个文件,同时上传表单域数据
// @POST("MyWeb/UPloadServlet") Call<ResponseBody> postUploadFilesMultipartBody(@Body MultipartBody multipartBody);}
//和Rxjava一起连用
@GET(ApiUrl.GET_MARKET)
Observable<BaseResult<List<MarketBean>>> getMarket(@QueryMap Map<String ,Object> map);
mRetrofit.create(WebService.class).getMarket(map).
subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).
subscribe(new ObserverCallBack<BaseResult<List<MarketBean>>>(new ApiCallBack<BaseResult<List<MarketBean>>>() {
@Override
public void onSuccess(BaseResult<List<MarketBean>> baseResult) {
}
@Override
public void onFailture(Throwable e,int errorCode) {
}
}));
3.动态代理示例【www.cnblogs.com/gonjan-blog…
动态代理(代理类在运行前不存在,运行时由程序生成的代理方式叫动态代理) 实现方式:创建一个实现了InvocationHandler 接口的类,然后实现其invoke方法,然后使用Proxy.newProxyInstance()方法创建代理对象,通过代理对象,调用接口中的方法,实际上是调用的InvocationHandler 中的invoke方法
/**
* 创建Person接口
* @author Gonjan
*/
public interface Person {
//上交班费
void giveMoney();
}
public class Student implements Person {
private String name;
public Student(String name) {
this.name = name;
}
@Override
public void giveMoney() {
try {
//假设数钱花了一秒时间
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + "上交班费50元");
}
}
public class StuInvocationHandler<T> implements InvocationHandler {
//invocationHandler持有的被代理对象
T target;
public StuInvocationHandler(T target) {
this.target = target;
}
/**
* proxy:代表动态代理对象
* method:代表正在执行的方法
* args:代表调用目标方法时传入的实参
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理执行" +method.getName() + "方法");
*/
//代理过程中插入监测方法,计算该方法耗时
MonitorUtil.start();
Object result = method.invoke(target, args);
MonitorUtil.finish(method.getName());
return result;
}
}
测试代理类:
public class ProxyTest {
public static void main(String[] args) {
//创建一个实例对象,这个对象是被代理的对象
Person zhangsan = new Student("张三");
//创建一个与代理对象相关联的InvocationHandler
InvocationHandler stuHandler = new StuInvocationHandler<Person>(zhangsan);
//创建一个代理对象stuProxy来代理zhangsan,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
Person stuProxy = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, stuHandler);
//代理执行上交班费的方法
stuProxy.giveMoney();
}
}
打印结果:
二.原理解析
(1)通过构造者模式创建一个retrofit实例,配置baseUrl,OkHttpClient,CallAdapterFactory(Rxjava2CallAdapterFactory将代理返回的call对象转化为Observable对象), ConvertFactory(GsonConvertFactory将代理返回的请求的结果转化为javabean)
(2).通过retrofit对象的create(Class service)返回一个Service的动态代理对象,在调用Service的方法的时候,就是动态调用invoke方法,在Invoke方法中,调用loadServiceMethod(method),在这个方法中会通过给method进行反射,解析注解,得到参数,请求头,请求地址,等等,构建Request请求所有需要的参数等,并提供toRequest()方法得到Request实例,然后构建OkHttpCall(servicMethod,args),通过 serviceMethod.callAdapter.adat(okHttpCall),返回一个Observable或者是Call。
如果是Call<T> call;
call.enqueue( Callback<T> callback){
Request request = serviceMethod.toRequest(args);
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
}
如果是Observable<T> ,会调用subcribe添加观察者,实际会调用subscribeActual(),在此方法中
observable.subcribe(new Observer(){}) //添加观察者
//Observable接口中的订阅方法
public final void subscribe(Observer<? super T> observer) {
ObjectHelper.requireNonNull(observer, "observer is null");
try {
observer = RxJavaPlugins.onSubscribe(this, observer);
ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");
subscribeActual(observer); //调用该方法
} catch (NullPointerException e) { // NOPMD
throw e;
} catch (Throwable e) {
}
}
//CallEnqueueObservable中
protected void subscribeActual(Observer<? super Response<T>> observer) {
// Since Call is a one-shot type, clone it for each new observer.
Call<T> call = originalCall.clone();
CallCallback<T> callback = new CallCallback<>(call, observer);
observer.onSubscribe(callback);
call.enqueue(callback);//执行OKHttpCall中的enqueue方法
}
(3).create()方法源码
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
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);
/* adapt方法中根据addCallAdapterFactory类型,如果是RxJava2CallAdapterFactory就返回
Observable<T>, 如果不传,则返回Call<T> */
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
//Retrofit中构造模式创建一个ServiceMethod对象
ServiceMethod<?, ?> loadServiceMethod(Method method) {
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
// this表示Retrofit,retrofit里面持有baseUrl,okHttpClient,convertFactory,callAdapterFactory
//method通过反射,解析注解,得到参数,header,isMulpart,isbody,isFormUrlEncode等构建Request的
//必要参数,并提供toRequest()返回Reqeust对象.
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
public ServiceMethod build() {
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError("'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation); //
}
if (httpMethod == null) {
throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
if (!hasBody) {
if (isMultipart) {
throw methodError(
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
+ "request body (e.g., @POST).");
}
}
int parameterCount = parameterAnnotationsArray.length;
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);
}
if (relativeUrl == null && !gotUrl) {
throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError("Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError("Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError("Multipart method must contain at least one @Part.");
}
return new ServiceMethod<>(this);
}
/*解析注解得到构建RequestBuilder的核心参数httpMethod,baseUrl,relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart */
private void parseMethodAnnotation(Annotation annotation) {
if (annotation instanceof DELETE) {
parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
} else if (annotation instanceof GET) {
parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
} else if (annotation instanceof HEAD) {
parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
if (!Void.class.equals(responseType)) {
throw methodError("HEAD method must use Void as response type.");
}
} else if (annotation instanceof PATCH) {
parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
} else if (annotation instanceof POST) {
parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
} else if (annotation instanceof PUT) {
parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
} else if (annotation instanceof OPTIONS) {
parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
} else if (annotation instanceof HTTP) {
HTTP http = (HTTP) annotation;
parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
} else if (annotation instanceof retrofit2.http.Headers) {
String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
if (headersToParse.length == 0) {
throw methodError("@Headers annotation is empty.");
}
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
if (isFormEncoded) {
throw methodError("Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError("Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}
(4).ServiceMethod中提供toRequest()生成Request.
Request toRequest(@Nullable Object... args) throws IOException {
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart);
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args != null ? args.length : 0;
if (argumentCount != handlers.length) {
throw new IllegalArgumentException("Argument count (" + argumentCount
+ ") doesn't match expected count (" + handlers.length + ")");
}
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, args[p]);
}
return requestBuilder.build();
}
(5).当我们获取到一个Observable,是如何触发OkHttpCall执行的呢?
//Observable接口中的订阅方法
public final void subscribe(Observer<? super T> observer) {
ObjectHelper.requireNonNull(observer, "observer is null");
try {
observer = RxJavaPlugins.onSubscribe(this, observer);
ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");
subscribeActual(observer); //调用该方法
} catch (NullPointerException e) { // NOPMD
throw e;
} catch (Throwable e) {
}
}
//CallEnqueueObservable中
protected void subscribeActual(Observer<? super Response<T>> observer) {
// Since Call is a one-shot type, clone it for each new observer.
Call<T> call = originalCall.clone();
CallCallback<T> callback = new CallCallback<>(call, observer);
observer.onSubscribe(callback);
call.enqueue(callback);//执行OKHttpCall中的enqueue方法
}
public void enqueue(final Callback<T> callback) {
okhttp3.Call call;
Request request = serviceMethod.toRequest(args);
//执行Request请求.
okhttp3.Call call = serviceMethod.callFactory.newCall(request); //callFactory就是OkHttpClient实例
}