目錄
前言
本文具體實現思路和大部分代碼參考自《第一行代碼》第2版,作者:郭霖;但是文中講解部分和POST請求方式實現代碼還是樓主自己碼出來的,本文相當於是對《第一行代碼》網絡通信部分內容的一次小小的拓展吧。
還有就是,我會把本文實現的Demo源碼在文末分享,有興趣的小伙伴可以直接拿來用,代碼也比較簡潔,對於初學者幫助應該還是蠻大的。
最后,說一下我學習《第一行代碼》書本上網絡通信部分遇到的小問題:
在實現書本上解析JSON格式數據,並在控制台上使用log方式打印解析出的數據信息時,控制台只提示了以下一句信息(PS:對,只有一句提示):
I/System: core_booster, getBoosterConfig = false
然后,就是沒有任何打印信息(PS:按照正常情況,是會打印出解析出的JSON數據),我在此查找了兩個多小時原因,結果網上對於此說明的文章,也無法解決我的問題。
到此時,開始嘗試注釋,分斷分方法區間調用parseJSONWithJSONObject()方法來解析JSON格式數據,最后我在parseJSONWithJSONObject()方法的For循環中加了一個Toast提示用於判斷獲取數據信息情況下,並把parseJSONWithJSONObject()放在了showResponse()方法的子線程中調用,才發現成功解析出了數據,但是log打印依然沒有在控制台輸出。Log打印信息我就沒再去追究了,畢竟已經在手機端實現出了JSON數據解析,所以我想了想,應該是自己log方法使用和AndroidStudio配置導致無法正常打印信息。
1 Get方式和Post方式接口說明
注:下面兩個接口是我自己使用Flask+MongoDB寫的簡單接口,搭建在阿里雲服務器上,僅作學習使用~
(1)Get請求方式接口
功能描述
用戶登陸
調用方式
Key |
Value |
請求URL |
|
HTTP請求方式 |
GET |
支持格式 |
JSON |
是否需要登錄 |
是 |
入參說明
無
返回值說明
參數名 |
類型及范圍 |
描述 |
name |
String |
返回信息 |
passward |
String |
返回信息 |
返回值示例
[
{
"name": "舞動的心",
"passward": "123456"
},
{
"name": "12350@qq.com",
"passward": "123456"
},
{
"name": "12350@qq.com",
"passward": "123456"
},
{
"name": "12350@qq.com",
"passward": "123456"
},
{
"name": "dsff50@qq.com",
"passward": "dsaf"
}
]
(2)Post請求方式接口
功能描述
用戶注冊
調用方式
Key |
Value |
請求URL |
http://120.79.82.151/register |
HTTP請求方式 |
POST |
支持格式 |
JSON |
是否需要登錄 |
是 |
入參說明
參數名 |
必選 |
類型及范圍 |
描述 |
name |
是 |
String |
用戶名 |
password |
是 |
String |
登錄密碼 |
nickname |
是 |
String |
用戶昵稱 |
返回值說明
參數名 |
類型及范圍 |
描述 |
name |
String |
返回信息 |
passward |
String |
返回信息 |
nickname |
String |
返回信息 |
返回值示例
{
"name": "dsff50@qq.com",
"nickname": "舞動的心05",
"passward": "dsaf"
}
2 OkHttp庫簡單介紹及環境配置
OkHttp是有Square公司開發的。OkHttp在接口封裝上做得簡單易用,比起原生的HttpURLConnection要好用好多,而且實現的代碼簡潔易懂。現在已是大多數Android開發者首選的網絡通信庫,它的項目主頁地址:https://github.com/square/okhttp
OkHttp是第三方庫,所以在使用之前,我們需要在項目app/build.grade文件中進行配置,找到dependencies,添加以下加粗紅色內容(PS:其中版本信息可以查看okhttp項目主頁最新版進行配置,也可以不用變更):
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:design:25.2.0'
compile 'com.android.support:recyclerview-v7:25.2.0'
compile 'com.squareup.okhttp3:okhttp:3.4.1'
testCompile 'junit:junit:4.12'
}
3 具體實現
GET方式模擬實現用戶登陸功能,獲取數據后解析並驗證,如果驗證成功,會有Toast提示“登陸成功!!!”。
POST方式模擬實現用戶注冊功能,提交數據獲取驗證數據后解析並驗證,如果驗證成功,會有Toast提示“注冊成功!!!”。
具體運行結果:
具體實現代碼:
代碼分為兩部分,一部分是layout布局文件,只有一個activity_main.xml文件;一部分是Java類,只有兩個文件,分別是MainActivity類和HttpUtil類。整體的代碼量很少。具體如下:
activity_main.xml代碼:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" > <Button android:id="@+id/send_request" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Send Request(Get方式)" /> <Button android:id="@+id/send_response" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Send Response(Post方式)" android:onClick="post_click"/> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/response_text" android:layout_width="match_parent" android:layout_height="wrap_content" /> </ScrollView> </LinearLayout>
MainActivity類代碼:
package com.liu.mapliutest; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import org.json.JSONArray; import org.json.JSONObject; import java.io.IOException; import okhttp3.Call; import okhttp3.MediaType; import okhttp3.RequestBody; import okhttp3.Response; public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private TextView responseText; public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button sendRequest = (Button) findViewById(R.id.send_request); responseText = (TextView) findViewById(R.id.response_text); sendRequest.setOnClickListener(this); } @Override public void onClick(View v) { if (v.getId() == R.id.send_request) { HttpUtil.sendOkHttpRequest("http://120.79.82.151/login", new okhttp3.Callback() { @Override public void onResponse(Call call, Response response) throws IOException { // 在這里根據返回內容執行具體的邏輯 showResponse(response.body().string(), 0); } @Override public void onFailure(Call call, IOException e) { // 在這里對異常情況進行處理 } }); } } //將提交到服務器數據轉換為JSON格式數據字符串 public String getJson(String name, String passward, String nickname)throws Exception { JSONObject jsonParam = new JSONObject(); jsonParam.put("name", name); jsonParam.put("passward", passward); jsonParam.put("nickname",nickname); return jsonParam.toString(); } //此處是POST方式Button的觸發事件,剛開始寫觸發事件時,寫在了onClick()方法中,使用else if條件判斷,結果沒有響應,所以改寫成了單獨方法。 public void post_click(View v) { String json = ""; try { json = getJson("liuzhen01","456321","wudongdexin"); } catch (Exception e) { e.printStackTrace(); } RequestBody requestBody = RequestBody.create(JSON, json); HttpUtil.sendOkHttpResponse("http://120.79.82.151/register",requestBody, new okhttp3.Callback() { @Override public void onResponse(Call call, Response response) throws IOException { // 在這里根據返回內容執行具體的邏輯 showResponse(response.body().string(), 1); } @Override public void onFailure(Call call, IOException e) { // 在這里對異常情況進行處理 } }); } //解析GET方式請求返回JSON數據 private void parseJSONWithJSONObject(String jsonData) { try { JSONArray jsonArray = new JSONArray(jsonData); for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); String name = jsonObject.getString("name"); String passward = jsonObject.getString("passward"); if(name.equals("舞動的心") && passward.equals("123456")) Toast.makeText(MainActivity.this, "登陸成功!!!", Toast.LENGTH_SHORT).show(); } } catch (Exception e) { e.printStackTrace(); } } //解析方式請求返回JSON數據 private void parseJSONWithJSONObjectPost(String jsonData) { try { JSONArray jsonArray = new JSONArray(jsonData); //注意,此處是一個JSON格式數組 for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); String name = jsonObject.getString("name"); String passward = jsonObject.getString("passward"); if(name.equals("liuzhen01") && passward.equals("456321")) Toast.makeText(MainActivity.this, "注冊成功!!!", Toast.LENGTH_SHORT).show(); } } catch (Exception e) { e.printStackTrace(); } } private void showResponse(final String response, final int judge) { runOnUiThread(new Runnable() { @Override public void run() { // 在這里進行UI操作,將結果顯示到界面上 if(judge == 0) parseJSONWithJSONObject(response); //放在此處執行,處理服務器上Get方式獲取的數據,進行相關功能邏輯處理 else { parseJSONWithJSONObjectPost("["+response+"]"); //處理Post方式獲取數據,此處加上中括號,因為Post返回的是一個JSON數據,加上中括號變成數組格式 } responseText.setText(response); } }); } }
HttpUtil類代碼:
package com.liu.mapliutest; import org.json.JSONObject; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; /** * Created by 舞動的心 on 2018/3/4. */ public class HttpUtil { //使用Get方式獲取服務器上數據 public static void sendOkHttpRequest(final String address, final okhttp3.Callback callback) { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url(address) .build(); client.newCall(request).enqueue(callback); } //使用Post方式向服務器上提交數據並獲取返回提示數據 public static void sendOkHttpResponse(final String address, final RequestBody requestBody, final okhttp3.Callback callback) { OkHttpClient client = new OkHttpClient(); // JSONObject object; Request request = new Request.Builder() .url(address).post(requestBody).build(); client.newCall(request).enqueue(callback); } }
項目代碼鏈接:https://coding.net/u/LiuZhen1995/p/MyDemo/git/tree/Thirteen