OKhttp網路請求實戰(請求表單,上傳圖片,上傳多張圖片)
阿新 • • 發佈:2021-02-03
今天和大家分享一個okhttp網路請求的實戰案例,歡迎新手學生,大佬指點,話不多說直接上乾貨。
我是直接手動新增的架包,手動匯入,記住一定要匯入。新增依賴也可以哈,看個人愛好(要架包的私信或者留言,留郵箱,或者什麼我發給你們)
然後在新增依賴:(允許我裝個x用rxjava2了,載入圖片用的是glide,支援多張上傳圖片)
implementation 'io.reactivex.rxjava2:rxjava:2.2.19' implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' implementation 'com.github.bumptech.glide:glide:4.11.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0' implementation 'com.google.code.gson:gson:2.8.5'
最重要的一步來了,記住了 新增網路許可權:
!--相機許可權--> <uses-permission android:name="android.permission.CAMERA" /> <!--讀檔案許可權--> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!--使用特性--> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" /> <uses-permission android:name="android.permission.INTERNET" />
配置的都差不多準備完成了開始幹程式碼吧:用rxjava介面是要有的:
public interface MyNetWorkCallback<T> {
void onSuccess(T t);
void onError(int errorCode, String errorMsg);
}
繼續在上:
public interface IHttp { <T> void get(String url, MyNetWorkCallback<T> callback); <T> void get(String url, Map<String, String> params, MyNetWorkCallback<T> callback); <T> void get(String url, Map<String, String> params, Map<String, String> headers, MyNetWorkCallback<T> callback); <T> void post(String url, Map<String, String> params, MyNetWorkCallback<T> callback); void upload(String url, String path, Map<String, String> params, String fileType, MediaType MEDIA_TYPE, final MyNetWorkCallback<String> callback); void download(); void loadImage(String url, ImageView imageView); }
這個類幹啥來的忘記了,場時間不用了,但是也寫山了,你們可以不用
public class HttpFactroy {
public static IHttp create(){
return OkHttpUtils.getInstance();
}
}
主要的類來了,單例走起:
/**
* 基於OKhttp傳送網路請求
* Created by 2018/1/10.
*
* @Author King
* @Email [email protected]
*/
public class OkHttpUtils implements IHttp {
private OkHttpClient okHttpClient;
//建構函式私有化
private OkHttpUtils(){
okHttpClient = new OkHttpClient.Builder().build();
}
private static OkHttpUtils okHttpUtils;
//提供一個公共的、靜態的、返回值型別是當前本類的物件
public static OkHttpUtils getInstance(){
if(okHttpUtils == null){
synchronized (OkHttpUtils.class){
if(okHttpUtils == null) {
okHttpUtils = new OkHttpUtils();
}
}
}
return okHttpUtils;
}
@Override
public <T> void get(String url, MyNetWorkCallback<T> callback) {
}
/**
* 上傳多張圖片及引數
* @param reqUrl URL地址
* @param paramssa 引數
* @param pic_key 上傳圖片的關鍵字
*/
public Observable<String> sendMultipart(final String reqUrl, final Map<String, String> paramssa, final String pic_key, final List<File> filessa){
return Observable.create(new ObservableOnSubscribe<String>(){
@Override
public void subscribe(@NonNull ObservableEmitter<String> emitter) throws Exception {
MultipartBody.Builder multipartBodyBuilder = new MultipartBody.Builder();
multipartBodyBuilder.setType(MultipartBody.FORM);
//遍歷map中所有引數到builder
if (paramssa != null){
for (String key : paramssa.keySet()) {
multipartBodyBuilder.addFormDataPart(key, paramssa.get(key));
}
}
//遍歷paths中所有圖片絕對路徑到builder,並約定key如“upload”作為後臺接受多張圖片的key
if (filessa != null){
for (File file : filessa) {
multipartBodyBuilder.addFormDataPart(pic_key, file.getName(), RequestBody.create(MEDIA_TYPE_PNG, file));
}
}
//構建請求體
RequestBody requestBody = multipartBodyBuilder.build();
Request.Builder RequestBuilder = new Request.Builder();
RequestBuilder.url(reqUrl);// 新增URL地址
RequestBuilder.post(requestBody);
Request request = RequestBuilder.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(okhttp3.Call call, IOException e) {
emitter.onError(e);
emitter.onComplete();
call.cancel();
}
@Override
public void onResponse(okhttp3.Call call, Response response) throws IOException {
String str = response.body().string();
emitter.onNext(str);
emitter.onComplete();
call.cancel();
}
});
}
});
}
/**
* 傳送get請求
* @param url 請求地址
* @param params 請求引數
* @param callback 回撥
* @param <T> 請求回來的資料對應的JavaBean
*/
@Override
public <T> void get(String url, Map<String, String> params, final MyNetWorkCallback<T> callback) {
StringBuffer sb = new StringBuffer(url);
if(params != null && params.size() > 0){
sb.append("?");
Set<String> keys = params.keySet();
for (String key : keys) {
String value = params.get(key);
sb.append(key).append("=").append(value).append("&");
}
url = sb.deleteCharAt(sb.length()-1).toString();
}
Request request = new Request.Builder().url(url).build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(okhttp3.Call call, IOException e) {
App.context.runOnUiThread(new Runnable() {
@Override
public void run() {
//執行在主執行緒
callback.onError(404,e.getMessage().toString());
}
});
}
@Override
public void onResponse(okhttp3.Call call, Response response) throws IOException {
final String jsonData = response.body().string();
//執行在子執行緒中
App.context.runOnUiThread(new Runnable() {
@Override
public void run() {
//執行在主執行緒
callback.onSuccess(getGeneric(jsonData,callback));
}
});
}
});
}
@Override
public <T> void get(String url, Map<String, String> params, Map<String, String> headers, final MyNetWorkCallback<T> callback) {
StringBuffer sb = new StringBuffer(url);
if(params != null && params.size() > 0){
sb.append("?");
Set<String> keys = params.keySet();
for (String key : keys) {
String value = params.get(key);
sb.append(key).append("=").append(value).append("&");
}
url = sb.deleteCharAt(sb.length()-1).toString();
}
Request.Builder builder = new Request.Builder();
if(headers != null && headers.size() > 0){
Set<String> keys = headers.keySet();
for (String key : keys){
String value = headers.get(key);
builder.addHeader(key,value);
}
}
Request request = builder.url(url).build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(okhttp3.Call call, IOException e) {
App.context.runOnUiThread(new Runnable() {
@Override
public void run() {
//執行在主執行緒
callback.onError(404,e.getMessage().toString());
}
});
}
@Override
public void onResponse(okhttp3.Call call, Response response) throws IOException {
final String jsonData = response.body().string();
//執行在子執行緒中
App.context.runOnUiThread(new Runnable() {
@Override
public void run() {
//執行在主執行緒
callback.onSuccess(getGeneric(jsonData,callback));
}
});
}
});
}
/**
* post方法上傳表單
* @param url
* @param params
* @param callback
* @param <T>
*/
@Override
public <T> void post(String url, Map<String, String> params, final MyNetWorkCallback<T> callback) {
FormBody.Builder builder = new FormBody.Builder();
if(params !=null && params.size() > 0){
Set<String> keys = params.keySet();
for (String key : keys) {
String value = params.get(key);
builder.add(key,value);
}
}
Request request = new Request.Builder().url(url).post(builder.build()).build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(okhttp3.Call call, IOException e) {
App.context.runOnUiThread(new Runnable() {
@Override
public void run() {
//執行在主執行緒
callback.onError(404,e.getMessage().toString());
}
});
}
@Override
public void onResponse(okhttp3.Call call, Response response) throws IOException {
final String jsonData = response.body().string();
//執行在子執行緒中
App.context.runOnUiThread(new Runnable() {
@Override
public void run() {
//執行在主執行緒
callback.onSuccess(getGeneric(jsonData,callback));
}
});
}
});
}
@Override
public void upload(String url, String path, Map<String, String> params, String fileType, MediaType MEDIA_TYPE, final MyNetWorkCallback<String> callback) {
File file = new File(path);
MultipartBody.Builder multiRequestBody = new MultipartBody.Builder();
if(params !=null && params.size() > 0){
Set<String> keys = params.keySet();
for (String key : keys) {
String value = params.get(key);
multiRequestBody.setType(MultipartBody.FORM)
.addFormDataPart(key, value);// 提交普通欄位
}
}
// 上傳檔案使用MultipartBody.Builder
RequestBody requestBody = multiRequestBody
.setType(MultipartBody.FORM)
.addFormDataPart(fileType, file.getName(), RequestBody.create(MEDIA_TYPE, file)) // 提交圖片,第一個引數是鍵(name="第一個引數"),第二個引數是檔名,第三個是一個RequestBody
.build();
// POST請求
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(okhttp3.Call call, IOException e) {
App.context.runOnUiThread(new Runnable() {
@Override
public void run() {
//執行在主執行緒
callback.onError(404,e.getMessage().toString());
}
});
}
@Override
public void onResponse(okhttp3.Call call, Response response) throws IOException {
final String upLoadResult=response.body().string();
//執行在子執行緒中
App.context.runOnUiThread(new Runnable() {
@Override
public void run() {
//執行在主執行緒
callback.onSuccess(upLoadResult);
}
});
}
});
}
@Override
public void download() {
}
@Override
public void loadImage(String url, ImageView imageView) {
Glide.with(App.context).load(url).into(imageView);
}
/**
* 自動解析json至回撥中的JavaBean
* @param jsonData
* @param callBack
* @param <T>
* @return
*/
private <T> T getGeneric(String jsonData, MyNetWorkCallback<T> callBack){
Gson gson = new Gson();
//通過反射獲取泛型的例項
Type[] types = callBack.getClass().getGenericInterfaces();
Type[] actualTypeArguments = ((ParameterizedType) types[0]).getActualTypeArguments();
Type type = actualTypeArguments[0];
T t = gson.fromJson(jsonData,type);
return t;
}
//取消
public void cancel(String url, Map<String, String> params){
FormBody.Builder builder = new FormBody.Builder();
if(params !=null && params.size() > 0){
Set<String> keys = params.keySet();
for (String key : keys) {
String value = params.get(key);
builder.add(key,value);
}
}
Request request = new Request.Builder().url(url).post(builder.build()).build();
okHttpClient.newCall(request).cancel();
}
}
你會發現很多問題哈紅的什麼的APP類得有吧()要不怎麼檢測更新呢:
public class App extends Application {
public static MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
public static MainActivity context = null;
}
準備工作都完成了,別拖延大家時間了開始使用吧:表單請求:
private Map<String, String> map = new HashMap<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//很重要的一行,要不然你就空指標去吧
App.context = this;
}
隨便寫個方法看你心情吧:
map.put("currentLang", "2");
OkHttpUtils.getInstance().post(ApiUrl.HTTP_LOG, map, new MyNetWorkCallback<寫自己的Bean>() {
@Override
public void onSuccess(寫自己的Bean s) {
//解析
Gson gson = new Gson();
//變成實體類了自己用吧,隨便用已經在子執行緒了隨便吐司。
寫自己的Bean logBean = gson.fromJson(s, 寫自己的Bean.class);
Toast.makeText(MainActivity.this, "登入成功", Toast.LENGTH_SHORT).show();
}
@Override
public void onError(int errorCode, String errorMsg) {
Toast.makeText(MainActivity.this, "請求失敗", Toast.LENGTH_SHORT).show();
}
});
要圖片的嗎?來了:
Map<String, String> map = new HashMap<>();
map.put("accessToken", toKen);
OkHttpUtils.getInstance().sendMultipart(path, map, "imgData", 存放圖片的集合listfiles)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.newThread())
.subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable throwable) {
dialog.dismiss();
Toast.makeText(ComputerRoomPatrolavtivity.this, "上傳失敗了", Toast.LENGTH_SHORT).show();
}
@Override
public void onNext(String s) {
s = s.trim();
s = s.substring(1, s.length() - 1);//去除首尾雙引號。
String str = s.replace("\\", "");//去除所有的\
Gson gson = new Gson();
Log.e("TAG", "str=" + str);
ToastShow.show(ComputerRoomPatrolavtivity.this, "上傳成功");
} else {
dialog.dismiss();
ToastShow.show(ComputerRoomPatrolavtivity.this, "失敗" + bean.getErrorMessage());
}
}
});
友情提示一下,我的張片上傳之前都壓縮了,這樣上傳比較爽。我用的是魯班壓縮可能很舊了湊合看吧
implementation 'top.zibin:Luban:1.1.3'
Luban.get(this)
.load(file) //傳人要壓縮的圖片
.putGear(Luban.THIRD_GEAR) //設定壓縮檔次,預設三擋
.setCompressListener(new OnCompressListener() { //設定回撥
@Override
public void onStart() {
// TODO 壓縮開始前呼叫,可以在方法內啟動 loading UI
}
@Override
public void onSuccess(File file) {
// TODO 壓縮成功後呼叫,返回壓縮後的圖片檔案
listFileImages.add(file);
//網路請求
httpssa(listFileImages,toKen,dataId);
}
@Override
public void onError(Throwable e) {
// TODO 當壓縮過去出現問題時呼叫
}
}).launch();
目前的專案還沒有涉及到長傳圖片,等涉及到了我自己用了我在改進,
在友情提示rxjava當中的長傳圖片觀察者模式可能有些更改,自己看下最新的吧,然後呼叫,應該舊可以了,用不好的話的等我更新吧。
感謝新手借鑑,大佬指點。