我刚开始接触 okhttp3 的时候,就想要发个请求而已,网络文章大多介绍原理、细节,对于入门者,还不能或者不想接触这些,只想发送网络请求感受一番。下面步骤是满足 restful 风格的 get/post/delete/put 请求的异步请求封装,开箱即用。
1. 添加网络访问权限
修改 AndroidManifest.xml 文件,添加网络访问权限。
<uses-permission android:name="android.permission.INTERNET"/>
2. 添加 okhttp 依赖
修改 build.gradle 文件,添加 okhttp 的依赖。
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
3. 新建 HttpUtil.java 类
restful 风格的 get/post/delete/put 请求封装。还不完善,不过对于 Py-novel 项目来说是够用了。请求 http 请求一直失败,请求 https 就能成功返回,不知道是不是内部限制。
如果有变量报红线,请注意看该类所属的包是否为 okhttp3,下面文件最上方列出了我用到的类所属的包。
package top.dkvirus.novel.okhttptest;import android.util.Log;import org.json.JSONException;import org.json.JSONObject;import java.util.Map;import okhttp3.Call;import okhttp3.Callback;import okhttp3.MediaType;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.RequestBody;public class HttpUtil {private static final String TAG = "HttpUtil";/*** get 请求*/public static void get (String url, Callback callback) {OkHttpClient client = new OkHttpClient();Request request = new Request.Builder().url(url).build();client.newCall(request).enqueue(callback);}/*** post 请求*/public static void post (String url, Map<String, Object> map, Callback callback) {OkHttpClient client = new OkHttpClient();MediaType JSON = MediaType.parse("application/json; charset=utf-8");JSONObject jsonObject = new JSONObject();try {for (String key : map.keySet()) {jsonObject.put(key, map.get(key));}} catch (JSONException e) {Log.d(TAG, "POST 请求 json 格式参数解析错误");e.printStackTrace();}Log.d(TAG, "POST 请求参数:" + jsonObject.toString());RequestBody body = RequestBody.create(JSON, jsonObject.toString());Request request = new Request.Builder().url(url).post(body).build();client.newCall(request).enqueue(callback);}/*** delete 请求*/public static void delete (String url, Callback callback) {OkHttpClient client = new OkHttpClient();Request request = new Request.Builder().url(url).delete().build();client.newCall(request).enqueue(callback);}/*** put 请求*/public static void put (String url, Map<String, Object> map, Callback callback) {OkHttpClient client = new OkHttpClient();MediaType JSON = MediaType.parse("application/json; charset=utf-8");JSONObject jsonObject = new JSONObject();try {for (String key : map.keySet()) {jsonObject.put(key, map.get(key));}} catch (JSONException e) {Log.d(TAG, "PUT 请求 json 格式参数解析错误");e.printStackTrace();}RequestBody body = RequestBody.create(JSON, jsonObject.toString());Request request = new Request.Builder().url(url).put(body).build();client.newCall(request).enqueue(callback);}}
4. 使用示例
package top.dkvirus.novel.okhttptest;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.widget.TextView;import java.io.IOException;import java.util.HashMap;import java.util.Map;import okhttp3.Call;import okhttp3.Callback;import okhttp3.Response;public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";TextView resp_text;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);resp_text = findViewById(R.id.resp_text);// Get 请求示例代码// HttpUtil.get("https://novel.dkvirus.top/api/test/gysw/novel/classify", new Callback() {// @Override// public void onFailure(Call call, IOException e) {// Log.d(TAG, "onFailure: 失败了");// }//// @Override// public void onResponse(Call call, Response response) throws IOException {// Log.d(TAG, "onResponse: 成功了");// Log.d(TAG, "onResponse: " + response.body().string());// }// });// Post 请求示例代码// Map<String, Object> map = new HashMap<String, Object>();// map.put("username", "18056891356");// map.put("password", "123456");// map.put("client_type", "MOBILE");// HttpUtil.post("https://novel.dkvirus.top/api/test/gysw/user/info", map, new Callback() {// @Override// public void onFailure(Call call, IOException e) {// Log.d(TAG, "onFailure: 新增数据失败");// }//// @Override// public void onResponse(Call call, Response response) throws IOException {// Log.d(TAG, "onResponse: 新增数据成功");// Log.d(TAG, "onResponse: " + response);// }// });// Delete 请求示例代码// HttpUtil.delete("https://novel.dkvirus.top/api/test/gysw/shelf/29", new Callback() {// @Override// public void onFailure(Call call, IOException e) {// Log.d(TAG, "onFailure: 删除数据失败");// }//// @Override// public void onResponse(Call call, Response response) throws IOException {// Log.d(TAG, "onResponse: 删除数据成功");// Log.d(TAG, "onResponse: " + response);// }// });// Post 请求示例代码Map<String, Object> map = new HashMap<>();map.put("recent_chapter_url", "https://www.biquge5200.cc/0_7/2046.html");HttpUtil.put("https://novel.dkvirus.top/api/test/gysw/shelf/30", map, new Callback() {@Overridepublic void onFailure(Call call, IOException e) {Log.d(TAG, "onFailure: 修改数据失败");}@Overridepublic void onResponse(Call call, Response response) throws IOException {Log.d(TAG, "onResponse: 修改数据成功");Log.d(TAG, "onResponse: " + response);}});}}
5. 解析数据
okhttp3 默认返回数据为字符串类型,想要转换为 json 格式的数据需要怎么做?
这里使用 gson 方式解析响应,第一步在 build.gradle 中加入 gson 依赖。
implementation 'com.google.code.gson:gson:2.7'
在上面的 HttpUtil.java 中添加一个方法。
public static <T> T parseJSONWithGSON (String jsonData, TypeToken<T> typeToken) {Gson gson = new Gson();T t = gson.fromJson(jsonData, typeToken.getType());return t;}
响应的数据结构如下:
{code: "0000",message: "操作成功",data: {userId: 1,username: "dkvirus",}}
定义实体类,实体类结构要与返回的数据结构一一对应。
public class DetailResult {private String code;private String message;private Detail data;// get/set 方法自己补充}// 另外一个 Java 类public class Detail {private int userId;private String username;// get/set 方法自己补充}
解析
String responseData = response.body().string();DetailResult detailResult = HttpUtil.parseJSONWithGSON(responseData, new TypeToken<DetailResult>(){});
