java okhttp3 工具类_OkHttp3 超级简单实用封装

本人分成了四个类,其实可以更加精简,两个类足以

首先引入依赖 okhttp github地址

implementation("com.squareup.okhttp3:okhttp:3.14.2")

上代码,首先展示一下请求代码(Kotlin)

OkHttp.post("url") //请求地址和请求方式,get和post方式切换

.add(map) //参数可以直接传入map集合

.add("key","value") //参数也可以传入键值对

.build(object : HttpCallBack() { //传入返回的实体类

override fun success(t: T?) {

//得到返回的实体类

}

override fun error(err: String?) {

//得到错误信息提醒

}

})

以上就是请求示例代码,够简单了吧,当然这都是表面的,下面来看一下背后做的工作

上关键类 OkHttp :

import android.annotation.SuppressLint;

import android.os.Handler;

import android.os.Message;

import com.toune.util.rxtool.GsonBinder;

import com.toune.util.rxtool.RxFileTool;

import okhttp3.*;

import org.json.JSONException;

import org.json.JSONObject;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.net.FileNameMap;

import java.net.URLConnection;

import java.util.HashMap;

import java.util.Map;

public class OkHttp {

private static int METHOD = 1000;

private static final int POST = 1001;

private static final int GET = 1002;

private static OkHttp okHttp;

private File updateFile;

public static void instance() {

okHttp = new OkHttp();

}

private static OkHttpClient okHttpClient;

private static RequestBody requestBody;

private static Request request;

private static String requestUrl;

public static OkHttp post(String url) {

instance();

okHttpClient = new OkHttpClient();

METHOD = POST;

requestUrl = url;

return okHttp;

}

public static OkHttp get(String url) {

instance();

okHttpClient = new OkHttpClient();

METHOD = GET;

requestUrl = url;

return okHttp;

}

private Map params = new HashMap();

private Map files = new HashMap<>();

public OkHttp add(String key, Object value) {

params.put(key, String.valueOf(value));

return this;

}

public OkHttp add(Map map) {

params.putAll(map);

return this;

}

public OkHttp add(String key, File file) {

files.put(key, file);

return this;

}

private int BUILD_TYPE = 300;

private final int JSON_TYPE = 301;

private final int FILE_TYPE = 302;

private MediaType JSONType = MediaType.parse("application/json; charset=utf-8");

public void buildByJson(final HttpCallBack httpCallBack) {

BUILD_TYPE = JSON_TYPE;

build(httpCallBack);

}

/**

* 基于http的文件上传(传入文件数组和key)混合参数和文件请求

* 通过addFormDataPart可以添加多个上传的文件

*/

private void buidByFile(final HttpCallBack myDataCallBack) {

if (params == null) {

params = new HashMap<>();

}

FormBody.Builder builder = new FormBody.Builder();

//form表单提交

for (String key : params.keySet()) {

builder.add(key, (String) params.get(key));

}

RequestBody body = builder.build();

MultipartBody.Builder multipartBody = new MultipartBody.Builder();

multipartBody.setType(MultipartBody.ALTERNATIVE)

.addPart(body);

if (files != null) {

RequestBody fileBody = null;

for (String key : files.keySet()) {

File file = files.get(key);

String fileName = file.getName();

fileBody = RequestBody.create(MediaType.parse(guessMimeType(fileName)), file);

//TODO 根据文件名设置contentType

multipartBody.addPart(Headers.of("Content-Disposition",

"form-data; name=\"" + key + "\"; filename=\"" + fileName + "\""),

fileBody);

}

}

requestBody = multipartBody.build();

BUILD_TYPE = FILE_TYPE;

}

private String guessMimeType(String fileName) {

FileNameMap fileNameMap = URLConnection.getFileNameMap();

String contentTypeFor = fileNameMap.getContentTypeFor(fileName);

if (contentTypeFor == null) {

contentTypeFor = "application/octet-stream";

}

return contentTypeFor;

}

public void build(final HttpCallBack httpCallBack) {

this.httpCallBack = httpCallBack;

handler.sendEmptyMessage(START);

switch (BUILD_TYPE) {

case JSON_TYPE: //json提交

requestBody = RequestBody.create(JSONType, GsonBinder.toJsonStr(params));

break;

case FILE_TYPE:

break;

default:

//form表单提交

FormBody.Builder builder = new FormBody.Builder();

for (String key : params.keySet()) {

builder.add(key, (String) params.get(key));

}

requestBody = builder.build();

break;

}

if (METHOD == GET) {

request = new Request.Builder()

.url(requestUrl)

.get()//默认就是GET请求,可以不写

.build();

} else if (METHOD == POST) {

request = new Request.Builder()

.url(requestUrl)

.post(requestBody)

.build();

}

Call call = okHttpClient.newCall(request);

call.enqueue(new Callback() {

@Override

public void onFailure(Call call, IOException e) {

Message message = new Message();

message.obj = e.getMessage();

message.what = ERROR;

handler.sendMessage(message);

}

@Override

public void onResponse(Call call, Response response) throws IOException {

try {

String jsonStr = response.body().string();

JSONObject jsonObject = new JSONObject(jsonStr);

String msg = "";

if (jsonObject.has("info")) {

msg = jsonObject.getString("info");

}

if (jsonObject.has("status")) {

String status = jsonObject.getString("status");

if ("1".equals(status)) {

//成功

if (jsonObject.has("data")) {

T data = GsonBinder.toObj(jsonObject.getString("data"),httpCallBack.mType);

response.close();

Message message = new Message();

message.obj = data;

message.what = SUCCESS;

handler.sendMessage(message);

}

} else if ("0".equals(status)) {

//错误

Message message = new Message();

message.obj = msg;

message.what = ERROR;

handler.sendMessage(message);

} else {

Message message = new Message();

message.obj = msg;

message.what = ERROR;

handler.sendMessage(message);

}

}

} catch (Exception e) {

e.printStackTrace();

handler.sendEmptyMessage(END);

} catch (Throwable throwable) {

throwable.printStackTrace();

}

handler.sendEmptyMessage(END);

}

});

}

private HttpCallBack httpCallBack;

@SuppressLint("HandlerLeak")

Handler handler = new Handler() {

@Override

public void handleMessage(Message msg) {

switch (msg.what) {

case START:

httpCallBack.start();

break;

case SUCCESS:

httpCallBack.success(msg.obj);

break;

case ERROR:

if (msg.obj != null) {

httpCallBack.error(msg.obj.toString());

}

httpCallBack.end();

break;

case END:

httpCallBack.end();

break;

}

}

};

private final int START = 10001;

private final int SUCCESS = 10002;

private final int ERROR = 10003;

private final int END = 10004;

/**

* 下载文件******************************************************************************************************************************************

*/

/**

* 文件下载

*

* @param url path路径

* @param destFileDir 本地存储的文件夹路径

* @param myDataCallBack 自定义回调接口

*/

private static String downUrl;

private static String filrDir;

private long totalSize = 0L; //APK总大小

private long downloadSize = 0L; // 下载的大小

private float count = 0L; //下载百分比

public static OkHttp downFile(String realURL, String destFileDir) {

instance();

downUrl = realURL;

filrDir = destFileDir;

return okHttp;

}

public void down(HttpFileCallBack httpFileCallBack) {

this.httpFileCallBack = httpFileCallBack;

Request request = new Request.Builder()

.url(downUrl)

.build();

okHttpClient = new OkHttpClient();

Call call = okHttpClient.newCall(request);

call.enqueue(new Callback() {

@Override

public void onFailure(Call call, IOException e) {

Message message = new Message();

message.obj = e.getMessage();

message.what = ERROR;

fileHandler.sendMessage(message);

}

@Override

public void onResponse(Call call, Response response) {

if (response.code() == 200) {

InputStream is = null;

byte[] buf = new byte[4096];

int len = 0;

FileOutputStream fos = null;

try {

totalSize = response.body().contentLength();

downloadSize = 0L;

if (memoryAvailable(totalSize)) {

is = response.body().byteStream();

fos = new FileOutputStream(updateFile, true);

while ((len = is.read(buf)) != -1) {

downloadSize += len;

fos.write(buf, 0, len);

if ((count == 0) || (int) (downloadSize * 100 / totalSize) >= count) {

count += 5;

//文本进度(百分比)

Message message = new Message();

message.obj = count;

message.what = FILE_PROGRESS;

}

}

fos.flush();

if (totalSize >= downloadSize) {

fileHandler.sendEmptyMessage(SUCCESS);

} else {

Message message = new Message();

message.obj = "下载失败";

message.what = ERROR;

fileHandler.sendMessage(message);

}

} else {

Message message = new Message();

message.obj = "内存不足";

message.what = ERROR;

fileHandler.sendMessage(message);

}

} catch (IOException e) {

e.printStackTrace();

Message message = new Message();

message.obj = "下载失败";

message.what = ERROR;

fileHandler.sendMessage(message);

} finally {

try {

if (is != null) {

is.close();

}

if (fos != null) {

fos.close();

}

} catch (IOException e) {

e.printStackTrace();

}

}

} else {

Message message = new Message();

message.obj = "下载失败";

message.what = ERROR;

fileHandler.sendMessage(message);

}

}

});

}

private String getFileName(String url) {

int separatorIndex = url.lastIndexOf("/");

return (separatorIndex < 0) ? url : url.substring(separatorIndex + 1, url.length());

}

/**

* 可用内存大小

*

* @param fileSize

* @return

*/

private boolean memoryAvailable(long fileSize) {

fileSize += (1024 << 10);

if (MemoryStatus.externalMemoryAvailable()) {

if ((MemoryStatus.getAvailableExternalMemorySize() <= fileSize)) {

if ((MemoryStatus.getAvailableInternalMemorySize() > fileSize)) {

createFile(false);

return true;

} else {

return false;

}

} else {

createFile(true);

return true;

}

} else {

if (MemoryStatus.getAvailableInternalMemorySize() <= fileSize) {

return false;

} else {

createFile(false);

return true;

}

}

}

private void createFile(boolean b) {

RxFileTool.createFileByDeleteOldFile(filrDir + getFileName(downUrl));

updateFile = RxFileTool.getFileByPath(filrDir + getFileName(downUrl));

}

private HttpFileCallBack httpFileCallBack;

Handler fileHandler = new Handler() {

@Override

public void handleMessage(Message msg) {

switch (msg.what) {

case FILE_START:

httpFileCallBack.start();

break;

case FILE_PROGRESS:

httpFileCallBack.progress((int) msg.obj);

break;

case FILE_SUCCESS:

httpFileCallBack.success(updateFile);

break;

case FILE_ERROR:

if (msg.obj != null) {

httpFileCallBack.error(msg.obj.toString());

}

httpFileCallBack.end();

break;

case FILE_END:

httpFileCallBack.end();

break;

}

}

};

private final int FILE_START = 100001;

private final int FILE_SUCCESS = 100002;

private final int FILE_ERROR = 100003;

private final int FILE_END = 100004;

private static final int FILE_PROGRESS = 100005;

/***************************************************************下载完文件*******************************************************************/

}

这个类中,我做了符合我们项目的深度配置,但是大部分项目都差不多,所以如果需要适配你们的项目只需要修改

3b82a5c468d6

TIM截图20190803101224.png

这个部分就可以了

上配套类 HttpCallBack

import com.google.gson.internal.$Gson$Types;

import java.lang.reflect.ParameterizedType;

import java.lang.reflect.Type;

public abstract class HttpCallBack {

public Type mType;

public HttpCallBack() {

//Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。

Type superclass = getClass().getGenericSuperclass();

if (superclass instanceof Class) {

// throw new RuntimeException("请传入实体类");

mType = null;

} else {

//ParameterizedType参数化类型,即泛型

ParameterizedType parameterized = (ParameterizedType) superclass;

//getActualTypeArguments获取参数化类型的数组,泛型可能有多个

//将Java 中的Type实现,转化为自己内部的数据实现,得到gson解析需要的泛型

mType = $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);

}

}

public void start() {

}

public abstract void success(T t);

public abstract void error(String err);

public void end() {

}

}

这是数据返回类,可以在这里面修改需要实现的方法

为了更清晰,我把文件下载做了单独的返回

import java.io.File;

/**

* 下载文件返回

*/

public abstract class HttpFileCallBack {

public void start() {

}

public abstract void progress(int size);

public abstract void success(File file);

public abstract void error(String err);

public void end() {

}

}

还有内存管理工具类

import android.os.Environment;

import android.os.StatFs;

import android.util.Log;

import java.io.File;

/**

* 完成代码的健壮性,其实现在的Android手机的储存都的够用的。

* 一般不会没有空间,有这个类来判断就更健壮一些

*/

public class MemoryStatus {

private static final int ERROR = -1;

// 判断SD卡是否存在?

static public boolean externalMemoryAvailable() {

return Environment.getExternalStorageState().equals(

Environment.MEDIA_MOUNTED);

}

// 获取内部存储器有用空间大小?

static public long getAvailableInternalMemorySize() {

File path = Environment.getDataDirectory();

StatFs stat = new StatFs(path.getPath());

long blockSize = stat.getBlockSize();

long availableBlocks = stat.getAvailableBlocks();

return availableBlocks * blockSize;

}

// 获取内部存储器空间的大小

static public long getTotalInternalMemorySize() {

File path = Environment.getDataDirectory();

StatFs stat = new StatFs(path.getPath());

long blockSize = stat.getBlockSize();

long totalBlocks = stat.getBlockCount();

return totalBlocks * blockSize;

}

// 获取SD卡有用空间大小,错误返回-1

static public long getAvailableExternalMemorySize() {

if (externalMemoryAvailable()) {

File path = Environment.getExternalStorageDirectory();

StatFs stat = new StatFs(path.getPath());

long blockSize = stat.getBlockSize();

long availableBlocks = stat.getAvailableBlocks();

return availableBlocks * blockSize;

} else {

return ERROR;

}

}

// 获取SD卡的空间大小,错误返码1

static public long getTotalExternalMemorySize() {

if (externalMemoryAvailable()) {

File path = Environment.getExternalStorageDirectory();

StatFs stat = new StatFs(path.getPath());

long blockSize = stat.getBlockSize();

long totalBlocks = stat.getBlockCount();

return totalBlocks * blockSize;

} else {

return ERROR;

}

}

/**

* 根据给定的文件的路径来计算文件夹的大小

*

* @param dir 文件的路径

* @return 文件夹的大小

*/

static public long getFileSize(File dir) {

if (dir == null) {

return 0;

}

if (!dir.isDirectory()) {

return 0;

}

long dirSize = 0;

File[] files = dir.listFiles();

for (File file : files) {

if (file.isFile()) {

dirSize += file.length();

} else if (file.isDirectory()) {

dirSize += getFileSize(file); //如果是目标那就进行递归 来计算文件的大小

}

}

return dirSize;

}

// 把文件大小转化字符串

static public String formatSize(long size) {

Log.d("WL-gui", "文件的大小为:" + size);

String suffix = null;

if (size == 0) {

return "";

}

if (size >= 1024) {

suffix = "KB";

size /= 1024;

if (size >= 1024) {

suffix = "MB";

size /= 1024;

if (size >= 1024) {

suffix = "G";

size /= 1024;

}

}

}

StringBuilder resultBuffer = new StringBuilder(Long.toString(size));

int commaOffset = resultBuffer.length() - 3;

while (commaOffset > 0) {

resultBuffer.insert(commaOffset, ',');

commaOffset -= 3;

}

if (suffix != null)

resultBuffer.append(suffix);

return resultBuffer.toString();

}

}

GsonBinder类

import android.text.TextUtils;

import com.google.gson.Gson;

import com.google.gson.GsonBuilder;

import com.google.gson.JsonDeserializationContext;

import com.google.gson.JsonDeserializer;

import com.google.gson.JsonElement;

import com.google.gson.JsonParseException;

import com.google.gson.JsonPrimitive;

import com.google.gson.JsonSerializationContext;

import com.google.gson.JsonSerializer;

import com.google.gson.reflect.TypeToken;

import java.lang.reflect.ParameterizedType;

import java.lang.reflect.Type;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

/**

* Created by Administrator on 2018/1/11 0011.

*/

public class GsonBinder {

//定义并配置gson

private static final Gson gson = new GsonBuilder()//建造者模式设置不同的配置

.serializeNulls()//序列化为null对象

.setDateFormat("yyyy-MM-dd HH:mm:ss") //设置日期的格式

.disableHtmlEscaping()//防止对网址乱码 忽略对特殊字符的转换

.registerTypeAdapter(String.class, new StringConverter())//对为null的字段进行转换

.create();

/**

* 对解析数据的形式进行转换

*

* @param obj 解析的对象

* @return 转化结果为json字符串

*/

public static String toJsonStr(Object obj) {

if (obj == null) {

return "";

}

try {

return gson.toJson(obj);

} catch (Exception e) {

return "";

}

}

/**

* 解析为一个具体的对象

*

* @param json 要解析的字符串

* @param obj 要解析的对象

* @param 将json字符串解析成obj类型的对象

* @return

*/

public static T toObj(String json, Class obj) {

//如果为null直接返回为null

if (obj == null || TextUtils.isEmpty(json)) {

return null;

}

try {

return gson.fromJson(json, obj);

} catch (Exception e) {

return null;

}

}

/**

* @return 不区分类型 传什么解析什么

*/

public static T toObj(String jsonStr, Type type) {

T t = null;

try {

t = gson.fromJson(jsonStr, type);

} catch (Exception e) {

e.printStackTrace();

}

return t;

}

/**

* 将Json数组解析成相应的映射对象列表

* 解决类型擦除的问题

*/

public static List toList(String jsonStr, Class clz) {

List list = gson.fromJson(jsonStr, new type(clz));

if (list == null) list = new ArrayList<>();

return list;

}

public static Map toMap(String jsonStr, Class clz) {

Map map = gson.fromJson(jsonStr, new type(clz));

if (map == null) map = new HashMap<>();

return map;

}

public static Map toMap(String jsonStr) {

Map dataMap = new HashMap<>();

try {

Type type = new TypeToken>() {

}.getType();

dataMap = gson.fromJson(jsonStr, type);

} catch (Exception e) {

e.printStackTrace();

}

return dataMap;

}

public static Map toMapStr(String jsonStr) {

Map dataMap = new HashMap<>();

try {

Type type = new TypeToken>() {

}.getType();

dataMap = gson.fromJson(jsonStr, type);

} catch (Exception e) {

e.printStackTrace();

}

return dataMap;

}

private static class type implements ParameterizedType {

private Type type;

private type(Type type) {

this.type = type;

}

@Override

public Type[] getActualTypeArguments() {

return new Type[]{type};

}

@Override

public Type getRawType() {

return ArrayList.class;

}

@Override

public Type getOwnerType() {

return null;

}

}

/**

* 实现了 序列化 接口 对为null的字段进行转换

*/

static class StringConverter implements JsonSerializer, JsonDeserializer {

//字符串为null 转换成"",否则为字符串类型

@Override

public String deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {

return json.getAsJsonPrimitive().getAsString();

}

@Override

public JsonElement serialize(String src, Type typeOfSrc, JsonSerializationContext context) {

return src == null || src.equals("null") ? new JsonPrimitive("") : new JsonPrimitive(src.toString());

}

}

}

GsonBinder类需要引用 implementation 'com.google.code.gson:gson:2.8.5'

以上就是全部代码了,第一次写文章,文字叙述和表达有不到位的地方,还请见谅,有问题可以留言

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值