android studio與springboot使用OkHttp連線前後端
一、SpringBoot介面分類
springboot後端介面分為3種,@RequestBody型別,@RequestParam型別以及@RequestParam("file") MultipartFile file型別,下面對這三種類型分別說明。
1.@RequestBody型別
在postman中使用body傳送JSON語句
對於該種類型的介面,程式碼如下
String json = "{\n" + //傳送的json格式語句直接複製過來 "}"; OkHttpClient client = new OkHttpClient();//建立Http客戶端 Request request = new Request.Builder() .url("http://***.***.**.***:xxxx/ / ")//***.***.**.***為本機IP,xxxx為埠,/ / 為訪問的介面字尾 .post(RequestBody.create(MediaType.parse("application/json"),json)) .build();//建立Http請求 Response response = client.newCall(request).execute();//執行傳送的指令 final String responseData = response.body().string();//獲取返回的結果
若返回的結果為json格式,可用JSONObject或JSONArray進行轉換,以JSONArray為例
JSONArray jsonArray = new JSONArray(responseData); for(int i = 0; i < jsonArray.length(); i++){//遍歷 JSONObject jsonObject = jsonArray.getJSONObject(i); String result = jsonObject.getString("xxx");//xxx為JSON語句中的key值,get到的為value值 }
2.@RequestParam型別
在postman中改變value的同時會改變url
對於該種類型的介面,程式碼如下(註解請參考1.型別中註解)
FormBody.Builder params = new FormBody.Builder(); params.add("xx",**); params.add("xx",**);//xx為key,**為value OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("http://***.***.**.**:xxxx/ / ") .post(params.build()) .build(); Response response = client.newCall(request).execute(); final String responseData = response.body().string();
若返回的結果為json格式,同上
3.@RequestParam("file") MultipartFile file
用於上傳檔案、圖片等,目前還未用到,會補全。
二、對OkHttp的使用
在以上程式碼的執行過程中遇到一些網路訪問的問題,下面一一講解
首先,使用OkHttp之前需匯入包。在Build.gradle(app)中新增
在AndroidManifest.xml中新增網路訪問許可權
執行發現第一個報錯:CLEARTEXT communication to xxxx not permitted by network security policy
查詢資料發現
在Android P系統的裝置上,如果應用使用的是非加密的明文流量的http網路請求,則會導致該應用無法進行網路請求,https則不會受影響,同樣地,如果應用嵌套了webview,webview也只能使用https請求。
故有三種方法,我採用的第三種方法
1、APP改用https請求
2、targetSdkVersion 降到27以下
3、在 res 下新增一個 xml 目錄,然後建立一個名為:network_security_config.xml 檔案(名字自定) ,內容如下,大概意思就是允許開啟http請求
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="true" /> </network-security-config>
然後在APP的AndroidManifest.xml檔案下的application標籤增加以下屬性
<application ... android:networkSecurityConfig="@xml/network_security_config" ... />
執行發現第二個報錯(阿巴阿巴現在調不出來了)
在AndroidManifest.xml中新增
然後解除安裝app,重新執行
附:如果出現fail to connect to報錯,檢查一下ip地址是否有問題
三、android studio的多工執行
android studio中傳送post請求需放在子執行緒中,因為請求可能失敗,為了不影響主執行緒,故建立子執行緒。
假設我點選按鈕然後傳送post請求,那麼程式碼如下
public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { //請求程式碼 } }).start(); }
如果線上程中需要改變UI,需要在子執行緒中呼叫函式,將改變UI的程式碼扔回給主執行緒執行,不然會報錯
假設我需要在子執行緒中show一個Toast
Toast.makeText(UserLoginActivity.this,"登入成功",Toast.LENGTH_SHORT).show();
有三種方式可以把請求回撥給主執行緒
1.Activity.runOnUiThread(Runnable)
新增toast就是用這個函式
runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(UserLoginActivity.this,"登入成功",Toast.LENGTH_SHORT).show(); } });
2.View.post(Runnable)
改變UI部件則使用這個函式
假設我
TextView username = findViewById(R.id.username);
那麼當我需要線上程中改變username的內容時,就把setText放到以下函式中
username.post(new Runnable() { public void run() { username.setText("使用者名稱"); } });
3.View.postDelayed(Runnable,long)
與2相同,Delay了long的時間延遲響應
四、對post請求的說明
建立post請求可能存在通訊不成功的情況,故在android studio中需把請求放在try函式中,結合上文改變UI的說明,程式碼如下
try { //post請求 }catch (Exception e){ e.printStackTrace(); runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(UserLoginActivity.this,"網路錯誤",Toast.LENGTH_SHORT).show(); } }); }
示例程式碼登入(方法1)
username = findViewById(R.id.username); password = findViewById(R.id.password); loginButton = findViewById(R.id.button); loginButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { usernameLogin = username.getText().toString(); passwordLogin = password.getText().toString(); new Thread(new Runnable() { @Override public void run() { try { String json = "{\n" + " \"storePhone\": \"" + usernameLogin + "\",\n" + " \"storePwd\": \"" + passwordLogin + "\"\n" + "}"; OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("http://192.168.43.178:23333/store/login") .post(RequestBody.create(MediaType.parse("application/json"),json)) .build(); Response response = client.newCall(request).execute(); final String responseData = response.body().string(); if(responseData.equals("true")){ runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(ShopLoginActivity.this,"登入成功",Toast.LENGTH_SHORT).show(); } }); } else if(responseData.equals("false")){ runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(ShopLoginActivity.this,"使用者名稱或密碼錯誤",Toast.LENGTH_SHORT).show(); } }); } }catch (Exception e){ e.printStackTrace(); runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(ShopLoginActivity.this,"網路錯誤",Toast.LENGTH_SHORT).show(); } }); } } }).start(); } });
執行結果