您的位置:首页 > 理论基础 > 计算机网络

android Retrofit+OKhttp实现接口调用

2017-10-16 17:36 671 查看

前言

最近几个项目都是使用的Retofit+OKHttp的来实现接口调用的,再之前的框架中本次加入了from表单的提交方式。为了方便自己以及大家整合了下,方便以后的工作开展

一.数据返回Model类

package com.reach.doooly.http.base;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import com.reach.doooly.bean.RHBaseVo;
import retrofit2.http.Multipart;
import retrofit2.http.POST;

/**
* @author fqming
*         <p>
*         公用的返回信息bean
*/

public class CommResultBeanVo extends RHBaseVo {
//错误码
private String code;
//信息
//下面的注释只有在gson中使用才有效
//    @Expose
//    @SerializedName("msg")
private String msg;
//返回信息

public String getMsg() {
return msg;
}

public void setMsg(String msg) {
this.msg = msg;
}

private String data;

public String getCode() {
return code;
}

public void setCode(String code) {
this.code = code;
}

public String getData() {
return data;
}

public void setData(String data) {
this.data = data;
}

/**純屬為了不該其他的方法而添加的方法*/
public String getMessage(){
return msg;
}

@Override
public String toString() {
return "CommResultBeanVo{" +
"code='" + code + '\'' +
",' message='" + msg + '\'' +
", data='" + data + "'\'}";
}
}


该类实为了方便数据解析,尤其是小编很不喜欢写json数据解析,喜欢用GSON,也是谷歌推荐的。

二.返回码

与后台服务端一起约定返回码,然后有下面的类

下面是小编与后端约定的返回码

package com.reach.doooly.http.client;

/**
* Created by tang on 2017/8/3 0003.
*/
public class ClientCode {
//成功
public static final int SUCCESS_CODE=1000;
//token失效
public static final int OUTTOKEN_CODE=40001;
}


三.Client Base类

package com.reach.doooly.http.client;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import okhttp3.ConnectionPool;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.fastjson.FastJsonConverterFactory;
import android.annotation.SuppressLint;
import android.content.Context;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.reach.doooly.http.base.BaseApiService;
import com.reach.doooly.http.base.CommResultBeanVo;
import com.reach.doooly.http.converfactory.StringConverterFactory;
import com.reach.doooly.http.cookie.CookieCacheImpl;
import com.reach.doooly.http.cookie.CookieManager;
import com.reach.doooly.http.cookie.SharedPrefsCookiePersistor;
import com.reach.doooly.http.errorhandler.NetException;
import com.reach.doooly.http.errorhandler.RxErrorHandlingCallAdapterFactory;
import com.reach.doooly.http.interceptor.DefaultHeaderInterceptor;
import com.reach.doooly.http.interceptor.OfflineCacheControlInterceptor;
import com.reach.doooly.http.util.Util;
import com.reach.doooly.utils.StringUtlis;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;

/**
* @author qinming.fu@reach-core.com
* <p>
* {@link # https://github.com/NeglectedByBoss/RetrofitClient} */

public final class Client {
public static final String TAG = "RetrofitClient";
private static Retrofit.Builder retrofitBuilder;
private static OkHttpClient.Builder okhttpBuilder;

@SuppressLint("StaticFieldLeak")
private static Context mContext;
private static BaseApiService apiService;

public static void init(Context context) {
mContext = context;
}

/**
* methodHandler
*/
private static List<Type> methodHandler(Type[] types) {
List<Type> needTypes = new ArrayList<>();

for (Type paramType : types) {
// if Type is T
if (paramType instanceof ParameterizedType) {
Type[] parenTypes = ((ParameterizedType) paramType).getActualTypeArguments();
for (Type childType : parenTypes) {
needTypes.add(childType);
if (childType instanceof ParameterizedType) {
Type[] childtypes = ((ParameterizedType) childType).getActualTypeArguments();
Collections.addAll(needTypes, childtypes);
}
}
}
}
return needTypes;
}

private static <T> Type getFinalType(final Observer<T> observable) {
final Type[] types = observable.getClass().getGenericInterfaces();
if (methodHandler(types) == null || methodHandler(types).size() == 0) {
return null;
}
return methodHandler(types).get(0);
}

private final ObservableTransformer schedulersTransformer = new ObservableTransformer() {

@Override
public ObservableSource apply(Observable upstream) {
return upstream.subscribeOn(Schedulers.io())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread());
}
};

private <T> Function parseBaseResultFunction(final Type type) {
return new Function() {
@Override
public T apply(Object o) throws Exception {
ResponseBody body = (ResponseBody) o;
byte[] bytes = body.bytes();
CommResultBeanVo result = null;
try {
//result=new Gson().fromJson(new String(bytes),CommResultBeanVo.class);[不可这样使用,gson要求后面数据类型必须一样一样的]
result = JSON.parseObject(new String(bytes), new TypeReference<CommResultBeanVo>() {
});
} catch (Exception e) {
result = null;
}
if (result != null && !StringUtlis.isEmpty(result.getCode())) {
int code=-1;
try{
code=Integer.parseInt(result.getCode());
}catch (Exception e){
code=-1;
}
if (code==ClientCode.SUCCESS_CODE) {

} else {
String errMsg = result.getMessage();
if (StringUtlis.isEmpty(errMsg)) {
errMsg = "";
}
throw new NetException(code, errMsg);
}
} else {
throw new NetException(-1, "");
}
return (T) result;
}
};
}

@SuppressWarnings("unchecked")
private <T> void compose(Observable respBody, final Observer<T> observer, ObservableTransformer transformer) {
if (transformer != null) {
respBody.compose(schedulersTransformer).compose(transformer).subscribe(observer);
} else {
respBody.compose(schedulersTransformer).subscribe(observer);
}
}

public <T> void get(final String path, final Map<String, Object> parameters, final Observer<T> observer) {
Observable respBody = apiService.get(path, parameters).map(parseBaseResultFunction(getFinalType(observer)));
compose(respBody, observer, null);
}

public <T> void postForm(final String path, final Map<String, Object> parameters, final Observer<T> observer) {
Observable respBody = apiService.post(path, parameters).map(parseBaseResultFunction(getFinalType(observer)));
compose(respBody, observer, null);
}

public <T> void postJson(final String path, final Map<String, Object> parameters, final Observer<T> observer) {
RequestBody body = Util.createJsonBody(Util.jsonStringFromMap(parameters));
Observable respBody = apiService.postJson(path, body).map(parseBaseResultFunction(getFinalType(observer)));
compose(respBody, observer, null);
}

public <T> void postJson(final String path, final Map<String, Object> parameters, final Observer<T> observer, Type type, final ObservableTransformer transformer) {
RequestBody body = Util.createJsonBody(Util.jsonStringFromMap(parameters));
Observable respBody = apiService.postJson(path, body).map(parseBaseResultFunction(type));
compose(respBody, observer, transformer);
}

public static final class Builder {
private static final int TIMEOUT_READ = 15;
private static final int TIMEOUT_CONNECTION = 15;
private static final int DEFAULT_MAXIDLE_CONNECTIONS = 5;
private static final long DEFAULT_KEEP_ALIVEDURATION = 8;
private static final long CACHE_MAX_SIZE = 10 * 1024 * 1024;

private String baseUrl;

public Builder() {
// Add the base url first. This prevents overriding its behavior but also
// ensures correct behavior when using novate that consume all types.
okhttpBuilder = new OkHttpClient.Builder();
retrofitBuilder = new Retrofit.Builder();
}

/**
* Create the {@link Retrofit} instance using the configured values.
* <p/>
* Note: A default {@link OkHttpClient} will be created and used.
*/
public Client build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}

if (mContext == null) {
throw new IllegalStateException("context required.");
}

if (okhttpBuilder == null) {
throw new IllegalStateException("okhttpBuilder required.");
}

if (retrofitBuilder == null) {
throw new IllegalStateException("retrofitBuilder required.");
}

/**
* Set a fixed API base URL.
*
* @see #baseUrl(HttpUrl)
*/

Interceptor cacheInterceptor = new OfflineCacheControlInterceptor();
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
okhttpBuilder.cookieJar(new CookieManager(new CookieCacheImpl(), new SharedPrefsCookiePersistor(mContext)))
.addInterceptor(loggingInterceptor)
//设置Cache目录
//.cache(new Cache(mContext.getCacheDir(), CACHE_MAX_SIZE))
//设置缓存
//.addInterceptor(cacheInterceptor)
.addNetworkInterceptor(cacheInterceptor)
//失败重连
.retryOnConnectionFailure(true)
.connectionPool(new ConnectionPool(DEFAULT_MAXIDLE_CONNECTIONS, DEFAULT_KEEP_ALIVEDURATION, TimeUnit.SECONDS))
//time out
.readTimeout(TIMEOUT_READ, TimeUnit.SECONDS)
.connectTimeout(TIMEOUT_CONNECTION, TimeUnit.SECONDS);

/**
* create okHttpClient
*/
OkHttpClient okHttpClient = okhttpBuilder.build();
/**
* set Retrofit client
*/
retrofitBuilder.client(okHttpClient)
.baseUrl(baseUrl)
//error 转换器
.addCallAdapterFactory(RxErrorHandlingCallAdapterFactory.create(mContext))
//Rx
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
//String转换器
.addConverterFactory(StringConverterFactory.create())
//fastjson转化器
.addConverterFactory(FastJsonConverterFactory.create());

apiService = retrofitBuilder.build().create(BaseApiService.class);
return new Client();
}

/**
* Set an API base URL which can change over time.
*/
public Builder baseUrl(String baseUrl) {
this.baseUrl = Util.checkNotNull(baseUrl, "baseUrl == null");
return this;
}

/**
* Add Header for serialization and deserialization of objects.
*/
public <T> Builder addHeader(Map<String, T> headers) {
okhttpBuilder.addInterceptor(new DefaultHeaderInterceptor<>(Util.checkNotNull(headers, "header == null")));
return this;
}

/**
* Returns a modifiable list of interceptors that observe a single network request and response.
* These interceptors must call {@link Interceptor.Chain#proceed} exactly once: it is an error
* for a network interceptor to short-circuit or repeat a network request.
*/
public Builder addInterceptor(Interceptor interceptor) {
okhttpBuilder.addInterceptor(Util.checkNotNull(interceptor, "interceptor == null"));
return this;
}
}
}


四.自己的类的基本实现

package com.reach.doooly.server;

import io.reactivex.Observer;
import okhttp3.Callback;
import okhttp3.ConnectionPool;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.reach.doooly.base.log.Logs;
import com.reach.doooly.consts.Constans;
import com.reach.doooly.http.base.CommResultBeanVo;
import com.reach.doooly.http.client.Client;
import com.reach.doooly.http.interceptor.OfflineCacheControlInterceptor;
import com.reach.doooly.utils.StringUtlis;
import com.reach.doooly.utils.UserManager;

/**
* @author qinming.fu@reach-core.com
*         <p>
*         <p>
*         网络基础请求服务, 所有的接口都需要调用此接口
*/

public final class NetService {
public static final String TAG = "NetService";

private static final String HEADER_TOKEN_KEY = "Token";
private static final String HEADER_APPVERSION_KEY = "AppVersion";
private static final String HEADER_CHANNELID_KEY = "Channel";
private static final String HEADER_TIMESTAMP_KEY = "Time";

//public static String COMM_TOKEN="";
// RHConstants.DEBUG_URL
public static String ufttt = Constans.SERVICE_URL;
public static Client client = new Client.Builder().baseUrl(ufttt)
.addHeader(defaultHeader()).build();

private static NetService INSTANCE;

public static synchronized NetService getInstance() {
if (INSTANCE == null) {
INSTANCE = new NetService();
}
return INSTANCE;
}

private NetService() {

}

public static Map<String, String> defaultHeader() {
Map<String, String> map = new HashMap<>();
if (!StringUtlis.isEmpty(UserManager.getInstance().getToken())) {
String cookie = "token=" + UserManager.getInstance().getToken();
if (!StringUtlis.isEmpty(UserManager.getInstance().getUserId())) {
cookie += ";uid=" + UserManager.getInstance().getUserId();
}
map.put("Cookie", cookie);
}
map.put(HEADER_CHANNELID_KEY, "10002");
return map;
}

/**
* 版本更新接口
*
* @param map
* @param obj
*/
public void updateVersion(Map<String, Object> map, Observer<CommResultBeanVo> obj) {
client.postJson("。。。", map, obj);
}

/**
* 我要申诉提交信息
* @param params
* @param files
* @param callback
*/
public void commitAgainst(Map<String,Object> params,List<File> files, Callback callback){
sendMultipart("。。。",params,files,callback);
}

/**
* 上传多张图片及参数
*
* @param reqUrl URL地址
* @param params 参数
*/
public void sendMultipart(String reqUrl, Map<String,Object> params, List<File> files, Callback callback) {
MultipartBody.Builder multipartBodyBuilder = new MultipartBody.Builder();
multipartBodyBuilder.setType(MultipartBody.FORM);
//遍历map中所有参数到builder
if (params != null) {
for (String key : params.keySet()) {
multipartBodyBuilder.addFormDataPart(key, params.get(key).toString());
}
}
//遍历paths中所有图片绝对路径到builder,并约定key如“upload”作为后台接受多张图片的key
if (files != null) {
int i = -1;
for (File file : files) {
i = i + 1;
multipartBodyBuilder.addFormDataPart("image" + i, file.getName(), RequestBody.create(MediaType.parse("image/png"), file));
}
}
//构建请求体
RequestBody requestBody = multipartBodyBuilder.build();
Request.Builder RequestBuilder = new Request.Builder();
RequestBuilder.url(NetService.ufttt + reqUrl);// 添加URL地址
RequestBuilder.post(requestBody);
String cookie ="";
if (!StringUtlis.isEmpty(UserManager.getInstance().getToken())) {
cookie = "token=" + UserManager.getInstance().getToken();
if (!StringUtlis.isEmpty(UserManager.getInstance().getUserId())) {
cookie += ";uid=" + UserManager.getInstance().getUserId();
}
}
Request request = RequestBuilder.addHeader("Cookie",cookie).build();
Interceptor cacheInterceptor = new OfflineCacheControlInterceptor();
OkHttpClient okHttpClient=new OkHttpClient.Builder()
.addNetworkInterceptor(cacheInterceptor)
.retryOnConnectionFailure(true)//失败重连
.connectionPool(new ConnectionPool(5,8, TimeUnit.SECONDS))
.readTimeout(15, TimeUnit.SECONDS)
.connectTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.readTimeout(15,TimeUnit.SECONDS)
.build();
okHttpClient.newCall(request).enqueue(callback);
//client.postJson();
}

}


基本上使用就是这些,具体的https相关的实现,本人已经上传资源,下载地址

http://download.csdn.net/download/onlymetagain/10024542
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息