文章內容概要:
- 框架需要解決的問題,及思路;
- 具體實施。
說明
okHttp是一款實用高效,使用簡單的網絡模塊實現,雖然使用簡單,但要在項目中使用還是得進行簡單的封裝,不可能每次請求都去寫十幾,甚至幾十行相同的代碼,這樣是相當低效的,說這麼多都算是廢話。
來看看本次封裝我想要達到的效果:
1. 調用起來要簡單,我可以選擇請求方式:getAsyn、getSync、post、fileUpload、fileDownload、displayImage。調用者只提供請求url,請求參數。至於內部如何發起請求,肯定是調用者所不關心的。
2. 返回值是調用者所關心的,調用成功或失敗是調用者關心的,成功後我可以拿到返回結果,調用失敗我可以選擇是否處理,或者我不處理的時候可以默認提示請求失敗。像顯示圖片這種請求,請求完後希望能直接更新UI。當然也可以選擇顯示完後進行回調。反正一句話,調用者想做什麼都能做,什麼都不做的時候程序不會出錯。
實現
首先想到下面第一種方法。
1.在okHttp幾大方法已經封裝在一個思HttpUtil的類裏,而且假設都是靜態方法。這裏在Activity中只需要調用譬如,HttpUtil.getAsyn(url,param);類似這樣的調用即可,看起來調用還是挺方便的。來看返回,返回有成功和失敗兩種情況,okHttp本身提供了Callback接口,我們是否可以實現這個接口就可以拿到返回了,於是調用就成這樣了
HttpUtil.getAsyn(url,param,new Callback() {
@Override
public void onFailure(Request request, IOException e) {
}
@Override
public void onResponse(final Response response) throws IOException {
}
});
但是這樣有一個問題,就是我調用方法的時候,我必須去實現這個接口,如果我不想去關心返回結果,那我還要去實現這個接口就太不友好了。那如果你不關心,大不了Activity實現這個接口,實現兩個空方法,調用方法就變成了
HttpUtil.getAsyn(url,param,this);//this指的是Activity,必須實現Callback接口。
這樣看起來是比匿名內部類簡潔一點。如果實在不願意去實現接口,那大不了HttpUtil多重載一個方法出來,不要求傳Callback實現就行了。這也不失爲一種解決辦法。呵呵,這是我寫之前沒有想到的,似乎這麼簡單封裝就能達到我們的要求了。
HttpUtil.getAsyn(url,param);//不關心返回時調用。
下面把我的封裝說一下,用的java三大特性:封閉、繼承、多態。呵呵,瞬間高大上了。
給所有 Activity 創建了一個父類:BaseActivity,父類中定義了一個屬性:HttpUtil(非靜態),在父類OnCreate中初始化HttpUtil。HttpUtil中保有BaseActivity的引用。
//BaseActivity部分代碼
public abstract class BaseActivity extends Activity {
public static final String TAG = BaseActivity.class.getSimpleName();
protected Handler mHandler = null;
public BaseUtil baseUtil;
public HttpUtil httpUtil;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
baseUtil = new BaseUtil(this);
//初始化httpUtil,並將this引用作爲參數
httpUtil = new HttpUtil(this);
//初始化mHandler,用於子線程向主線程發消息
initHandler();
}
//實現了一個http請求返回調用的空方法
protected void httpResponse(String url, Map<String, Object> params, Object result) {
}
//文件下載完成後回調,空方法
protected void completeDownload(String abstractPath) {
}
////請求出錯回調,默認提示網絡請求失敗
void httpError(String url, Map<String, Object> params) {
mHandler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(BaseActivity.this, "網絡請求失敗", 300).show();
}
});
}
.
.
.
}
//HttpUtil部分代碼,這裏也並非面對真正的okHttp封裝,而在之上又包了一層。
//邊寫邊想的時候發現這一層如果拿掉也不是不可以,但這樣至少我們直接面對的代碼是比較簡潔的。
public class HttpUtil {
private BaseActivity activity;
public HttpUtil(BaseActivity activity) {
this.activity = activity;
}
public Map<String, Object> getSyncHttp(String url) {
try {
Response response = OkHttpEngine.getInstance().getSyncHttp(activity, url);
Map<String, Object> result = new HashMap<>();
return result;
} catch (IOException e) {
return null;
}
}
.
.
.
}
進行了這兩層封裝,請求的返回方法已經被BaseActivity實現,子類Activity如果不關心,完全不用實現任何接口,請求之後的事情完全可以由BaseActivity消化吸收。若需要對返回值進行處理,子類實現httpResponse()方法即可。
Activity中調用網絡請求方法:
public void httpTest(){
this.httpUtil.getAsynHttp("https://www.baidu.com", p1);
ImageView view = findView(R.id.imageview);
// 加載圖片
this.httpUtil.displayImage(mHandler, view, "https://www.baidu.com/img/bd_logo1.png", R.drawable.no_image);
String p = MyApplication.mkdirs("/net_image/a/b");
//下載文件保存到sdcard/net_image/a/b文件夾下。
this.httpUtil.downloadFile("http://a4.att.hudong.com/23/09/01300000165488122547095974400.jpg", p);
}
直接上代碼了。來一張代碼結構圖
從上到下
BaseActivity.java
創建了mHandler,保證瞭如果子類不創建handler時,子類調用http請求後,父類可以代爲處理響應,更新UI,顯示提示信息等。
創建了httpUtil,將父類的引用傳遞到httpUtil中,請求返回後,直接調用響應成功或失敗方法,如果子類實現了響應方法,調用會直達子類實現,這就是繼承時多態。
實現了響應回調方法,若子類未實現時,父類可以代爲處理。
package com.mydemo.common;
import java.util.Map;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Toast;
public abstract class BaseActivity extends Activity {
public static final String TAG = BaseActivity.class.getSimpleName();
protected Handler mHandler = null;
public BaseUtil baseUtil;
public HttpUtil httpUtil;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
baseUtil = new BaseUtil(this);
httpUtil = new HttpUtil(this);
initHandler();
}
protected void initHandler() {
mHandler = new Handler();
}
public <T> T findView(int id) {
View view = findViewById(id);
if (view == null || view.toString().equals("")) {
return null;
}
return (T) view;
}
/**
* 通過類名啓動Activity
*
* @param pClass
*/
protected void openActivity(Class<?> pClass) {
openActivity(pClass, null);
}
/**
* 通過類名啓動Activity,並且含有Bundle數據
*
* @param pClass
* @param pBundle
*/
protected void openActivity(Class<?> pClass, Bundle pBundle) {
Intent intent = new Intent(this, pClass);
if (pBundle != null) {
intent.putExtras(pBundle);
}
startActivity(intent);
}
/**
* 通過Action啓動Activity
*
* @param pAction
*/
protected void openActivity(String pAction) {
openActivity(pAction, null);
}
/**
* 通過Action啓動Activity,並且含有Bundle數據
*
* @param pAction
* @param pBundle
*/
protected void openActivity(String pAction, Bundle pBundle) {
Intent intent = new Intent(pAction);
if (pBundle != null) {
intent.putExtras(pBundle);
}
startActivity(intent);
}
protected void httpResponse(String url, Map<String, Object> params, Object result) {
}
protected void completeDownload(String abstractPath) {
}
protected void httpError(String url, Map<String, Object> params, final Exception e) {
mHandler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(BaseActivity.this, "網絡請求失敗:" + e.getMessage(), 4000).show();
}
});
}
void httpError(String url, Map<String, Object> params) {
mHandler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(BaseActivity.this, "網絡請求失敗", 300).show();
}
});
}
}
BaseUtil
這個類是工具類,一併承上,非本人原創。
package com.mydemo.common;
import java.util.Locale;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.telephony.TelephonyManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.Toast;
public class BaseUtil {
private Context context;
protected InputMethodManager imm;
private TelephonyManager tManager;
public BaseUtil(Context context) {
this.context = context;
tManager = (TelephonyManager) context.getSystemService(context.TELEPHONY_SERVICE);
imm = (InputMethodManager) context.getSystemService(context.INPUT_METHOD_SERVICE);
}
public void DisPlay(String content) {
Toast.makeText(context, content, 1).show();
}
public void DisplayToast(String str) {
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
}
public void hideOrShowSoftInput(boolean isShowSoft, EditText editText) {
if (isShowSoft) {
imm.showSoftInput(editText, 0);
} else {
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
}
}
// 獲得當前程序版本信息
public String getVersionName() throws Exception {
// 獲取packagemanager的實例
PackageManager packageManager = context.getPackageManager();
// getPackageName()是你當前類的包名,0代表是獲取版本信息
PackageInfo packInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
return packInfo.versionName;
}
// 獲得設備信息
public String getDeviceId() throws Exception {
String deviceId = tManager.getDeviceId();
return deviceId;
}
/**
* 獲取SIM卡序列號
*
* @return
*/
public String getToken() {
return tManager.getSimSerialNumber();
}
/* 獲得系統版本 */
public String getClientOs() {
return android.os.Build.ID;
}
/* 獲得系統版本號 */
public String getClientOsVer() {
return android.os.Build.VERSION.RELEASE;
}
// 獲得系統語言包
public String getLanguage() {
return Locale.getDefault().getLanguage();
}
public String getCountry() {
return Locale.getDefault().getCountry();
}
}
HttpUtil
該類在BaseActivity中創建,並且保存BaseActivity對象引用。
1.使得調用都不需要將自身作爲參數進行傳遞,減小了調用複雜度,
2.使得OkHttpEngine不需要BaseActivity進行綁定,使OkHttpEngine作爲完全獨立的存在。
package com.mydemo.common;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import android.os.Handler;
import android.widget.ImageView;
import com.squareup.okhttp.Response;
public class HttpUtil {
private BaseActivity activity;
public HttpUtil(BaseActivity activity) {
this.activity = activity;
}
public void getAsynHttp(String url, Map<String, Object> params) {
OkHttpEngine.getInstance().getAsynHttp(activity, url);
}
public Map<String, Object> getSyncHttp(String url) {
try {
Response response = OkHttpEngine.getInstance().getSyncHttp(activity, url);
Map<String, Object> result = new HashMap<>();
return result;
} catch (IOException e) {
return null;
}
}
public void post(String url, Map<String, Object> params) {
OkHttpEngine.getInstance().postAsynHttp(activity, url, params);
}
public void downloadFile(final String url, final String destFileDir) {
OkHttpEngine.getInstance().downloadFile(activity, url, destFileDir);
}
public void displayImage(final Handler mHandler, final ImageView view, final String imgUrl, final int errorResId) {
OkHttpEngine.getInstance().displayImage(mHandler, view, imgUrl, errorResId);
}
public void fileUpload(final String url, final Map<String, Object> params, File[] files, String[] fileKeys) {
OkHttpEngine.getInstance().fileUpload(activity, url, params, files, fileKeys);
}
}
ImageUtil
與圖片處理相關工具類,非本人原創,一併承上。
package com.mydemo.common;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.lang.reflect.Field;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
/**
*/
public class ImageUtils {
/**
* 根據InputStream獲取圖片實際的寬度和高度
*/
public static ImageSize getImageSize(InputStream imageStream) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(imageStream, null, options);
return new ImageSize(options.outWidth, options.outHeight);
}
public static class ImageSize {
int width;
int height;
public ImageSize() {
}
public ImageSize(int width, int height) {
this.width = width;
this.height = height;
}
@Override
public String toString() {
return "ImageSize{" + "width=" + width + ", height=" + height + '}';
}
}
public static int calculateInSampleSize(ImageSize srcSize, ImageSize targetSize) {
// 源圖片的寬度
int width = srcSize.width;
int height = srcSize.height;
int inSampleSize = 1;
int reqWidth = targetSize.width;
int reqHeight = targetSize.height;
if (width > reqWidth && height > reqHeight) {
// 計算出實際寬度和目標寬度的比率
int widthRatio = Math.round((float) width / (float) reqWidth);
int heightRatio = Math.round((float) height / (float) reqHeight);
inSampleSize = Math.max(widthRatio, heightRatio);
}
return inSampleSize;
}
/**
* 根據ImageView獲適當的壓縮的寬和高
*/
public static ImageSize getImageViewSize(View view) {
ImageSize imageSize = new ImageSize();
imageSize.width = getExpectWidth(view);
imageSize.height = getExpectHeight(view);
return imageSize;
}
/**
* 根據view獲得期望的高度
*/
private static int getExpectHeight(View view) {
int height = 0;
if (view == null) return 0;
final ViewGroup.LayoutParams params = view.getLayoutParams();
// 如果是WRAP_CONTENT,此時圖片還沒加載,getWidth根本無效
if (params != null && params.height != ViewGroup.LayoutParams.WRAP_CONTENT) {
height = view.getWidth(); // 獲得實際的寬度
}
if (height <= 0 && params != null) {
height = params.height; // 獲得佈局文件中的聲明的寬度
}
if (height <= 0) {
height = getImageViewFieldValue(view, "mMaxHeight");// 獲得設置的最大的寬度
}
// 如果寬度還是沒有獲取到,憋大招,使用屏幕的寬度
if (height <= 0) {
DisplayMetrics displayMetrics = view.getContext().getResources().getDisplayMetrics();
height = displayMetrics.heightPixels;
}
return height;
}
/**
* 根據view獲得期望的寬度
*/
private static int getExpectWidth(View view) {
int width = 0;
if (view == null) return 0;
final ViewGroup.LayoutParams params = view.getLayoutParams();
// 如果是WRAP_CONTENT,此時圖片還沒加載,getWidth根本無效
if (params != null && params.width != ViewGroup.LayoutParams.WRAP_CONTENT) {
width = view.getWidth(); // 獲得實際的寬度
}
if (width <= 0 && params != null) {
width = params.width; // 獲得佈局文件中的聲明的寬度
}
if (width <= 0)
{
width = getImageViewFieldValue(view, "mMaxWidth");// 獲得設置的最大的寬度
}
// 如果寬度還是沒有獲取到,憋大招,使用屏幕的寬度
if (width <= 0)
{
DisplayMetrics displayMetrics = view.getContext().getResources().getDisplayMetrics();
width = displayMetrics.widthPixels;
}
return width;
}
/**
* 通過反射獲取imageview的某個屬性值
*/
private static int getImageViewFieldValue(Object object, String fieldName) {
int value = 0;
try {
Field field = ImageView.class.getDeclaredField(fieldName);
field.setAccessible(true);
int fieldValue = field.getInt(object);
if (fieldValue > 0 && fieldValue < Integer.MAX_VALUE) {
value = fieldValue;
}
} catch (Exception e) {
}
return value;
}
public static Bitmap getLoacalBitmap(String url) {
try {
FileInputStream fis = new FileInputStream(url);
return BitmapFactory.decodeStream(fis);
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
}
}
okHttp封裝
說明,這裏方法調用裏,使用BaseActivity作爲參數,可能不是最好的方法,可以考慮使用實現了接口,可能更爲妥當。本次暫不深究了。
package com.mydemo.common;
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.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.widget.ImageView;
import com.squareup.okhttp.Cache;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.Headers;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.MultipartBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;
public class OkHttpEngine {
private static OkHttpEngine okHttpEngine;
private OkHttpClient mOkHttpClient;
public static synchronized void initEngine() {
okHttpEngine = new OkHttpEngine();
}
public static OkHttpEngine getInstance() {
if (okHttpEngine == null) {
initEngine();
}
return okHttpEngine;
}
private OkHttpEngine() {
mOkHttpClient = new OkHttpClient();
mOkHttpClient.setConnectTimeout(15, TimeUnit.SECONDS);
mOkHttpClient.setWriteTimeout(20, TimeUnit.SECONDS);
mOkHttpClient.setReadTimeout(20, TimeUnit.SECONDS);
}
public OkHttpEngine setCache(Context mContext) {
File sdcache = mContext.getExternalCacheDir();
int cacheSize = 10 * 1024 * 1024;
mOkHttpClient.setCache(new Cache(sdcache.getAbsoluteFile(), cacheSize));
return okHttpEngine;
}
/**
* @param currentActivity
* 當前活動的activity對象
* @param url
* 請求地址
* @param params
* 參數
*/
public void getAsynHttp(final BaseActivity currentActivity, final String url) {
final Request request = new Request.Builder().url(url).build();
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
}
@Override
public void onResponse(final Response response) throws IOException {
String str = response.body().string();
currentActivity.httpResponse(url, null, str);
}
});
}
public Response getSyncHttp(final BaseActivity currentActivity, final String url) throws IOException {
// OkHttpClient mOkHttpClient = new OkHttpClient();
final Request request = new Request.Builder().url(url).build();
Call call = mOkHttpClient.newCall(request);
Response mResponse = call.execute();
if (mResponse.isSuccessful()) {
currentActivity.httpResponse(url, null, mResponse.body().string());
return mResponse;
} else {
currentActivity.httpError(url, null);
}
return null;
}
public void postAsynHttp(final BaseActivity currentActivity, final String url, final Map<String, Object> params) {
// OkHttpClient mOkHttpClient = new OkHttpClient();
FormEncodingBuilder builer = _getFormBuilder(params);
Request request = new Request.Builder().url(url).post(builer.build()).build();
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
currentActivity.httpError(url, params);
}
@Override
public void onResponse(Response response) throws IOException {
currentActivity.httpResponse(url, params, response.body().string());
}
});
}
public void fileUpload(final BaseActivity currentActivity, final String url, final Map<String, Object> params, File[] files, String[] fileKeys) {
Request request = buildMultipartFormRequest(url, files, fileKeys, params);
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
currentActivity.httpError(url, params);
}
@Override
public void onResponse(Response response) throws IOException {
String str = response.body().string();
currentActivity.httpResponse(url, params, response.body().string());
}
});
}
/**
* 下載文件,返回文件絕對路徑
*
* @param currentActivity
* @param url
* 文件網絡地址
* @param destFileDir
* 文件存儲位置
*/
public void downloadFile(final BaseActivity currentActivity, final String url, final String destFileDir) {
final Request request = new Request.Builder().url(url).build();
final Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(final Request request, final IOException e) {
currentActivity.httpError(url, new HashMap<String, Object>());
}
@Override
public void onResponse(Response response) {
InputStream is = null;
byte[] buf = new byte[2048];
int len = 0;
FileOutputStream fos = null;
try {
is = response.body().byteStream();
File file = new File(destFileDir, getFileName(url));
fos = new FileOutputStream(file);
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fos.flush();
Map<String, Object> params = new HashMap<String, Object>();
currentActivity.completeDownload(file.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
currentActivity.httpError(url, new HashMap<String, Object>(), e);
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {
}
try {
if (fos != null)
fos.close();
} catch (IOException e) {
}
}
}
});
}
public void displayImage(final Handler mHandler, final ImageView view, final String imgUrl, final int errorResId) {
final Request request = new Request.Builder().url(imgUrl).build();
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
mHandler.post(new Runnable() {
@Override
public void run() {
view.setImageResource(errorResId);
}
});
}
@Override
public void onResponse(Response response) {
InputStream is = null;
try {
is = response.body().byteStream();
ImageUtils.ImageSize actualImageSize = ImageUtils.getImageSize(is);
ImageUtils.ImageSize imageViewSize = ImageUtils.getImageViewSize(view);
int inSampleSize = ImageUtils.calculateInSampleSize(actualImageSize, imageViewSize);
try {
is.reset();
} catch (IOException e) {
response = _getAsyn(imgUrl);
is = response.body().byteStream();
}
BitmapFactory.Options ops = new BitmapFactory.Options();
ops.inJustDecodeBounds = false;
ops.inSampleSize = inSampleSize;
final Bitmap bm = BitmapFactory.decodeStream(is, null, ops);
mHandler.post(new Runnable() {
@Override
public void run() {
view.setImageBitmap(bm);
}
});
} catch (Exception e) {
setErrorResId(mHandler, view, errorResId);
} finally {
if (is != null)
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
}
/**
* 同步的Get請求
*
* @param url
* @return Response
*/
private Response _getAsyn(String url) throws IOException {
final Request request = new Request.Builder().url(url).build();
Call call = mOkHttpClient.newCall(request);
Response execute = call.execute();
return execute;
}
private FormEncodingBuilder _getFormBuilder(Map<String, Object> params) {
FormEncodingBuilder builder = new FormEncodingBuilder();
if (params != null && params.size() > 0) {
Set<Entry<String, Object>> set = params.entrySet();
Iterator<Entry<String, Object>> iterator = set.iterator();
while (iterator.hasNext()) {
Entry<String, Object> entry = iterator.next();
builder.add(entry.getKey(), entry.getValue().toString());
}
}
return builder;
}
private Request buildMultipartFormRequest(String url, File[] files, String[] fileKeys, final Map<String, Object> params) {
MultipartBuilder builder = new MultipartBuilder().type(MultipartBuilder.FORM);
if (params != null && params.size() > 0) {
Set<Entry<String, Object>> set = params.entrySet();
Iterator<Entry<String, Object>> iterator = set.iterator();
while (iterator.hasNext()) {
Entry<String, Object> entry = iterator.next();
builder.addPart(Headers.of(String.format("Content-Disposition", "form-data; name=\"%s\"", entry.getKey())), RequestBody.create(null, entry.getValue().toString()));
}
}
if (files != null) {
RequestBody fileBody = null;
for (int i = 0; i < files.length; i++) {
File file = files[i];
String fileName = file.getName();
fileBody = RequestBody.create(MediaType.parse(guessMimeType(fileName)), file);
// TODO 根據文件名設置contentType
builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + fileKeys[i] + "\"; filename=\"" + fileName + "\""), fileBody);
}
}
RequestBody requestBody = builder.build();
return new Request.Builder().url(url).post(requestBody).build();
}
private String guessMimeType(String path) {
FileNameMap fileNameMap = URLConnection.getFileNameMap();
String contentTypeFor = fileNameMap.getContentTypeFor(path);
if (contentTypeFor == null) {
contentTypeFor = "application/octet-stream";
}
return contentTypeFor;
}
private String getFileName(String path) {
int separatorIndex = path.lastIndexOf("/");
return (separatorIndex < 0) ? path : path.substring(separatorIndex + 1, path.length());
}
private void setErrorResId(final Handler mHandler, final ImageView view, final int errorResId) {
mHandler.post(new Runnable() {
@Override
public void run() {
view.setImageResource(errorResId);
}
});
}
}
MainActivity
package com.mydemo.ui;
import java.util.HashMap;
import java.util.Map;
import com.mydemo.MyApplication;
import com.mydemo.common.BaseActivity;
import com.mydemo.common.ImageUtils;
import com.mydemo.okhttp.R;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;
import android.widget.TextView;
public class MainActivity extends BaseActivity {
private final String BAIDU_INDEX1 = "http://www.baidu.com";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new Handler(getMainLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
break;
}
}
};
Map<String, Object> p1 = new HashMap<String, Object>();
this.httpUtil.getAsynHttp(BAIDU_INDEX1, p1);
// this.getAsynHttp(BAIDU_INDEX2, p1);
//
// this.getAsynHttp(BAIDU_INDEX3, p1);
// 要調用同步GET方法,但需要另起一個子線程發起請求,而不能直接在主線程發起請求。
/*
* Thread t = new Thread(new Runnable() {
* @Override
* public void run() {
* Map<String, Object> p1 = new HashMap<>();
* p1.put("s", System.currentTimeMillis());
* MainActivity.this.getSyncHttp(BAIDU_INDEX4, p1);
* }
* });
* t.start();
*/
this.httpUtil.getAsynHttp(BAIDU_INDEX1, p1);
ImageView view = findView(R.id.imageview);
// 加載圖片
this.httpUtil.displayImage(mHandler, view, "https://www.baidu.com/img/bd_logo1.png", R.drawable.no_image);
String p = MyApplication.mkdirs("/net_image/a/b");
this.httpUtil.downloadFile("http://a4.att.hudong.com/23/09/01300000165488122547095974400.jpg", p);
}
@Override
public void httpResponse(String url, Map<String, Object> params, Object result) {
Message msg = new Message();
switch (url) {
case BAIDU_INDEX1:
msg.what = 1;
msg.obj = result;
mHandler.sendMessage(msg);
break;
}
}
@Override
public void completeDownload(final String abstractPath) {
super.completeDownload(abstractPath);
mHandler.post(new Runnable() {
@Override
public void run() {
ImageView view5 = findView(R.id.imageview2);
view5.setImageBitmap(ImageUtils.getLoacalBitmap(abstractPath));
TextView view1 = findView(R.id.result5);
view1.setText("存儲位置:" + abstractPath);
}
});
}
@Override
protected void httpError(String url, Map<String, Object> params, final Exception e) {
mHandler.post(new Runnable() {
@Override
public void run() {
TextView view4 = findView(R.id.result5);
view4.setText(e.getMessage());
}
});
}
}
Application
package com.mydemo;
import java.io.File;
import android.app.Application;
import android.os.Environment;
public class MyApplication extends Application {
static MyApplication application = new MyApplication();
@Override
public void onCreate() {
super.onCreate();
}
private MyApplication() {
}
public static MyApplication getApplication() {
return application;
}
public static String getSDPath() {
File sdDir = null;
boolean sdCardExist = Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);// 判斷sd卡是否存在
if (sdCardExist) {
sdDir = Environment.getExternalStorageDirectory();// 獲取跟目錄
}
return sdDir.toString();
}
public static String mkdirs(String path) {
String sdcard = getSDPath();
if (path.indexOf(getSDPath()) == -1) {
path = sdcard + (path.indexOf("/") == 0 ? "" : "/") + path;
}
File destDir = new File(path);
if (!destDir.exists()) {
path = createDir(path);
if (path == null) {
return null;
}
}
return path;
}
//不限層級創建文件夾,
private static String createDir(String path) {
String sdPath = getSDPath();
String[] dirs = path.replace(sdPath, "").split("/");
StringBuffer filePath = new StringBuffer(sdPath);
for (String dir : dirs) {
if (!"".equals(dir) && !dir.equals(sdPath)) {
filePath.append("/").append(dir);
File destDir = new File(filePath.toString());
if (!destDir.exists()) {
boolean b = destDir.mkdirs();
if (!b) {
return null;
}
}
}
}
return filePath.toString();
}
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="20dp"
android:orientation="vertical" >
<TextView
android:id="@+id/result1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@string/hello_world" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="百度圖片是直接顯示的網絡圖片" />
<ImageView
android:id="@+id/imageview"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp"
android:contentDescription="網絡圖片" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="下面這張圖是下載在本地後,再加載顯示的" />
<TextView
android:id="@+id/result5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@string/hello_world" />
<ImageView
android:id="@+id/imageview2"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp"
android:contentDescription="網絡圖片" />
</LinearLayout>
原諒,代碼中註釋太少,以後一定改正。
gitHub地址,歡迎Star or Fork!
https://github.com/luodengzhong/okHttpDemo
原源碼奉上:
http://download.csdn.net/detail/ldz_wolf/9619513