OkHttp使用+檔案的上傳+斷點續傳
阿新 • • 發佈:2019-02-08
- 普通的Get請求
case R.id.get:
HttpManager.getInstance().getRequest(getUri,this);
break;
//方法的回撥
@Override
public void onFailure(Call call, IOException e) {//子執行緒
Log.d("flag", "----------------->onFailure: ");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
byte[] bytes = response.body().bytes();
Log.d("flag", "------>onResponse: 獲取圖片位元組長度: " +bytes.length);
final Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
runOnUiThread(new Runnable() {
@Override
public void run() {
mImageView.setImageBitmap(bitmap);
Log.d("flag", "------->run: 圖片載入成功");
}
});
}
為了方便呼叫請求,建立單例模式呼叫方法
public void getRequest(String url, Callback callback){
Request request = new Request.Builder()
.url(url)
.build();
mOkHttpClient.newCall(request ).enqueue(callback);
}
OkHttp是在子執行緒中,注意更新UI操作
- POST請求
public void postRequest(String url, RequestBody requestBody, Callback callback){
Request request = new Request.Builder()
.url(url)
.post(requestBody)//請求體,引數
.build();
mOkHttpClient.newCall(request).enqueue(callback);
}
case R.id.post:
RequestBody requestBody = new FormBody.Builder()
.add("name","michael")
.add("age","25")
.add("tel","666")
.build();
HttpManager.getInstance().postRequest(postUri,requestBody,this);
此處的回撥方法依舊是Get請求當中的載入圖片
- 檔案的上傳(post類似,新增請求體)
//上傳資料給伺服器
public void uploadImage(String url, RequestBody uploadBody, Callback callback) {
Request request = new Request.Builder()
.url(url)
.post(uploadBody)
.build();
mOkHttpClient.newCall(request).enqueue(callback);
}
addFormDataPart(請求體)
case upload://上傳資料給伺服器,也是post請求,post請求有請求體,將檔案包裹到請求體,進行上傳
//multipart/form-data 上傳檔案
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath()
+ File.separator + "icon.jpg";
File file = new File(path);
RequestBody body = RequestBody.create(MediaType.parse("image/*"),file);
RequestBody uploadBody = new MultipartBody.Builder()
.addFormDataPart("name","softpo")
.addFormDataPart("age","34")
.addFormDataPart("tel","0987654321")
.addFormDataPart("image","softpo.jpg",body)
.build();
HttpManager.getInstance().uploadImage(uploadUri,uploadBody, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d("flag", "----------------->onFailure: " +e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d("flag", "----------------->onResponse: " +response.body().string());
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "檔案上傳成功", Toast.LENGTH_SHORT).show();
}
});
}
});
break;
- 檔案的斷點續傳
核心:
1.請求網址計算內容的總長度
2.建立執行緒池的物件
3.分配執行緒的執行長度(開始和結束)
4.根據開始和結束-新增addHeader請求頭
5.根據Respose獲取輸入流,讀取寫入檔案
6.介面回撥,載入圖片
case R.id.download_range:
DownloadManager.getInstance().download(imageUrl,this);
break;
public class DownloadManager {
//執行緒池
public static final int MAX_SIZE = 2;
private ThreadPoolExecutor mThreadPoolExecutor = new ThreadPoolExecutor(
MAX_SIZE,
MAX_SIZE,
60,
TimeUnit.MILLISECONDS,
new SynchronousQueue<Runnable>(),//執行緒管理佇列
new ThreadFactory() {
AtomicInteger mAtomicInteger = new AtomicInteger();
@Override
public Thread newThread(Runnable r) {
//引數二區分執行緒
Thread thread =
new Thread(r,"Thread Number # "+mAtomicInteger.getAndIncrement());
return thread;
}
}
);
private static DownloadManager ourInstance = new DownloadManager();
public static DownloadManager getInstance() {
return ourInstance;
}
private DownloadManager() {
}
public void download(final String url, final Callback callback){
HttpManager.getInstance().getRequest(url, new okhttp3.Callback() {
@Override
public void onFailure(Call call, IOException e) {
callback.onFailure(e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//要下載內容的總長度
long contentLength = response.body().contentLength();
//多執行緒下載
processDownload(url,contentLength,callback);
}
});
}
private void processDownload(String url, long contentLength, Callback callback) {
int length = (int) (contentLength/MAX_SIZE);
for (int i = 0; i < MAX_SIZE; i++) {//執行兩次
int start = i*length;
//奇數:9 4.5 0-4 --- 4+
//偶數:10 5 0-4 --- 4+
int end = 0;
//奇數偶數(類似)
if(contentLength%2==1){
end = (i+1)*length;
}else {//偶數
end = (i+1)*length-1;
}
mThreadPoolExecutor.execute(new DownloadRunnable(url,start,end,callback));
}
}
}
根據迴圈每個執行緒去執行start和end
public class DownloadRunnable implements Runnable {
private String mUrl;
private int mStart;
private int mEnd;
private Callback mCallback;
public DownloadRunnable(String url, int start, int end, Callback callback) {
this.mUrl = url;
this.mStart = start;
this.mEnd = end;
this.mCallback = callback;
}
@Override
public void run() {//子執行緒
Response response = HttpManager.getInstance().asyncGetRangeBytes(mUrl, mStart, mEnd);
try {
InputStream is = response.body().byteStream();
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
.getAbsolutePath() + File.separator
+ mUrl.substring(mUrl.lastIndexOf("/") + 1);
File file = new File(path);
RandomAccessFile randomAccessFile = new RandomAccessFile(file,"rwd");//rwd:可讀可寫可追加
//!!!
randomAccessFile.seek(mStart);
//寫資料
int len = 0;
byte[] buf = new byte[1024*8];
while((len = is.read(buf))!=-1){
randomAccessFile.write(buf,0,len);
}
//回撥
mCallback.onSuccess(file);
} catch (IOException e) {
e.printStackTrace();
}
}
}
HttpManager中建立獲取RangeBytes的方法
public Response asyncGetRangeBytes(String imageUrl,int start,int end){
//斷點獲取伺服器的資料
Request request = new Request.Builder()
.url(imageUrl)
.addHeader("range","bytes="+start+"-"+end)//請求頭
.build();
//execute OkHttp執行聯網請求,下載資料
try {
return mOkHttpClient.newCall(request).execute();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
介面回撥,設定圖片
@Override
public void onFailure(String message) {
Log.d("flag", "----------------->onFailure: 多執行緒下載失敗");
}
@Override
public void onSuccess(File file) {
Log.d("flag", "----------------->onSuccess: 多執行緒下載圖片成功");
final Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
runOnUiThread(new Runnable() {
@Override
public void run() {
mImageView.setImageBitmap(bitmap);
}
});
}
所用的介面
public interface Callback {
void onFailure(String message);
void onSuccess(File file);
}
程式碼已經上傳: