您的位置:首页 > 理论基础 > 计算机网络

Android中搭建自己的项目网络框架

2018-03-22 21:31 591 查看
Android发展至今,先后出现了许多流行的网络框架,比如Xutils、OkHttp、Volley、Retrofit等框架,但是作为开发者,我们也应有自己的搭建网络框架的能里,以自己的项目“量体裁衣”,另一方面,不是每一个网络框架都是没有缺点的比如

Xutils 网络请求框架的弊端:

1、请求方式、地址、参数都拆开了,应该封装到一个对象里面

2、请求之前应该判断网络

3、每次请求都new了一个RequestCallBack对象

4、请求得到的响应不知道是那次请求发出的

5、json的解析封装是耗时的操作不应该放到主线程

6、gson解析用流比字符串效率高很多

7、httpUtils基于HttpClient , HttpUrlConnection 扩展性很差,如果项目要用OkHttp之类的 NoHttp

8、错误的处理不应该让子类来处理

9、请求的响应应该分为三种:成功、其他的情况、错误

现在我们开始搭建网络框架,下面是我们网络搭建的时序图:



添加依赖 okhttp、Gson

implementation ‘com.squareup.okhttp3:okhttp:3.10.0’ compile

compile ‘com.google.code.gson:gson:2.8.2’

添加权限:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />


/**
* Created by MG_ZXC on 2018/3/22.
* 封装:请求方式, 请求地址, 请求参数
*/

public abstract class BaseRequest {
public enum HttpMethod{
GET,POST;
}
public abstract HttpMethod getMethod();
public abstract String getUrl();
public abstract Map<String, String> getParams();
}


BaseResponse类封装响应:

/**
* Created by MG_ZXC on 2018/3/22.
* 响应json数据的封装
*/

public abstract class BaseResponse <T> {
//响应码
public int code;

public T data;

public boolean success() {
return code >= 200 && code < 300;
}
}


声明接口 Callback结果回调:

/**
* Created by MG_ZXC on 2018/3/22.
* 请求结果回调
*  为了回调的时候告知当前的响应是哪次请求发出的,响应的方法把请求的BaseRequest传入
*/

public interface Callback <Res extends BaseResponse>  {
void onError(BaseRequest request, Exception e);
void onOther(BaseRequest request, Res response);
void onSuccess(BaseRequest request, Res response);
}


通过NetUtil发送网络请求:

public class NetUtil {
private static ConnectivityManager connectivityManager;

public static void init(Context context) {
connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
}

private static boolean checkNet() {
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isAvailable();
}

/**
* 通过NetUtil发送网络请求
*
* @param request       请求的参数
* @param responseClass 相应的自字节码
* @param callback      请求的回调结果
* @param <Res>
*/
public static <Res extends BaseResponse> void sendRequest(BaseRequest request, Class<Res> responseClass, Callback callback) {

//请求之前检查网络
if (checkNet()) {

new NetTask().execute(new NetBean(request, responseClass, callback));
} else {

callback.onError(request, new IllegalStateException("请检查网络"));
}
}

//需要的对象:BaseRequest, Callback
private static class NetTask extends AsyncTask<NetBean, Void, NetBean> {
@Override
protected NetBean doInBackground(NetBean[] params) {
NetBean netBean = params[0];
try {
Reader readerResponse = HttpWrapper.getInstance().getReaderResponse(netBean.request);
BaseResponse response = new Gson().fromJson(readerResponse, netBean.responseClass);
netBean.response = response;
} catch (IOException e) {
e.printStackTrace();
netBean.exception = e;
} catch (JsonParseException e) {
e.printStackTrace();
netBean.exception = e;
} catch (Exception e) {
e.printStackTrace();
netBean.exception = e;
}
return netBean;
}

@Override
protected void onPostExecute(NetBean netBean) {
//出现了异常
if (netBean.exception != null) {
netBean.callback.onError(netBean.request, netBean.exception);
} else {
if (netBean.response.success()) {
netBean.callback.onSuccess(netBean.request, netBean.response);
} else {
netBean.callback.onOther(netBean.request, netBean.response);
}
}
}
}

private static class NetBean {
public NetBean(BaseRequest request, Class<? extends BaseResponse> responseClass, Callback callback) {
this.request = request;
this.callback = callback;
this.responseClass = responseClass;
}

BaseRequest request;
Callback callback;
Class<? extends BaseResponse> responseClass;
//json解析封装的结果对象BaseResponse response
BaseResponse response;
Exception exception;
}
}


声明 HttpWrapper 对Http封装 :

/**
* Created by MG_ZXC on 2018/3/22.
* Http的封装,真正执行网络请求: OkHttp封装
*/

public class HttpWrapper {
private volatile static HttpWrapper singleton;
private final OkHttpClient okHttpClient;

private HttpWrapper() {
okHttpClient = new OkHttpClient();
}

public static HttpWrapper getInstance() {
if (singleton == null) {
synchronized (HttpWrapper.class) {
if (singleton == null) {
singleton = new HttpWrapper();
}
}
}
return singleton;
}

//执行请求 get请求 :请求参数url?username=zxc&password=123
//post    在请求体
public Reader getReaderResponse(BaseRequest request) throws IOException {
return getResponseBody(request).charStream();
}

public String getStringResponse(BaseRequest request) throws IOException {
return getResponseBody(request).string();
}

public byte[] getBytesResponse(BaseRequest request) throws IOException {
return getResponseBody(request).bytes();
}

public InputStream getInputStreamResponse(BaseRequest request) throws IOException {
return getResponseBody(request).byteStream();
}

private ResponseBody getResponseBody(BaseRequest request) throws IOException {
Request.Builder builder = new Request.Builder();
if (request.getMethod() == BaseRequest.HttpMethod.GET) {
StringBuilder stringBuilder = new StringBuilder(request.getUrl());
Map<String, String> params = request.getParams();
if (params != null && params.size() > 0) {
stringBuilder.append("?");
Set<String> keySet = params.keySet();
for (String key : keySet) {
stringBuilder.append(key).append("=").append(URLEncoder.encode(params.get(key), "UTF-8")).append("&");
}
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
}
builder.url(stringBuilder.toString()).get();
} else if (request.getMethod() == BaseRequest.HttpMethod.POST) {
//添加请求参数到请求体
FormBody.Builder formBody = new FormBody.Builder();
Map<String, String> params = request.getParams();
if (params != null && params.size() > 0) {
Set<String> keySet = params.keySet();
for (String key : keySet) {
formBody.addEncoded(key, params.get(key));
}
}
builder.url(request.getUrl()).post(formBody.build());
}
ResponseBody body = okHttpClient.newCall(builder.build()).execute().body();
return body;
}
}


使用方式:

1,在 Application 中初始化 :

NetUtil.init(getApplicationContext());


2,使用

NetUtil.sendRequest(new TestRequest(), TestResponse.class, new Callback<TestResponse>() {
@Override
public void onError(BaseRequest request, Exception e) {

Toast.makeText(mContext, e.getMessage(), Toast.LENGTH_SHORT).show();
}

@Override
public void onOther(BaseRequest request, TestResponse response) {

Toast.makeText(mContext, "其他错误", Toast.LENGTH_SHORT).show();
}

@Override
public void onSuccess(BaseRequest request, TestResponse response) {

TestData data = response.data;
content.setText(data.toString());
showSuccesStateView();
}

});


public class TestData {
/**
* name : sz
* score : 100
* sex : true
*/

private String name;
private int score;
private boolean sex;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getScore() {
return score;
}

public void setScore(int score) {
this.score = score;
}

public boolean isSex() {
return sex;
}

public void setSex(boolean sex) {
this.sex = sex;
}

@Override
public String toString() {
return "TestData{" +
"name='" + name + '\'' +
", score=" + score +
", sex=" + sex +
'}';
}
}


public class TestResponse extends BaseResponse<TestData> {
}


public class TestRequest implements BaseRequest {
@Override
public HttpMethod getMethod() {
return HttpMethod.POST;
}

@Override
public String getUrl() {
return Constant.format("TestServlet");
}

@Override
public Map<String, String> getParams() {
HashMap<String, String> map = new HashMap<>();
map.put("username", "itcast");
map.put("password", "123&heima");
return map;
}
}


以上是网络框架的基本用法。实际上在开发中还可以优化形式出现比如(在基类中进行除数据请求成功的页面设置,在子类中进行,发送数据请求和处理数据请求正确的情况的):

在基类BaseFragment:

private OnSuccessCallback mOnSuccessCallback;
//由父类发出请求在通知子类,错误,空数据由父类处理
public void sendRequest(BaseRequest request, Class<? extends BaseResponse> responseClass, OnSuccessCallback onSuccessCallback) {

mOnSuccessCallback = onSuccessCallback;
NetUtil.sendRequest(request, responseClass, this);
}

@Override
public void onError(BaseRequest request, Exception e) {
//在基类中统一进行错误处理,比如错误页面的展示
}

@Override
public void onOther(BaseRequest request, BaseResponse response) {
Toast.makeText(mContext, "其他错误", Toast.LENGTH_SHORT).show();
}

//请求通知子类
@Override
public void onSuccess(BaseRequest request, BaseResponse response) {

if (response == null || response.data == null) {
// 数据为空的情况
} else {
//展示成功页面由子类处理
mOnSuccessCallback.onSuccess(request, response);
}
}


声明数据请求成功的情况的接口

public interface OnSuccessCallback<Res extends BaseResponse> {
public void onSuccess(BaseRequest request, Res response);
}


在子类中进行处理成功数据请求情况:

//调用父类sendRequest
sendRequest(new TestRequest(), TestResponse.class, new OnSuccessCallback<TestResponse>() {
@Override
public void onSuccess(BaseRequest request, TestResponse response) {
//获取请求数据
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: