技术选型
HttpClient、HttpUrlConnection、Volley、okhttp/retrofit
这里选用okhttp
封装思路
导包
新建lib_networkmodule
在自定义的项目.gradle文件中添加
ext {
...
depsVersion = [
...
okhttp : '3.3.0',
gson : '2.8.0',
]
depsLibs = [
...
okhttp : "com.squareup.okhttp3:okhttp:${depsVersion.okhttp}",
gson : "com.google.code.gson:gson:${depsVersion.gson}",
]
}
在lib_network的build.gradle中添加
android {
compileSdkVersion rootProject.android.compileSdkVersion
defaultConfig {
minSdkVersion rootProject.android.minSdkVersion
targetSdkVersion rootProject.android.targetSdkVersion
versionCode 1
versionName "1.0"
}
...
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
compileOnly rootProject.depsLibs.appcompact
implementation rootProject.depsLibs.okhttp //okttp依赖
compileOnly rootProject.depsLibs.gson
}
request封装
post请求
新建RequestParams,用于保存请求所需的参数
public class RequestParams {
public ConcurrentHashMap<String, String> urlParams = new ConcurrentHashMap<String, String>();
public ConcurrentHashMap<String, Object> fileParams = new ConcurrentHashMap<String, Object>();
public RequestParams() {
this((Map<String, String>) null);
}
public RequestParams(Map<String, String> source) {
if (source != null) {
for (Map.Entry<String, String> entry : source.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
}
public RequestParams(final String key, final String value) {
this(new HashMap<String, String>() {
{
put(key, value);
}
});
}
public void put(String key, String value) {
if (key != null && value != null) {
urlParams.put(key, value);
}
}
public void put(String key, Object object) throws FileNotFoundException {
if (key != null) {
fileParams.put(key, object);
}
}
public boolean hasParams() {
if(urlParams.size() > 0 || fileParams.size() > 0){
return true;
}
return false;
}
}
新建request包,在包下面新建CommonRequest
public static Request createPostRequest(String url, RequestParams params) {
return createPostRequest(url, params, null);
}
/**
* 可以带请求头的Post请求
*/
public static Request createPostRequest(String url, RequestParams params, RequestParams headers) {
FormBody.Builder mFormBodyBuild = new FormBody.Builder();
if (params != null) {
for (Map.Entry<String, String> entry : params.urlParams.entrySet()) {
mFormBodyBuild.add(entry.getKey(), entry.getValue());
}
}
//添加请求头
Headers.Builder mHeaderBuild = new Headers.Builder();
if (headers != null) {
for (Map.Entry<String, String> entry : headers.urlParams.entrySet()) {
mHeaderBuild.add(entry.getKey(), entry.getValue());
}
}
FormBody mFormBody = mFormBodyBuild.build();
Headers mHeader = mHeaderBuild.build();
Request request = new Request.Builder().url(url).
post(mFormBody).
headers(mHeader)
.build();
return request;
}
get请求
public static Request createGetRequest(String url, RequestParams params) {
return createGetRequest(url, params, null);
}
/**
* 可以带请求头的Get请求
*/
public static Request createGetRequest(String url, RequestParams params, RequestParams headers) {
StringBuilder urlBuilder = new StringBuilder(url).append("?");
if (params != null) {
for (Map.Entry<String, String> entry : params.urlParams.entrySet()) {
urlBuilder.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
}
//添加请求头
Headers.Builder mHeaderBuild = new Headers.Builder();
if (headers != null) {
for (Map.Entry<String, String> entry : headers.urlParams.entrySet()) {
mHeaderBuild.add(entry.getKey(), entry.getValue());
}
}
Headers mHeader = mHeaderBuild.build();
return new Request.Builder().
url(urlBuilder.substring(0, urlBuilder.length() - 1))
.get()
.headers(mHeader)
.build();
}
文件上传请求
/**
* 文件上传请求
*/
private static final MediaType FILE_TYPE = MediaType.parse("application/octet-stream");
public static Request createMultiPostRequest(String url, RequestParams params) {
MultipartBody.Builder requestBody = new MultipartBody.Builder();
requestBody.setType(MultipartBody.FORM);
if (params != null) {
for (Map.Entry<String, Object> entry : params.fileParams.entrySet()) {
if (entry.getValue() instanceof File) {
requestBody.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + entry.getKey() + "\""),
RequestBody.create(FILE_TYPE, (File) entry.getValue()));
} else if (entry.getValue() instanceof String) {
requestBody.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + entry.getKey() + "\""),
RequestBody.create(null, (String) entry.getValue()));
}
}
}
return new Request.Builder().url(url).post(requestBody.build()).build();
}
response封装
json类型响应处理
public class CommonJsonCallback implements Callback {
protected final String RESULT_CODE = "ecode"; // 有返回则对于http请求来说是成功的,但还有可能是业务逻辑上的错误
protected final int RESULT_CODE_VALUE = 0;
protected final String ERROR_MSG = "emsg";
protected final String EMPTY_MSG = "";
protected final int NETWORK_ERROR = -1; // the network relative error
protected final int JSON_ERROR = -2; // the JSON relative error
protected final int OTHER_ERROR = -3; // the unknow error
/**
* 将其它线程的数据转发到UI线程
*/
private Handler mDeliveryHandler;
private DisposeDataListener mListener;
private Class<?> mClass;
public CommonJsonCallback(DisposeDataHandle handle) {
this.mListener = handle.mListener;
this.mClass = handle.mClass;
this.mDeliveryHandler = new Handler(Looper.getMainLooper());
}
@Override
public void onFailure(final Call call, final IOException ioexception) {
//此时还在非UI线程,因此要转发
mDeliveryHandler.post(new Runnable() {
@Override
public void run() {
mListener.onFailure(new OkHttpException(NETWORK_ERROR, ioexception));
}
});
}
@Override
public void onResponse(final Call call, final Response response) throws IOException {
final String result = response.body().string();
mDeliveryHandler.post(new Runnable() {
@Override
public void run() {
handleResponse(result);
}
});
}
private void handleResponse(Object responseObj) {
if (responseObj == null || responseObj.toString().trim().equals("")) {
mListener.onFailure(new OkHttpException(NETWORK_ERROR, EMPTY_MSG));
return;
}
try {
JSONObject result = new JSONObject(responseObj.toString());
if (mClass == null) {
mListener.onSuccess(result);
} else {
Object obj = new Gson().fromJson(responseObj.toString(), mClass);
if (obj != null) {
mListener.onSuccess(obj);
} else {
mListener.onFailure(new OkHttpException(JSON_ERROR, EMPTY_MSG));
}
}
} catch (Exception e) {
mListener.onFailure(new OkHttpException(OTHER_ERROR, e.getMessage()));
e.printStackTrace();
}
}
}
文件类型响应处理
public class CommonFileCallback implements Callback {
protected final int NETWORK_ERROR = -1; // the network relative error
protected final int IO_ERROR = -2; // the JSON relative error
protected final String EMPTY_MSG = "";
/**
* 将其它线程的数据转发到UI线程
*/
private static final int PROGRESS_MESSAGE = 0x01;
private Handler mDeliveryHandler;
private DisposeDownloadListener mListener;
private String mFilePath;
private int mProgress;
public CommonFileCallback(DisposeDataHandle handle) {
this.mListener = (DisposeDownloadListener) handle.mListener;
this.mFilePath = handle.mSource;
this.mDeliveryHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case PROGRESS_MESSAGE:
mListener.onProgress((int) msg.obj);
break;
}
}
};
}
@Override
public void onFailure(final Call call, final IOException ioexception) {
mDeliveryHandler.post(new Runnable() {
@Override
public void run() {
mListener.onFailure(new OkHttpException(NETWORK_ERROR, ioexception));
}
});
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final File file = handleResponse(response);
mDeliveryHandler.post(new Runnable() {
@Override
public void run() {
if (file != null) {
mListener.onSuccess(file);
} else {
mListener.onFailure(new OkHttpException(IO_ERROR, EMPTY_MSG));
}
}
});
}
/**
* 此时还在子线程中,不则调用回调接口
*/
private File handleResponse(Response response) {
if (response == null) {
return null;
}
InputStream inputStream = null;
File file = null;
FileOutputStream fos = null;
byte[] buffer = new byte[2048];
int length;
int currentLength = 0;
double sumLength;
try {
checkLocalFilePath(mFilePath);
file = new File(mFilePath);
fos = new FileOutputStream(file);
inputStream = response.body().byteStream();
sumLength = (double) response.body().contentLength();
while ((length = inputStream.read(buffer)) != -1) {
fos.write(buffer, 0, length);
currentLength += length;
mProgress = (int) (currentLength / sumLength * 100);
mDeliveryHandler.obtainMessage(PROGRESS_MESSAGE, mProgress).sendToTarget();
}
fos.flush();
} catch (Exception e) {
file = null;
} finally {
try {
if (fos != null) {
fos.close();
}
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return file;
}
private void checkLocalFilePath(String localFilePath) {
File path = new File(localFilePath.substring(0,
localFilePath.lastIndexOf("/") + 1));
File file = new File(localFilePath);
if (!path.exists()) {
path.mkdirs();
}
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
okhttpclient封装
/**
* 用来发送get, post请求的工具类,包括设置一些请求的共用参数
*/
public class CommonOkHttpClient {
private static final int TIME_OUT = 30;
private static OkHttpClient mOkHttpClient;
static {
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
okHttpClientBuilder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
/**
* 为所有请求添加请求头,看个人需求
*/
okHttpClientBuilder.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain
.request()
.newBuilder()
.addHeader("User-Agent", "Imooc-Mobile") // 标明发送本次请求的客户端
.build();
return chain.proceed(request);
}
});
okHttpClientBuilder.cookieJar(new SimpleCookieJar());
okHttpClientBuilder.connectTimeout(TIME_OUT, TimeUnit.SECONDS);
okHttpClientBuilder.readTimeout(TIME_OUT, TimeUnit.SECONDS);
okHttpClientBuilder.writeTimeout(TIME_OUT, TimeUnit.SECONDS);
okHttpClientBuilder.followRedirects(true);
/**
* trust all the https point
*/
okHttpClientBuilder.sslSocketFactory(HttpsUtils.initSSLSocketFactory(),
HttpsUtils.initTrustManager());
mOkHttpClient = okHttpClientBuilder.build();
}
public static OkHttpClient getOkHttpClient() {
return mOkHttpClient;
}
/**
* 通过构造好的Request,Callback去发送请求
*/
public static Call get(Request request, DisposeDataHandle handle) {
Call call = mOkHttpClient.newCall(request);
call.enqueue(new CommonJsonCallback(handle));
return call;
}
public static Call post(Request request, DisposeDataHandle handle) {
Call call = mOkHttpClient.newCall(request);
call.enqueue(new CommonJsonCallback(handle));
return call;
}
public static Call downloadFile(Request request, DisposeDataHandle handle) {
Call call = mOkHttpClient.newCall(request);
call.enqueue(new CommonFileCallback(handle));
return call;
}
}
请求框架使用
public class RequestCenter {
//根据参数发送所有post请求
public static void getRequest(String url, RequestParams params, DisposeDataListener listener,
Class<?> clazz) {
CommonOkHttpClient.get(CommonRequest.
createGetRequest(url, params), new DisposeDataHandle(listener, clazz));
}
/**
* 用户登陆请求
*/
public static void login(DisposeDataListener listener) {
RequestParams params = new RequestParams();
params.put("phone", "13677778888");
params.put("pwd", "123456");
RequestCenter.getRequest(HttpConstants.LOGIN, params, listener, User.class);
}
}