1. 程式人生 > 實用技巧 >android studio與springboot使用OkHttp連線前後端

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();
            }
        });

執行結果