使用基于Android网络通信的OkHttp库实现Get和Post方式简单操作服务器JSON格式数据
目录
前言
本文具体实现思路和大部分代码参考自《第一行代码》第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在接口封装上做得简单易用,比起原Connection要好用好多,而且实现的代码简洁易懂。现在已是大多数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