简洁
库名称:Httplibs
版本:1.0
此封装库适合开发前期安卓开发选手,用于学习和全国职业技能大赛--移动应用开发赛项,目前封装为第一版本,后续会有更多版本
简介:
Httplibs是一个基于OkHttp的Android网络请求封装库。它简化了OkHttp的使用,提供了更加便捷、灵活的API接口,适用于各类Android开发比赛和项目。尤其是移动应用开发大赛,该库旨在帮助开发者更加高效地处理网络请求,减少重复代码,提高开发效率。
特点:
- 简洁易用:Httplibs提供了简洁明了的函数方法,总共就两个主要的函数分别对应同步请求和异步请求,简化Httplibs网络请求过程。可以减轻代码量
- 针对性强:Httplibs主要针对各类比赛(尤其是移动应用开发赛),支持token加载到头部。
- 性能较强:采用到单例模式运行,后续可能考虑支持并发请求
- :可以统一插入json错误处理代码/错误重启代码
一、配置部分
1.网络权限
首先okhttp是网络请求第三方框架,网络权限肯定是需要具备
<uses-permission android:name="android.permission.INTERNET" />
2.配置usesCleartextTraffic
这个配置表示应用程序是否使用明文网络流量,在API 27前默认为True,后续版本为False,这个配置在<applicantion>中,这里统一把他配置成True
3.配置application节点里配置网络安全
在res文件夹新建xml文件夹,新建一个xml,随意叫什么名字,假设叫network.xml,
需要现在network.xml添加
<?xml version="1.0" encoding="utf-8"?> <network-security-config xmlns:android="http://schemas.android.com/apk/res/android"> <base-config cleartextTrafficPermitted="true" /> </network-security-config>
然后需要在applicant中配置
android:networkSecurityConfig="@xml/network"
其中清单部分2和3的配置,择其一即可,它们在功能上无差别,只是network-securitty-config文件中定义的配置,可以为不同的域名和ip设置不同的明文流量策略,而usesCleartextTraffic是整个applicant的全局配置。对于小项目够用了
4.引入依赖
需要再app级别的build.gradle中配置
implementation 'com.squareup.okhttp3:okhttp:3.14.+'
二、代码部分
1.全局变量
public static Httplibs instance; //单例模式
public static Context context; //弹toast
public static int Result_OK = 0; //成功
public static int Result_Failed =1; //失败
public static String token="";
Serverip和Fileserverip是根据项目而定,对于此封装代码而言可以不必存在
2.单例模式创建
外部需要传入context方便后续操作
private OkHttpClient.Builder client;
private Httplibs() {
client = new OkHttpClient.Builder();
}
// 获取单例实例的方法
public static synchronized Httplibs getInstance(Context mcontext) {
context = mcontext;
if (instance == null) {
instance = new Httplibs();
}
return instance;
}
3.建立接口
这里需要把异步请求成功的消息通知出去,一种封装自带的callback,我们这里将callback自定义化,新建接口
public interface ResponseCallback {
void onResponse(int ResultCode,String responseBody);
}
4.建立数据封装类
这里主要是获取同步的数据封装
public static class ResponseEvent {
int ResultCode;
String responseBody;
public ResponseEvent(int resultCode, String responseBody) {
ResultCode = resultCode;
this.responseBody = responseBody;
}
public int getResultCode() {
return ResultCode;
}
public String getResponseBody() {
return responseBody;
}
}
5.request建立函数
这里为了能两个函数就完全get,post,put,delete,将request放在外部构建,后续可能用method方法一步搞定
public static Request.Builder buildrequest(String url) { //get
return new Request.Builder().url(url);
}
public static Request.Builder buildrequest(String url, JSONObject json) { //post json
RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json.toString());
return new Request.Builder().post(body).url(url);
}
public static Request.Builder buildrequest(String url, FormBody formBody) { //post requestbody
return new Request.Builder().post(formBody).url(url);
}
6.同步请求
public ResponseEvent synchttp(Request.Builder request,boolean headtoken) { //第二个参数后期会换成Map
if (headtoken) request.addHeader("Authorization",token);
StrictMode.ThreadPolicy policy = new StrictMode //很早版本就要求了,必须加
.ThreadPolicy
.Builder()
.permitAll()
.build(); //放入主线程
StrictMode.setThreadPolicy(policy);
client.readTimeout(10, TimeUnit.SECONDS) // 设置读取超时时间为3秒
.connectTimeout(5, TimeUnit.SECONDS) // 设置连接超时时间为3秒
.build();
try {
Response response = client.build().newCall(request.build()).execute();
if (response.isSuccessful()) return new ResponseEvent(Result_OK,response.body().string()); //请求成功的情况
} catch (IOException e) {
//io异常的情况
e.printStackTrace();
Toast.makeText(context,"同步请求失败",Toast.LENGTH_LONG).show();
Log.e("synchttp", "同步请求失败 " );
return new ResponseEvent(Result_Failed,""); //返回一个新建的封装类
}
//response不成功的代码添加在下面,例如可以如下添加toast,或者loge
Toast.makeText(context,"同步请求失败",Toast.LENGTH_LONG).show();
Log.e("synchttp", "同步请求失败 " );
return new ResponseEvent(Result_Failed,"");
}
7.异步请求
public void Asynchttp(Request.Builder request,boolean headtoken ,final ResponseCallback responseCallback) { //第二个参数后期会换成Map
if (headtoken && !TextUtils.isEmpty(token)) request.addHeader("Authorization",token);
client.readTimeout(180, TimeUnit.SECONDS) // 设置读取超时时间为3秒
.connectTimeout(30, TimeUnit.SECONDS) // 设置连接超时时间为3秒
.build();
client.build().newCall(request.build()).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
responseCallback.onResponse(Result_Failed ,"");
//在这里添加处理io异常导致请求失败的代码,例如以下,或者其他
Toast.makeText(context,"异步请求失败",Toast.LENGTH_LONG).show();
Log.e("Asynchttp", "异步请求失败 " );
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) { //这里可以插入一些json处理代码,例如json=401时进行登录
responseCallback.onResponse(Result_OK ,response.body().string()); //回调接口给外部
} else {
//这里一般是服务器对接问题,例如:405接口访问方式不对,500服务器代码错误
Toast.makeText(context,"异步请求失败",Toast.LENGTH_LONG).show();
Log.e("Asynchttp", "异步请求失败 " );
responseCallback.onResponse(Result_Failed ,"");
}
}
});
}
8.完整代码:
package com.yy.httplibsdemo;
import android.content.Context;
import android.os.StrictMode;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import org.json.JSONObject;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class Httplibs {
public static Httplibs instance; //单例模式
public static Context context; //弹toast
public static int Result_OK = 0; //成功
public static int Result_Failed =1; //失败
public static String token="";
private OkHttpClient.Builder client;
private Httplibs() {
client = new OkHttpClient.Builder();
}
// 获取单例实例的方法
public static synchronized Httplibs getInstance(Context mcontext) {
context = mcontext;
if (instance == null) {
instance = new Httplibs();
}
return instance;
}
public interface ResponseCallback {
void onResponse(int ResultCode,String responseBody);
}
public void Asynchttp(Request.Builder request,boolean headtoken ,final ResponseCallback responseCallback) { //第二个参数后期会换成Map
if (headtoken && !TextUtils.isEmpty(token)) request.addHeader("Authorization",token);
client.readTimeout(180, TimeUnit.SECONDS) // 设置读取超时时间为3秒
.connectTimeout(30, TimeUnit.SECONDS) // 设置连接超时时间为3秒
.build();
client.build().newCall(request.build()).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
responseCallback.onResponse(Result_Failed ,"");
//在这里添加处理io异常导致请求失败的代码,例如以下,或者其他
Toast.makeText(context,"异步请求失败",Toast.LENGTH_LONG).show();
Log.e("Asynchttp", "异步请求失败 " );
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) { //这里可以插入一些json处理代码,例如json=401时进行登录
responseCallback.onResponse(Result_OK ,response.body().string()); //回调接口给外部
} else {
//这里一般是服务器对接问题,例如:405接口访问方式不对,500服务器代码错误
Toast.makeText(context,"异步请求失败",Toast.LENGTH_LONG).show();
Log.e("Asynchttp", "异步请求失败 " );
responseCallback.onResponse(Result_Failed ,"");
}
}
});
}
public ResponseEvent synchttp(Request.Builder request,boolean headtoken) { //第二个参数后期会换成Map
if (headtoken) request.addHeader("Authorization",token);
StrictMode.ThreadPolicy policy = new StrictMode //很早版本就要求了,必须加
.ThreadPolicy
.Builder()
.permitAll()
.build(); //放入主线程
StrictMode.setThreadPolicy(policy);
client.readTimeout(10, TimeUnit.SECONDS) // 设置读取超时时间为3秒
.connectTimeout(5, TimeUnit.SECONDS) // 设置连接超时时间为3秒
.build();
try {
Response response = client.build().newCall(request.build()).execute();
if (response.isSuccessful()) return new ResponseEvent(Result_OK,response.body().string()); //请求成功的情况
} catch (IOException e) {
//io异常的情况
e.printStackTrace();
Toast.makeText(context,"同步请求失败",Toast.LENGTH_LONG).show();
Log.e("synchttp", "同步请求失败 " );
return new ResponseEvent(Result_Failed,""); //返回一个新建的封装类
}
//response不成功的代码添加在下面,例如可以如下添加toast,或者loge
Toast.makeText(context,"同步请求失败",Toast.LENGTH_LONG).show();
Log.e("synchttp", "同步请求失败 " );
return new ResponseEvent(Result_Failed,"");
}
public static Request.Builder buildrequest(String url) { //get
return new Request.Builder().url(url);
}
public static Request.Builder buildrequest(String url, JSONObject json) { //post json
RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json.toString());
return new Request.Builder().post(body).url(url);
}
public static Request.Builder buildrequest(String url, FormBody formBody) { //post requestbody
return new Request.Builder().post(formBody).url(url);
}
//同步数据封装
public static class ResponseEvent {
int ResultCode;
String responseBody;
public ResponseEvent(int resultCode, String responseBody) {
ResultCode = resultCode;
this.responseBody = responseBody;
}
public int getResultCode() {
return ResultCode;
}
public String getResponseBody() {
return responseBody;
}
}
}
9.demo案例:
目前后端练习接口在编写中,后续给出
三、缺点分析
1.结果返回
无论是同异步,都是将response.body().string()放入result中输出,这种做法,不仅会将整个请求体加载进内存,并且不能适配response为非字符的情况,因此仅适合竞赛,在1.0.1版本会进行改进
2.性能较差
虽然现在采用单例模式,从一定程度提升性能,但是整体性能还是待改进
3.对head控制较差
目前对于head仅添加常规的token参数:Authorization,在1.0.2进行改进
由福州职业技术学校温辉编写,欢迎搬运帮助更多人,但请带上以上这句。