public class OkHttp3Utils {

private volatile static OkHttp3Utils mInstance;

private OkHttpClient mOkHttpClient;

private Handler mHandler;

private Context mContext;

private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");

private OkHttp3Utils(Context context) {

super();

Builder clientBuilder = new OkHttpClient().newBuilder();

clientBuilder.readTimeout(30, TimeUnit.SECONDS);

clientBuilder.connectTimeout(15, TimeUnit.SECONDS);

clientBuilder.writeTimeout(60, TimeUnit.SECONDS);

mOkHttpClient = clientBuilder.build();

this.mContext = context.getApplicationContext();

mHandler = new Handler(mContext.getMainLooper());

}

public static OkHttp3Utils getInstance(Context context) {

OkHttp3Utils temp = mInstance;

if (temp == null) {

synchronized (OkHttp3Utils.class) {

temp = mInstance;

if (temp == null) {

temp = new OkHttp3Utils(context);

mInstance = temp;

}

}

}

return temp;

}

/**

* 设置请求头

*

* @param headersParams

* @return

*/

private Headers SetHeaders(Map headersParams) {

Headers headers = null;

Headers.Builder headersbuilder = new Headers.Builder();

if (headersParams != null) {

Iterator iterator = headersParams.keySet().iterator();

String key = "";

while (iterator.hasNext()) {

key = iterator.next().toString();

headersbuilder.add(key, headersParams.get(key));

}

}

headers = headersbuilder.build();

return headers;

}

/**

* post请求参数

*

* @param BodyParams

* @return

*/

private RequestBody SetPostRequestBody(Map BodyParams) {

RequestBody body = null;

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

if (BodyParams != null) {

Iterator iterator = BodyParams.keySet().iterator();

String key = "";

while (iterator.hasNext()) {

key = iterator.next().toString();

formEncodingBuilder.add(key, BodyParams.get(key));

}

}

body = formEncodingBuilder.build();

return body;

}

/**

* Post上传图片的参数

*

* @param BodyParams

* @param fileParams

* @return

*/

private RequestBody SetFileRequestBody(Map BodyParams, Map filePathParams) {

// 带文件的Post参数

RequestBody body = null;

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

MultipartBodyBuilder.setType(MultipartBody.FORM);

RequestBody fileBody = null;

if (BodyParams != null) {

Iterator iterator = BodyParams.keySet().iterator();

String key = "";

while (iterator.hasNext()) {

key = iterator.next().toString();

MultipartBodyBuilder.addFormDataPart(key, BodyParams.get(key));

}

}

if (filePathParams != null) {

Iterator iterator = filePathParams.keySet().iterator();

String key = "";

int i = 0;

while (iterator.hasNext()) {

key = iterator.next().toString();

i++;

MultipartBodyBuilder.addFormDataPart(key, filePathParams.get(key));

fileBody = RequestBody.create(MEDIA_TYPE_PNG, new File(filePathParams.get(key)));

MultipartBodyBuilder.addFormDataPart(key, i + ".png", fileBody);

}

}

body = MultipartBodyBuilder.build();

return body;

}

/**

* get方法连接拼加参数

*

* @param mapParams

* @return

*/

private String setGetUrlParams(Map mapParams) {

String strParams = "";

if (mapParams != null) {

Iterator iterator = mapParams.keySet().iterator();

String key = "";

while (iterator.hasNext()) {

key = iterator.next().toString();

strParams += "&" + key + "=" + mapParams.get(key);

}

}

return strParams;

}

/**

* 实现post请求

*

* @param reqUrl

* @param headersParams

* @param params

* @param callback

*/

public void doPost(String reqUrl, Map headersParams, Map params, final NetCallback callback) {

Request.Builder RequestBuilder = new Request.Builder();

RequestBuilder.url(reqUrl);// 添加URL地址

RequestBuilder.method("POST", SetPostRequestBody(params));

RequestBuilder.headers(SetHeaders(headersParams));// 添加请求头

Request request = RequestBuilder.build();

mOkHttpClient.newCall(request).enqueue(new Callback() {

@Override

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

mHandler.post(new Runnable() {

@Override

public void run() {

callback.onSuccess(0, response.body().toString());

call.cancel();

}

});

}

@Override

public void onFailure(final Call call, final IOException exception) {

mHandler.post(new Runnable() {

@Override

public void run() {

callback.onFailure(-1, exception.getMessage());

call.cancel();

}

});

}

});

}

/**

* 实现get请求

*

* @param reqUrl

* @param headersParams

* @param params

* @param callback

*/

public void doGet(String reqUrl, Map headersParams, Map params, final NetCallback callback) {

Request.Builder RequestBuilder = new Request.Builder();

RequestBuilder.url(reqUrl + setGetUrlParams(params));// 添加URL地址 自行加 ?

RequestBuilder.headers(SetHeaders(headersParams));// 添加请求头

Request request = RequestBuilder.build();

mOkHttpClient.newCall(request).enqueue(new Callback() {

@Override

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

mHandler.post(new Runnable() {

@Override

public void run() {

callback.onSuccess(0, response.body().toString());

call.cancel();

}

});

}

@Override

public void onFailure(final Call call, final IOException exception) {

mHandler.post(new Runnable() {

@Override

public void run() {

callback.onFailure(-1, exception.getMessage());

call.cancel();

}

});

}

});

}

/**

* 实现加载图片

*

* @param context

* @param reqUrl

* @param headersParams

* @param imageView

* @param defResImag imageView.setImageResource(context.getResources().getIdentifier(defResImag, "drawable", context.getPackageName()));

*/

public void loadImage(final Context context, final String reqUrl, Map headersParams, final ImageView imageView, final String defResImag) {

Bitmap result;

// 从内存缓存中获取图片

final ImageMemoryCache memoryCache = new ImageMemoryCache(context);

result = memoryCache.getBitmapFromCache(reqUrl);

if (result != null) {

imageView.setImageBitmap(result);

return;

}

// 从硬盘缓存中获取图片

final ImageFileCache fileCache = new ImageFileCache(context);

result = fileCache.getImage(context, reqUrl);

if (result != null) {

imageView.setImageBitmap(result);

// 添加到内存缓存

memoryCache.addBitmapToCache(reqUrl, result);

return;

}

Request.Builder RequestBuilder = new Request.Builder();

RequestBuilder.url(reqUrl);// 添加URL地址

// RequestBuilder.headers(SetHeaders(headersParams));// 添加请求头

Request request = RequestBuilder.build();

mOkHttpClient.newCall(request).enqueue(new Callback() {

@Override

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

byte[] bytes = response.body().bytes();

final Bitmap decodeStream = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);

mHandler.post(new Runnable() {

@Override

public void run() {

try {

if (decodeStream != null) {

imageView.setImageBitmap(decodeStream);

// 缓存在文件

fileCache.saveBitmap(context, decodeStream, reqUrl);

// 缓存在内存

memoryCache.addBitmapToCache(reqUrl, decodeStream);

} else {

// 加载图片

imageView.setImageResource(context.getResources().getIdentifier(defResImag, "drawable", context.getPackageName()));

}

} catch (Exception e) {

e.printStackTrace();

} finally {

call.cancel();

}

}

});

}

@Override

public void onFailure(final Call call, final IOException exception) {

mHandler.post(new Runnable() {

@Override

public void run() {

// 加载图片

imageView.setImageResource(context.getResources().getIdentifier(defResImag, "drawable", context.getPackageName()));

call.cancel();

}

});

}

});

}

public abstract class NetCallback {

public abstract void onFailure(int code, String msg);

public abstract void onSuccess(int code, String content);

public abstract void loadImage(Bitmap bitmap);

}

}

public class ImageMemoryCache {

/**

* 从内存读取数据速度是最快的,为了更大限度使用内存,这里使用了两层缓存。 硬引用缓存不会轻易被回收,用来保存常用数据,不常用的转入软引用缓存。

*/

private static final int SOFT_CACHE_SIZE = 15; // 软引用缓存容量

private static LruCache mLruCache; // 硬引用缓存

private static LinkedHashMap> mSoftCache; // 软引用缓存

public ImageMemoryCache(Context context) {

int memClass = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();

int cacheSize = 1024 * 1024 * memClass / 4; // 硬引用缓存容量,为系统可用内存的1/4

mLruCache = new LruCache(cacheSize) {

@Override

protected int sizeOf(String key, Bitmap value) {

if (value != null)

return value.getRowBytes() * value.getHeight();

else

return 0;

}

@Override

protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {

if (oldValue != null)

// 硬引用缓存容量满的时候,会根据LRU算法把最近没有被使用的图片转入此软引用缓存

mSoftCache.put(key, new SoftReference(oldValue));

}

};

mSoftCache = new LinkedHashMap>(SOFT_CACHE_SIZE, 0.75f, true) {

private static final long serialVersionUID = 6040103833179403725L;

@Override

protected boolean removeEldestEntry(Entry> eldest) {

if (size() > SOFT_CACHE_SIZE) {

return true;

}

return false;

}

};

}

/**

* 从缓存中获取图片

*/

public Bitmap getBitmapFromCache(String url) {

Bitmap bitmap;

// 先从硬引用缓存中获取

synchronized (mLruCache) {

bitmap = mLruCache.get(url);

if (bitmap != null) {

// 如果找到的话,把元素移到LinkedHashMap的最前面,从而保证在LRU算法中是最后被删除

mLruCache.remove(url);

mLruCache.put(url, bitmap);

return bitmap;

}

}

// 如果硬引用缓存中找不到,到软引用缓存中找

synchronized (mSoftCache) {

SoftReference bitmapReference = mSoftCache.get(url);

if (bitmapReference != null) {

bitmap = bitmapReference.get();

if (bitmap != null) {

// 将图片移回硬缓存

mLruCache.put(url, bitmap);

mSoftCache.remove(url);

return bitmap;

} else {

mSoftCache.remove(url);

}

}

}

return null;

}

/**

* 添加图片到缓存

*/

public void addBitmapToCache(String url, Bitmap bitmap) {

if (bitmap != null) {

synchronized (mLruCache) {

mLruCache.put(url, bitmap);

}

}

}

public void clearCache() {

mSoftCache.clear();

}

}

public class ImageFileCache {

private static final String CACHDIR = ".ImgCache";

private static final String WHOLESALE_CONV = ".cache";

private static final int MB = 1024 * 1024;

private static final int CACHE_SIZE = 10;

private static final int FREE_SD_SPACE_NEEDED_TO_CACHE = 10;

public ImageFileCache(Context ctx) {

// 清理文件缓存

removeCache(ctx,getDirectory(ctx));

}

/** 从缓存中获取图片 **/

public Bitmap getImage(Context ctx, final String url) {

final String path = getDirectory(ctx) + "/" + convertUrlToFileName(url);

File file = new File(path);

if (file.exists()) {

Bitmap bmp = BitmapFactory.decodeFile(path);

if (bmp == null) {

file.delete();

} else {

updateFileTime(path);

return bmp;

}

}

return null;

}

/** 将图片存入文件缓存 **/

public void saveBitmap(Context ctx, Bitmap bm, String url) {

if (bm == null) {

return;

}

// 判断sdcard上的空间

if (FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd(ctx)) {

// SD空间不足

return;

}

String filename = convertUrlToFileName(url);

String dir = getDirectory(ctx);

File dirFile = new File(dir);

if (!dirFile.exists())

dirFile.mkdirs();

File file = new File(dir + "/" + filename);

try {

file.createNewFile();

OutputStream outStream = new FileOutputStream(file);

bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);

outStream.flush();

outStream.close();

} catch (FileNotFoundException e) {

Log.w("ImageFileCache", "FileNotFoundException");

} catch (IOException e) {

Log.w("ImageFileCache", "IOException");

}

}

/**

* 计算存储目录下的文件大小,

* 当文件总大小大于规定的CACHE_SIZE或者sdcard剩余空间小于FREE_SD_SPACE_NEEDED_TO_CACHE的规定

* 那么删除40%最近没有被使用的文件

*/

private boolean removeCache(Context ctx,String dirPath) {

File dir = new File(dirPath);

File[] files = dir.listFiles();

if (files == null) {

return true;

}

//if (!android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {

//return false;

//}

int dirSize = 0;

for (int i = 0; i < files.length; i++) {

if (files[i].getName().contains(WHOLESALE_CONV)) {

dirSize += files[i].length();

}

}

if (dirSize > CACHE_SIZE * MB || FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd(ctx)) {

int removeFactor = (int) ((0.4 * files.length) + 1);

Arrays.sort(files, new FileLastModifSort());

for (int i = 0; i < removeFactor; i++) {

if (files[i].getName().contains(WHOLESALE_CONV)) {

files[i].delete();

}

}

}

if (freeSpaceOnSd(ctx) <= CACHE_SIZE) {

return false;

}

return true;

}

/** 修改文件的最后修改时间 **/

public void updateFileTime(String path) {

File file = new File(path);

long newModifiedTime = System.currentTimeMillis();

file.setLastModified(newModifiedTime);

}

/** 计算sdcard上的剩余空间 **/

private int freeSpaceOnSd(Context ctx) {

StatFs stat = new StatFs(getCachePath(ctx));

double sdFreeMB = ((double) stat.getAvailableBlocks() * (double) stat.getBlockSize()) / MB;

return (int) sdFreeMB;

}

/** 将url转成文件名 **/

private String convertUrlToFileName(String url) {

String[] strs = url.split("/");

return strs[strs.length - 1] + WHOLESALE_CONV;

}

/** 获得缓存目录 **/

private String getDirectory(Context ctx) {

String dir = getCachePath(ctx);

return dir;

}

/** 取SD卡路径 **/

private String getSDPath() {

File sdDir = null;

boolean sdCardExist = Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED); // 判断sd卡是否存在

if (sdCardExist) {

sdDir = Environment.getExternalStorageDirectory(); // 获取根目录

}

if (sdDir != null) {

return sdDir.toString();

} else {

return null;

}

}

private String getCachePath(Context ctx) {

String sdCardPath = getSDPath();

if (sdCardPath != null) {

return sdCardPath + File.separator + "Android" + File.separator + "data" + File.separator + ctx.getPackageName() + File.separator + CACHDIR;

}

return ctx.getFilesDir().getAbsolutePath() + File.separator + CACHDIR;

}

/**

* 根据文件的最后修改时间进行排序

*/

private class FileLastModifSort implements Comparator {

public int compare(File arg0, File arg1) {

if (arg0.lastModified() > arg1.lastModified()) {

return 1;

} else if (arg0.lastModified() == arg1.lastModified()) {

return 0;

} else {

return -1;

}

}

}

}

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐