个人博客

http://www.milovetingting.cn

Android中网络框架的简单封装

前言

Android作为一款主要应用在移动终端的操作系统,访问网络是必不可少的功能。访问网络,最基本的接口有:HttpUrlConnection,HttpClient,而在后续的发展中,出现了VolleyOkHttpRetrofit等网络封装库。由于各种原因,在实际的项目开发中,我们可能会需要在项目的版本迭代中,切换网络框架。如果对于网络框架没有好的封装,那么当需要切换网络框架时,可能就会有大量的迁移工作要做。

封装网络框架

在架构设计中,面向接口抽象,是解耦的一个重要原则。本文将基于这一原则,实现一个简单的网络框架封装。

定义网络访问的接口

抽取出不同网络框架的共同方法,定义成接口方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public interface IHttpLoader {

/**
* GET方式请求
*
* @param url
* @param params
* @param callback
*/
void get(String url, Map<String, Object> params, IHttpCallback callback);

/**
* POST方式请求
*
* @param url
* @param params
* @param callback
*/
void post(String url, Map<String, Object> params, IHttpCallback callback);

}

定义网络访问的Callback

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface IHttpCallback {

/**
* 成功时的回调
*
* @param result
*/
void onSuccess(String result);

/**
* 失败时的回调
*
* @param msg
*/
void onFailed(String msg);

}

定义具体的接口实现类

分别对具体的网络框架进行接口实现,这里以Volley和OkHttp为例

Volley的实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class VolleyHttpLoader implements IHttpLoader {

private static RequestQueue mRequestQueue;

public VolleyHttpLoader(Context context) {
mRequestQueue = Volley.newRequestQueue(context);
}

@Override
public void get(String url, Map<String, Object> params, final IHttpCallback callback) {
StringRequest request = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
@Override
public void onResponse(String s) {
callback.onSuccess(s);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
callback.onFailed(volleyError.toString());
}
});
mRequestQueue.add(request);
}

@Override
public void post(String url, Map<String, Object> params, final IHttpCallback callback) {
StringRequest request = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
@Override
public void onResponse(String s) {
callback.onSuccess(s);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
callback.onFailed(volleyError.toString());
}
});
mRequestQueue.add(request);
}
}

OkHttp的实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public class OkHttpLoader implements IHttpLoader {

private static OkHttpClient mOkHttpClient;

public OkHttpLoader() {
mOkHttpClient = new OkHttpClient();
}


@Override
public void get(String url, Map<String, Object> params, final IHttpCallback callback) {
Request request = new Request.Builder().url(url).build();
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
callback.onFailed(e.toString());
}

@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
if (response.isSuccessful()) {
String result = response.body().string();
callback.onSuccess(result);
} else {
callback.onFailed(response.message());
}
}
});
}

@Override
public void post(String url, Map<String, Object> params, final IHttpCallback callback) {
RequestBody requestBody = appendBody(params);
Request request = new Request.Builder().post(requestBody).url(url).build();
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
callback.onFailed(e.toString());
}

@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
if (response.isSuccessful()) {
String result = response.body().string();
callback.onSuccess(result);
} else {
callback.onFailed(response.message());
}
}
});
}

private RequestBody appendBody(Map<String, Object> params) {
FormBody.Builder body = new FormBody.Builder();
if (params == null || params.isEmpty()) {
return body.build();
}
for (Map.Entry<String, Object> entry : params.entrySet()) {
body.add(entry.getKey(), entry.getValue().toString());
}
return body.build();
}
}

定义Callback的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public abstract class HttpCallback<Result> implements IHttpCallback {

@Override
public void onSuccess(String result) {
Gson gson = new Gson();
Class<?> clazz = analysisClazzInfo(this);
Result resultObj = (Result) gson.fromJson(result, clazz);
onSuccess(resultObj);
}

/**
* 成功时的回调
*
* @param result
*/
public abstract void onSuccess(Result result);

private Class<?> analysisClazzInfo(Object object) {
Type genType = object.getClass().getGenericSuperclass();
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
return (Class<?>) params[0];
}
}

返回的数据Bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
public class Data {

private int errorCode;
private String errorMsg;
private List<DataBean> data;

public int getErrorCode() {
return errorCode;
}

public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}

public String getErrorMsg() {
return errorMsg;
}

public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}

public List<DataBean> getData() {
return data;
}

public void setData(List<DataBean> data) {
this.data = data;
}

public static class DataBean {

private int courseId;
private int id;
private String name;
private int order;
private int parentChapterId;
private boolean userControlSetTop;
private int visible;
private List<?> children;

public int getCourseId() {
return courseId;
}

public void setCourseId(int courseId) {
this.courseId = courseId;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

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

public int getOrder() {
return order;
}

public void setOrder(int order) {
this.order = order;
}

public int getParentChapterId() {
return parentChapterId;
}

public void setParentChapterId(int parentChapterId) {
this.parentChapterId = parentChapterId;
}

public boolean isUserControlSetTop() {
return userControlSetTop;
}

public void setUserControlSetTop(boolean userControlSetTop) {
this.userControlSetTop = userControlSetTop;
}

public int getVisible() {
return visible;
}

public void setVisible(int visible) {
this.visible = visible;
}

public List<?> getChildren() {
return children;
}

public void setChildren(List<?> children) {
this.children = children;
}

@Override
public String toString() {
return "DataBean{" +
"courseId=" + courseId +
", id=" + id +
", name='" + name + '\'' +
", order=" + order +
", parentChapterId=" + parentChapterId +
", userControlSetTop=" + userControlSetTop +
", visible=" + visible +
", children=" + children +
'}';
}
}

@Override
public String toString() {
return "Data{" +
"errorCode=" + errorCode +
", errorMsg='" + errorMsg + '\'' +
", data=" + data +
'}';
}

}

定义统一管理类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class HttpHelper implements IHttpLoader {

private static IHttpLoader mHttpLoader;

private HttpHelper() {

}

public static void init(IHttpLoader httpLoader) {
mHttpLoader = httpLoader;
}

public static HttpHelper obtain() {
return HttpHelperHolder.INSTANCE;
}

static class HttpHelperHolder {
private static HttpHelper INSTANCE = new HttpHelper();
}

@Override
public void get(String url, Map<String, Object> params, IHttpCallback callback) {
mHttpLoader.get(url, params, callback);
}

@Override
public void post(String url, Map<String, Object> params, IHttpCallback callback) {
mHttpLoader.post(url, params, callback);
}
}

在Application中初始化

定义一个继承自Application的类,在onCreate方法中初始化网络访问

1
2
3
4
5
6
7
8
9
public class App extends Application {

@Override
public void onCreate() {
super.onCreate();
// HttpHelper.init(new OkHttpLoader());
HttpHelper.init(new VolleyHttpLoader(this));
}
}

后续如果需要切换网络框架,只需要在这里修改就可以了。

应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class MainActivity extends AppCompatActivity {

private static final String URL_HTTP = "https://www.wanandroid.com/wxarticle/chapters/json";

private ImageView mIv;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mTv = findViewById(R.id.tv);

findViewById(R.id.btn_get).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
HttpHelper.obtain().get(URL_HTTP, null, new HttpCallback<Data>() {
@Override
public void onFailed(final String msg) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mTv.setText(msg);
}
});
}

@Override
public void onSuccess(final Data data) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mTv.setText(data.toString());
}
});
}
});
}
});

}
}

结束

这里介绍的,其实只是一个封装的思路。基于这个思路,还可以封装常用的图片访问库等。可以自由拓展。

源码

源码地址:https://github.com/milovetingting/Samples/tree/master/Loader