前言
最近捣鼓android
,但学习不多,索性完全把android
当前端玩了,然后自己写了个后端服务,所以这个中间过程就需要网络请求,找了个三方库,即AsyncHttpClient
,下面就是自己简单的封装了下get
和post
方法,这两个也够我目前业务开发了。
如果想看下代码的可以按照顺序慢慢看,如果有不喜欢看代码,就喜欢直接复制粘贴的,也可以直接点目录,倒数第二个大标题《完整代码》
,添加文件,复制代码,然后目录最后一个《外部使用》
简单看下实现效果模仿者来就好了。
1、为项目添加网络权限
打开项目清单文件,添加如下两行代码即可,有权限才能开网络请求嘛。
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
2、新建一个Axios.java文件,写入如下代码
文件名其实是由于之前搞前端习惯用axios库,也是个非常优秀的请求库;代码的相关注释我已写好,其中主要分为几个部分:
- 基本配置(请求地址、超时时间,合法状态码)
- get和post方法的实现
- 加载提示(请求前、请求结束后)
- 请求反馈(回调)
2.1先看基本配置吧
这个其实没什么太多说的,光看注释应该是看的懂的
private Context context; // 上下文,用来给弹框反馈提示用的
private AsyncHttpClient asyncHttpClient; // asyncHttpClient对象
private ProgressDialog waitingDialog = null; // 弹框对象
private String dialogTitle = "", dialogMsg = ""; // 弹框标题和内容
private static String baseURL = "http://xxxx:5000"; // 请求地址
private static int ConnectTimeOut = 5000; // 超时时间
private CallBackFun callBackFun; // 回调接口
2.2 get和post的实现
get:
注意:这里我是没有在方法中体现携带方法的,要携带参数一般是直接拼在url
后面,或者你可以看看post
的实现。
还有,你可能会看到两个失败的回调的实现,之所以是两个,是因为这个请求的错误有可能有很多情况,有可能400、有可能500,也有可能是网络没打开等等原因,但我业务又不是很复杂,所以没有深究,就把两种实现都写上去,提示下用户就好了。
public void get(String url) {
String requsetUrl = baseURL + url; // 完整链接
if (this.asyncHttpClient != null) {
try {
showLoading(); // 弹框加载
this.asyncHttpClient.get(requsetUrl, new JsonHttpResponseHandler() { // 实现AsyncHttpClient的响应
@SuppressLint("DefaultLocale")
@Override
public void onSuccess(int statusCode, Header[] headers, org.json.JSONObject response) { // 实现成功的回调
super.onSuccess(statusCode, headers, response);
stopLoading(); // 停止加载
try {
if (!Axios.isValidCode(Integer.parseInt(response.getString("Tag")))) { // 校验一下后端的给的code是不是合法的,注意这不是http的code,而是业务自己设定的
Toast.makeText(context, response.getString("Message"), Toast.LENGTH_SHORT).show();
} else {
callBackFun.onAxiosSuccess(response); // 调用外部给的成功回调方法
}
} catch (JSONException e) {
e.printStackTrace();
}
}
@SuppressLint("DefaultLocale")
@Override
public void onFailure(int statusCode, Header[] headers, Throwable throwable, org.json.JSONObject errorResponse) { // 实现失败的回调
super.onFailure(statusCode, headers, throwable, errorResponse);
callBackFun.onAxiosFailure(errorResponse); // 调用外部失败的回调方法
stopLoading(); // 停止加载
if (errorResponse == null) {
Toast.makeText(context, R.string.fail + ":网络", Toast.LENGTH_SHORT).show();
return;
}
try {
Toast.makeText(context, errorResponse.getString("reason"), Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) { // 实现失败的回调
super.onFailure(statusCode, headers, responseString, throwable);
callBackFun.onAxiosFailure(responseString); // 调用外部失败的回调方法
stopLoading(); // 停止加载
Toast.makeText(context, R.string.fail + responseString, Toast.LENGTH_SHORT).show();
}
});
} catch (Exception e) {
e.printStackTrace();
stopLoading();
}
}
}
post:
这里注意的地方到没什么,就是携带参数那里,我设置了用json格式发送的。
public void post(String url, RequestParams requestParams) {
requestParams.setUseJsonStreamer(true); // 代表是用json格式携带进body里面,即Mime-Type为application/json
String requsetUrl = baseURL + url; //请求完整地址
if (this.asyncHttpClient != null) {
try {
showLoading(); // 弹框加载
this.asyncHttpClient.post(requsetUrl, requestParams, new JsonHttpResponseHandler() {
@SuppressLint("DefaultLocale")
@Override
public void onSuccess(int statusCode, Header[] headers, org.json.JSONObject response) {
super.onSuccess(statusCode, headers, response);
stopLoading();
try {
if (!Axios.isValidCode(Integer.parseInt(response.getString("Tag")))) { // 校验一下后端的给的code是不是合法的,注意这不是http的code,而是业务自己设定的
Toast.makeText(context, response.getString("Message"), Toast.LENGTH_SHORT).show();
} else {
callBackFun.onAxiosSuccess(response); // 调用外部的成功回调方法
}
} catch (JSONException e) {
e.printStackTrace();
}
}
@SuppressLint("DefaultLocale")
@Override
public void onFailure(int statusCode, Header[] headers, Throwable throwable, org.json.JSONObject errorResponse) {
super.onFailure(statusCode, headers, throwable, errorResponse);
callBackFun.onAxiosFailure(errorResponse); // 调用外部失败的回调方法
stopLoading();
if (errorResponse == null) {
Toast.makeText(context, R.string.fail, Toast.LENGTH_SHORT).show();
return;
}
try {
Toast.makeText(context, errorResponse.getString("reason"), Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
super.onFailure(statusCode, headers, responseString, throwable);
callBackFun.onAxiosFailure(responseString);
stopLoading();
Toast.makeText(context, R.string.fail, Toast.LENGTH_SHORT).show();
}
});
} catch (Exception e) {
e.printStackTrace();
stopLoading();
}
}
}
2.3回调实现
这里代码其实很简单,其实就是自己多琢磨琢磨就好了,没啥技巧,因为回调不管是前端还是后端,应用场景大多都是异步操作,等异步操作完了再干嘛干嘛。
public interface CallBackFun { // 外部用的回调接口
public void onAxiosSuccess(org.json.JSONObject obj);
public void onAxiosFailure(Object obj);
}
public void setOnCallBack(CallBackFun callBackFun) { // 为该对象添加回调接口
this.callBackFun = callBackFun;
}
完整代码
package com.xlzn.hcpda.uhf.ui;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.widget.Toast;
import com.alibaba.fastjson.JSONObject;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.JsonHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import com.xlzn.hcpda.uhf.R;
import org.json.JSONException;
import cz.msebera.android.httpclient.Header;
public class Axios {
private Context context; // 上下文,用来给弹框反馈提示用的
private AsyncHttpClient asyncHttpClient; // asyncHttpClient对象
private ProgressDialog waitingDialog = null; // 弹框对象
private String dialogTitle = "", dialogMsg = ""; // 弹框标题和内容
private static String baseURL = "http://xxxx:5000"; // 请求地址
private static int ConnectTimeOut = 5000; // 超时时间
private CallBackFun callBackFun; // 回调接口
public Axios(Context context) { // 初始化
this.context = context;
this.dialogTitle = context.getString(R.string.dialog_title);
this.dialogMsg = context.getString(R.string.dialog_loading_msg);
AsyncHttpClient client = new AsyncHttpClient();
client.setTimeout(Axios.ConnectTimeOut);
this.asyncHttpClient = client;
}
public void setDialogTitle(String dialogTitle) { // 设置加载框的标题,用来给外部用的
this.dialogTitle = dialogTitle;
}
public void setDialogMsg(String dialogMsg) { // 设置加载框的内容,用来给外部用的
this.dialogMsg = dialogMsg;
}
/*
* 没太大用,把对象实例返回出去而已,
* 之前想着是用来外部判断网络连接没有,
* 但是后面发现,其实如果没有网路连接的话,
* 其实会进入 AsyncHttpClient 里面失败的回调,
* 相当于是别人内部以及做了处理了
* */
public AsyncHttpClient getAsyncHttpClient() {
if (!this.isNetConnection()) {
Toast.makeText(context, R.string.net_error, Toast.LENGTH_SHORT).show();
return null;
}
return asyncHttpClient;
}
private boolean isNetConnection() { // 判断是否有网络连接 包括wifi和数据流量
if (this.context != null) {
ConnectivityManager connectivityManager = (ConnectivityManager) this.context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
return networkInfo.getState() == NetworkInfo.State.CONNECTED;
}
}
return false;
}
private void showLoading() {
if (this.waitingDialog == null) {
this.waitingDialog = new ProgressDialog(this.context);
this.waitingDialog.setTitle(dialogTitle);
this.waitingDialog.setMessage(dialogMsg);
this.waitingDialog.setIndeterminate(true);
this.waitingDialog.setCancelable(false);
}
this.waitingDialog.show();
}
private void stopLoading() {
if (this.waitingDialog != null) this.waitingDialog.cancel();
}
public static boolean isValidCode(int code) {
return code == 1;
}
public void get(String url) {
String requsetUrl = baseURL + url; // 完整链接
if (this.asyncHttpClient != null) {
try {
showLoading(); // 弹框加载
this.asyncHttpClient.get(requsetUrl, new JsonHttpResponseHandler() { // 实现AsyncHttpClient的响应
@SuppressLint("DefaultLocale")
@Override
public void onSuccess(int statusCode, Header[] headers, org.json.JSONObject response) { // 实现成功的回调
super.onSuccess(statusCode, headers, response);
stopLoading(); // 停止加载
try {
if (!Axios.isValidCode(Integer.parseInt(response.getString("Tag")))) { // 校验一下后端的给的code是不是合法的,注意这不是http的code,而是业务自己设定的
Toast.makeText(context, response.getString("Message"), Toast.LENGTH_SHORT).show();
} else {
callBackFun.onAxiosSuccess(response); // 调用外部给的成功回调方法
}
} catch (JSONException e) {
e.printStackTrace();
}
}
@SuppressLint("DefaultLocale")
@Override
public void onFailure(int statusCode, Header[] headers, Throwable throwable, org.json.JSONObject errorResponse) { // 实现失败的回调
super.onFailure(statusCode, headers, throwable, errorResponse);
callBackFun.onAxiosFailure(errorResponse); // 调用外部失败的回调方法
stopLoading(); // 停止加载
if (errorResponse == null) {
Toast.makeText(context, R.string.fail + ":网络", Toast.LENGTH_SHORT).show();
return;
}
try {
Toast.makeText(context, errorResponse.getString("reason"), Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) { // 实现失败的回调
super.onFailure(statusCode, headers, responseString, throwable);
callBackFun.onAxiosFailure(responseString); // 调用外部失败的回调方法
stopLoading(); // 停止加载
Toast.makeText(context, R.string.fail + responseString, Toast.LENGTH_SHORT).show();
}
});
} catch (Exception e) {
e.printStackTrace();
stopLoading();
}
}
}
public void post(String url, RequestParams requestParams) {
requestParams.setUseJsonStreamer(true); // 代表是用json格式携带进body里面,即Mime-Type为application/json
String requsetUrl = baseURL + url; //请求完整地址
if (this.asyncHttpClient != null) {
try {
showLoading(); // 弹框加载
this.asyncHttpClient.post(requsetUrl, requestParams, new JsonHttpResponseHandler() {
@SuppressLint("DefaultLocale")
@Override
public void onSuccess(int statusCode, Header[] headers, org.json.JSONObject response) {
super.onSuccess(statusCode, headers, response);
stopLoading();
try {
if (!Axios.isValidCode(Integer.parseInt(response.getString("Tag")))) { // 校验一下后端的给的code是不是合法的,注意这不是http的code,而是业务自己设定的
Toast.makeText(context, response.getString("Message"), Toast.LENGTH_SHORT).show();
} else {
callBackFun.onAxiosSuccess(response); // 调用外部的成功回调方法
}
} catch (JSONException e) {
e.printStackTrace();
}
}
@SuppressLint("DefaultLocale")
@Override
public void onFailure(int statusCode, Header[] headers, Throwable throwable, org.json.JSONObject errorResponse) {
super.onFailure(statusCode, headers, throwable, errorResponse);
callBackFun.onAxiosFailure(errorResponse); // 调用外部失败的回调方法
stopLoading();
if (errorResponse == null) {
Toast.makeText(context, R.string.fail, Toast.LENGTH_SHORT).show();
return;
}
try {
Toast.makeText(context, errorResponse.getString("reason"), Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
super.onFailure(statusCode, headers, responseString, throwable);
callBackFun.onAxiosFailure(responseString);
stopLoading();
Toast.makeText(context, R.string.fail, Toast.LENGTH_SHORT).show();
}
});
} catch (Exception e) {
e.printStackTrace();
stopLoading();
}
}
}
public interface CallBackFun { // 外部用的回调接口
public void onAxiosSuccess(org.json.JSONObject obj);
public void onAxiosFailure(Object obj);
}
public void setOnCallBack(CallBackFun callBackFun) { // 为该对象添加回调接口
this.callBackFun = callBackFun;
}
}
外部使用
Axios axios = new Axios(mainActivity);
axios.setOnCallBack(new Axios.CallBackFun() {
@Override
public void onAxiosSuccess(org.json.JSONObject obj) {
Toast.makeText(mainActivity, "请求成功", Toast.LENGTH_SHORT).show();
}
@Override
public void onAxiosFailure(Object obj) {
Toast.makeText(mainActivity,"请求失败", Toast.LENGTH_SHORT).show();
}
});
RequestParams requestParams = new RequestParams();
requestParams.put("name", "张三");
requestParams.put("age", 18);
axios.post("/xxx/yyy",requestParams); // post携带参数
axios.get("/aaa/bbb?id=1"); // get携带参数