目錄
一,OkHttp簡介
二,OkHttp請求處理流程
三,OkHttp環境配置
四,OkHttp的使用
1.get網絡請求
2.post上傳表單數據
3.post上傳json格式數據
4.文件上傳
5.文件下載
一,OkHttp簡介
????????OkHttp是square公司推出的一款Android和Java網絡請求庫,是目前公認的最好用的網絡請求框架,OkHttp有以下的特點:
- 支持Http/2,允許對同一主機的所有請求共享同一套接字;
- 使用連接池減少請求延時;
- 透明的GZIP壓縮減少響應數據的大小;
- 緩存響應的內容,避免重復請求;
OkHttp源碼地址:https://github.com/square/okhttp?
二,OkHttp請求處理流程
(1)使用OkHttp需要先創建OkHttpClient對象,可以使用構造器直接創建,也可以使用builder創建;
(2)使用Request.builder創建Request請求,用于封裝要訪問的網絡地址Url。當進行post操作時,還需創建RequestBody用于封裝請求數據,并調用Requst的post方法;
(3)通過OkHttpClient的newCall方法創建Call對象,使用同步或異步的方法發送Request請求,并接收Response響應數據;
三,OkHttp環境配置
(1)在build.gradle中添加依賴:
dependencies {
????????implementation 'com.squareup.okhttp3:okhttp:3.14.9'
}
(2)在AndroidManifest.xml中添加網絡訪問權限:
<uses-permission android:name="android.permission.INTERNET"/>?
(3)在AndroidManifest.xml添加 android:usesCleartextTraffic="true" 解除Http訪問禁制:
四,OkHttp的使用
OkHttp主要有以下功能:
- get,post請求文本數據;
- 上傳文件;
- 下載文件;
- 加載圖片(自動壓縮圖片大小);
1.get網絡請求
private void visitInternet() {//1.創建HttpClient對象OkHttpClient okHttpClient = new OkHttpClient();//2.獲取request對象Request.Builder builder = new Request.Builder().url("https://www.bilibili.com/");Request request = builder.build();//3.獲取call對象Call call = okHttpClient.newCall(request);//4.執行網絡操作(同步)try {//同步執行網絡操作Response response = call.execute();String result = response.body().string();showResultOnUiThread(result);} catch (IOException e) {throw new RuntimeException(e);}
}
????????注意這里使用了call的同步請求方式,會產生阻塞,所以此方法必須放在子線程中執行。如果不想放在子線程中執行的話,可以使用call的異步請求方式。
????????當請求成功時call會返回Response,我們可以通過response.body()獲取字符串,輸入流等返回的信息。
2.post上傳表單數據
????????當需要上傳數據時,需要創建RequestBody用于封裝數據,因為我們這里上傳的是表單數據,所以需要創建RequestBody的子類FormBody 。
private void postForm() {OkHttpClient okHttpClient = new OkHttpClient();//創建FormBody對象,封裝數據(鍵值對信息)FormBody formBody = new FormBody.Builder().add("userName", "json").add("pwd", "123456").build();Request request = new Request.Builder().post(formBody).url(Host + "/servlet01").build();Call call = okHttpClient.newCall(request);//異步執行網絡操作call.enqueue(new Callback() {//請求本身失敗時調用@Overridepublic void onFailure(Call call, IOException e) {showResultOnUiThread("請求為空");}//請求成功時調用@Overridepublic void onResponse(Call call, Response response) throws IOException {String result = response.body().string();showResultOnUiThread(result);}});
}
????????當使用call的異步請求方式時,需要重寫兩個方法onFailure和onResponse,當請求失敗時(連接失敗或讀寫超時)調用onFailure,請求成功時調用onResponse。
????????可以寫一個簡單的服務端來驗證一下是否可以請求成功:
@WebServlet("/servlet01")
public class servlet01 extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf-8");resp.setCharacterEncoding("utf-8");String userName = req.getParameter("userName");String pwd = req.getParameter("pwd");if(userName == null || "".equals(userName)){resp.getWriter().write("用戶名不能為空");}else if(pwd == null || "".equals(pwd)){resp.getWriter().write("密碼不能為空");}else {resp.getWriter().write("歡迎:" + userName);}}
}
3.post上傳json格式數據
????????使用Gson需要先添加依賴:
implementation'com.google.code.gson:gson:2.10.1'
????????當上傳json數據時,自然需要用到RequestBody來封裝json數據,同時還需用MediaType來設置數據類型(也就是我們想要上傳的數據的類型)。
private void postJson() {OkHttpClient okHttpClient = new OkHttpClient();//1.創建json數據User user = new User();user.setUsername("json");user.setPwd("123456");String json = new Gson().toJson(user);//2.通過RequestBody封裝json數據RequestBody requestBody = RequestBody.create(MediaType.parse("application/json;charset=utf-8"),//設置數據類型json//數據);Request request = new Request.Builder().post(requestBody).url(Host + "/servlet02").build();Call call = okHttpClient.newCall(request);try {Response response = call.execute();String result = response.body().string();showResultOnUiThread(result);} catch (IOException e) {throw new RuntimeException(e);}
}
同樣寫一個簡單服務端來測試一下:
@WebServlet("/servlet02")
public class servlet02 extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf-8");resp.setCharacterEncoding("utf-8");BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(req.getInputStream()));String data = bufferedReader.readLine();resp.getWriter().write("json:" + data);}
}
4.文件上傳
????????通過OkHttp上傳文件的步驟與上傳json數據一致,只需更換設置的數據類型即可。因為上傳的需要是安卓客戶端的數據,所以我們需要先在安卓客戶端添加數據。
????????打開路徑data/data/com.example.okhttp/files,在files目錄下添加一張圖片,之后就可以開始上傳了。第一次打開時沒有files這個目錄,需要手動創建。
同時還需要給app添加訪問sd卡的權限,在AndroidManifest.xml中添加:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
客戶端上傳文件:
private void upImg() {//通過文件路徑打開文件String path = getFilesDir().getAbsolutePath() +"/zj.png";File file = new File(path);OkHttpClient okHttpClient = new OkHttpClient();RequestBody requestBody = RequestBody.create(MediaType.parse("application/octet-stream"),file);Request request = new Request.Builder().post(requestBody).url(Host + "/servlet02").build();Call call = okHttpClient.newCall(request);try {Response response = call.execute();String result = response.body().string();showResultOnUiThread(result);} catch (IOException e) {throw new RuntimeException(e);}
}
服務端接收文件:
@WebServlet("/servlet02")
public class servlet02 extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf-8");resp.setCharacterEncoding("utf-8");File file = new File(filePath);ServletInputStream inputStream = req.getInputStream();FileOutputStream fileOutputStream = new FileOutputStream(file);byte[] bytes = new byte[1024];int len = -1;while((len = inputStream.read(bytes)) != -1){fileOutputStream.write(bytes, 0, len);fileOutputStream.flush();}resp.getWriter().write("上傳成功!");inputStream.close();fileOutputStream.close();}
}
5.文件下載
下載文件時不需要上傳數據,因此不用創建RequestBody對象,只需發送請求即可。
private void downImg() {OkHttpClient okHttpClient = new OkHttpClient();Request request = new Request.Builder().url(Host2 + "/servlet03").build();Call call = okHttpClient.newCall(request);try {Response response = call.execute();//獲取返回的輸入流InputStream inputStream = response.body().byteStream();//轉成bitmap數據Bitmap bitmap = BitmapFactory.decodeStream(inputStream);runOnUiThread(new Runnable() {@Overridepublic void run() {img_img.setImageBitmap(bitmap);}});} catch (IOException e) {throw new RuntimeException(e);}
}
服務端提供數據:
@WebServlet("/servlet03")
public class servlet03 extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {File file = new File(filePath);ServletOutputStream outputStream = resp.getOutputStream();BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file));byte[] bytes = new byte[1024];int len = -1;while((len = bufferedInputStream.read(bytes)) != -1){bufferedOutputStream.write(bytes, 0, len);}bufferedOutputStream.close();bufferedInputStream.close();}
}