个人博客
http://www.milovetingting.cn
Android中网络框架的简单封装
前言
Android
作为一款主要应用在移动终端的操作系统,访问网络是必不可少的功能。访问网络,最基本的接口有:HttpUrlConnection
,HttpClient
,而在后续的发展中,出现了Volley
,OkHttp
,Retrofit
等网络封装库。由于各种原因,在实际的项目开发中,我们可能会需要在项目的版本迭代中,切换网络框架。如果对于网络框架没有好的封装,那么当需要切换网络框架时,可能就会有大量的迁移工作要做。
封装网络框架
在架构设计中,面向接口
和抽象
,是解耦的一个重要原则。本文将基于这一原则,实现一个简单的网络框架封装。
定义网络访问的接口
抽取出不同网络框架的共同方法,定义成接口方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public interface IHttpLoader {
void get(String url, Map<String, Object> params, IHttpCallback 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 {
void onSuccess(String result);
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); }
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 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