一.简介
Retrofit是是Square公司开发的一款针对Android网络请求的框架,Retrofit2底层基于OkHttp实现的,OkHttp现在已经得到Google官方认可,大量的app都采用OkHttp做网络请求,其源码详见OkHttp Github。
二.贴代码
1.首先在gradle中添加如下配置
compile 'com.google.code.gson:gson:2.6.2'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
compile 'io.reactivex:rxjava:1.1.0'
compile 'io.reactivex:rxandroid:1.1.0'
这样就将Retrofit+RxJava引入进来了
2.在manifest中添加网络权限
<uses-permission android:name="android.permission.INTERNET" />
3.写个接口FactoryInters,用来封装get post方法
①这是get方法,一会在RetrofitBase中调用
@GET
Observable<JSONObject> getData(
@Url String url,
@QueryMap Map<String, Object> params);
②这是post方法,一会在RetrofitBase中调用
@FormUrlEncoded
@POST
Observable<JSONObject> postData(
@Url String url,
@FieldMap Map<String, Object> params);
③这是上传文件的方法
有两种写法:使用@MultiPart注解,@Part注解文件入参,则文件入参类型应是List< okhttp3.MultipartBody.Part>;
不使用@Multipart注解,直接使用@Body注解文件入参,则文件入参类型应是okhttp3.MultipartBody
@Multipart
@POST
Observable<JSONObject> uploadFiles(
@Url String url,
@PartMap() Map<String, RequestBody> strParams,
@Part() List<MultipartBody.Part> fileParams);
4.新建类RetrofitBase,用来具体实现get post方法
全局参数:
private static final String TAG = RetrofitBase.class.getSimpleName();
protected static String BASEURL = Config.SERVER_ADDRESS;
private static final long TIMEOUT = 5 * 1000;
private FactoryInters service;
private Retrofit retrofit;
private Gson gson;
private JsonParser jsonParser;
初始化
private RetrofitBase() {
retrofit = new Retrofit.Builder()
.baseUrl(BASEURL)
.client(client())
//增加返回值为Gson的支持(自定义MyGsonConverterFactory)
.addConverterFactory(MyGsonConverterFactory.create())
//增加返回值为Oservable<T>的支持
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
service = retrofit.create(FactoryInters.class);
gson = new GsonBuilder().setPrettyPrinting().create();
jsonParser = new JsonParser();
}
private static class SingletonHolder {
private static final RetrofitBase INSTENCE = new RetrofitBase();
}
public static RetrofitBase getInstance() {
return SingletonHolder.INSTENCE;
}
获得连接
private OkHttpClient client() {
LauncherTrust launcherTrust = new LauncherTrust();
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.readTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.sslSocketFactory(sslSocketFactory(launcherTrust), launcherTrust)
.hostnameVerifier(new AllowAllHostnameVerifier())
.addInterceptor(interceptor)
.retryOnConnectionFailure(false)//失败重连
.build();
return okHttpClient;
}
private SSLSocketFactory sslSocketFactory(LauncherTrust launcherTrust) {
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{launcherTrust}, new SecureRandom());
return sslContext.getSocketFactory();
} catch (NoSuchAlgorithmException | KeyManagementException e) {
e.printStackTrace();
}
return null;
}
static class LauncherTrust implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
LogInterceptor interceptor = new LogInterceptor(new LogInterceptor.Logger() {
@Override
public void log(String message) {
Log.i(TAG, message);
}
});
重点!!!
get方法
public void getData(String url, Map<String, Object> params, SubListenerHelper listener) {
Log.d(TAG, "[get请求参数] = \n" + gson.toJson(jsonParser.parse(gson.toJson(params))));
service.getData(url, params)
.compose(schedulersTransformer())
.subscribe(listener);
}
post方法
public void postData(String url, Map<String, Object> params, SubListenerHelper listener) {
Log.d(TAG, "[post请求参数] = \n" + gson.toJson(jsonParser.parse(gson.toJson(params))));
service.postData(url, params)
.compose(schedulersTransformer())
.subscribe(listener);
}
上传文件
public void uploadFiles(String url, Map<String, RequestBody> strParams, List<MultipartBody.Part> fileParams, SubListenerHelper subscriberHelper) {
service.uploadFiles(url, strParams, fileParams)
.compose(schedulersTransformer())
.subscribe(subscriberHelper);
}
Observable
Observable.Transformer schedulersTransformer() {
return new Observable.Transformer() {
@Override
public Object call(Object observable) {
return ((Observable) observable)
.subscribeOn(Schedulers.io())//执行在io线程
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());//主线程显示
}
};
}
上传文件时将map转成List
public static List<MultipartBody.Part> fileList2PartList(Map<String, File> fileMap) {
List<MultipartBody.Part> partList = new ArrayList<>(fileMap.size());
for (Map.Entry<String, File> entry : fileMap.entrySet()) {
String fileKey = entry.getKey();
File file = entry.getValue();
RequestBody requestBody = RequestBody.create(MediaType.parse("image/jpg"), file);
MultipartBody.Part part = MultipartBody.Part.createFormData(fileKey, file.getName(), requestBody);
partList.add(part);
}
return partList;
}
4.LogInterceptor类
public class LogInterceptor implements Interceptor {
private static final Charset UTF8 = Charset.forName("UTF-8");
public enum Level {
NONE,
BASIC,
HEADERS,
BODY
}
public interface Logger {
void log(String message);
int INFO = 800;
Logger DEFAULT = new Logger() {
@Override
public void log(String message) {
Platform.get().log(INFO, message, null);
}
};
}
public LogInterceptor() {
this(Logger.DEFAULT);
}
public LogInterceptor(Logger logger) {
this.logger = logger;
}
private final Logger logger;
private volatile Level level = Level.BODY;
/**
* Change the level at which this interceptor logs.
*/
public LogInterceptor setLevel(Level level) {
if (level == null) throw new NullPointerException("level == null. Use Level.NONE instead.");
this.level = level;
return this;
}
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Level level = this.level;
Request request = chain.request();
if (level == Level.NONE) {
return chain.proceed(request);
}
boolean logBody = level == Level.BODY;
boolean logHeaders = logBody || level == Level.HEADERS;
RequestBody requestBody = request.body();
boolean hasRequestBody = requestBody != null;
String requestStartMessage = request.method() + ' ' + request.url();
if (!logHeaders && hasRequestBody) {
requestStartMessage += " (" + requestBody.contentLength() + "-byte body)";
}
logger.log(requestStartMessage);
if (logHeaders) {
if (!logBody || !hasRequestBody) {
logger.log("--> END " + request.method());
} else if (bodyEncoded(request.headers())) {
logger.log("--> END " + request.method() + " (encoded body omitted)");
} else if (request.body() instanceof MultipartBody) {
//如果是MultipartBody,会log出一大推乱码的东东
} else {
Buffer buffer = new Buffer();
requestBody.writeTo(buffer);
Charset charset = UTF8;
MediaType contentType = requestBody.contentType();
if (contentType != null) {
contentType.charset(UTF8);
}
logger.log(buffer.readString(charset));
// logger.log(request.method() + " (" + requestBody.contentLength() + "-byte body)");
}
}
long startNs = System.nanoTime();
Response response = chain.proceed(request);
long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);
logger.log(response.code() + ' ' + response.message() + " (" + tookMs + "ms" + ')');
return response;
}
private boolean bodyEncoded(Headers headers) {
String contentEncoding = headers.get("Content-Encoding");
return contentEncoding != null && !contentEncoding.equalsIgnoreCase("identity");
}
private static String protocol(Protocol protocol) {
return protocol == Protocol.HTTP_1_0 ? "HTTP/1.0" : "HTTP/1.1";
}
}
5.MyGsonConverterFactory类
public class MyGsonConverterFactory extends Converter.Factory {
private static final String TAG = MyGsonConverterFactory.class.getSimpleName();
private final Gson gson;
public static MyGsonConverterFactory create() {
return create(new Gson());
}
public static MyGsonConverterFactory create(Gson gson) {
return new MyGsonConverterFactory(gson);
}
private MyGsonConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
this.gson = gson;
}
/**
* 响应
*
* @param type
* @param annotations
* @param retrofit
* @return
*/
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
Log.i(TAG, "responseBodyConverter");
return new JsonResponseBodyConverter(gson, adapter);
}
/**
* 请求
*
* @param type
* @param parameterAnnotations
* @param methodAnnotations
* @param retrofit
* @return
*/
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
Log.i(TAG, "requestBodyConverter");
return new JsonRequestBodyConverter<>(gson, adapter); //请求
}
}
6.自定义请求类:JsonRequestBodyConverter
public class JsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
private static final String TAG = JsonRequestBodyConverter.class.getSimpleName();
private Gson gson;
private TypeAdapter<T> adapter;
public JsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override
public RequestBody convert(T value) throws IOException {
Log.i(TAG, "convert(T value)");
String result = URLEncoder.encode(EncryptUtil.encryptByPublicKey(value.toString()), "utf-8");
String postBody = gson.toJson(result); //对象转化成json
Log.i(TAG, "转化后的数据:" + postBody);
return RequestBody.create(MEDIA_TYPE, postBody);
}
}
7.自定义响应类:JsonResponseBodyConverter
public class JsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private static final String TAG = JsonResponseBodyConverter.class.getSimpleName();
private final Gson mGson;//gson对象
private final TypeAdapter<JSONObject> adapter;
public JsonResponseBodyConverter(Gson gson, TypeAdapter<JSONObject> adapter) {
this.mGson = gson;
this.adapter = adapter;
}
@Override
public T convert(ResponseBody responseBody) throws IOException {
Log.i(TAG, "ResponseBody");
String responseString = responseBody.string();
String result = EncryptUtil.decryptByPublicKey(responseString);//解密
Log.i(TAG, "解密的服务器数据:" + result);
JSONObject data = null;
try {
data = new JSONObject(result);
} catch (JSONException e) {
Log.i(TAG, "e:" + e);
e.printStackTrace();
}
return (T) data;
}
}
8.封装的解析类SubListenerHelper
public abstract class SubListenerHelper extends Subscriber<JSONObject> {
private static final String TAG = SubListenerHelper.class.getSimpleName();
private boolean toastInfo = false;
public abstract void onSuccess(JSONObject oriData, ServerResponse response);
public abstract void onFailure(Throwable e);
public abstract void onFinish();
@Override
public void onNext(JSONObject data) {
ServerResponse response = ServerResponse.parseFromVolleyResponse(data);
Log.i(TAG, "onNext data=" + data);
//提示信息
if (!response.isSuccess) {
if (toastInfo) {
//如果服务器返回的status状态不为1,就弹出服务器给的吐司
if (!TextUtils.isEmpty(response.msg)) {
Toast.makeText(AppContext.getContext(), response.msg, Toast.LENGTH_SHORT).show();
} else if (!TextUtils.isEmpty(response.error)) {
Toast.makeText(AppContext.getContext(), response.error, Toast.LENGTH_SHORT).show();
}
}
}
if (null != response) {
onSuccess(data, response);
}
}
@Override
public void onError(Throwable e) {
Log.i(TAG, "onError e=" + e);
onFailure(e);
}
@Override
public void onCompleted() {
onFinish();
}
public SubListenerHelper setToastInfo(boolean toastInfo) {
this.toastInfo = toastInfo;
return this;
}
}
9.ServerResponse类
解析统一的格式
{"error":"E00000000","msg":"成功(没有异常)","status":"1"}
这是我的返回格式,不同格式可根据需求改代码
public class ServerResponse {
public static final int STATUS_SUCCESS = 1;
public boolean isSuccess;
public JSONObject data;
public String error;
public String msg;
public int status;
//对网络返回的json数据进行解析
public static ServerResponse parseFromVolleyResponse(JSONObject object) {
ServerResponse result = new ServerResponse();
if (object != null) {
result.status = object.optInt("status");
result.isSuccess = result.status == STATUS_SUCCESS;
result.error = object.optString("error");
result.msg = object.optString("msg");
//如果是数据就不能用result.data----object
result.data = object.optJSONObject("data");
}
return result;
}
@Override
public String toString() {
return "ServerResponse{" +
"data=" + data +
", error='" + error + '\'' +
", msg='" + msg + '\'' +
", status=" + status +
'}';
}
}