一、概述
在我们app的开发中,经常会使用一些网络请求,一般我们都会去选择网络上比较的流行的网络框架,如: async_http_client、volley和okhttp等。 通过粗略的研究这么几个网络请求框架。发现他们在网络请求上的封装都差不多. 这样我萌发出了自己也写一个简单的网络请求框架的想法. 废话不多说,来我们一起分析下,一般的框架都有哪些部分组成。
二、简单框架的分析
一般的框架给我们提供的api是非常简单的,一般都有url、params和responseListener等主要的几个参数。让我们不比去关注它是否是在主线程中运行、线程池等问题。其实真正的联网操作肯定是在异步线程中,返回的结果通过回调机制返回给主线程。
三、框架的基本组成
这样我们就可以看出有一个对请求进行配置的类(RequestConfig),里面包含了请求的路径、参数、请求超时时间等. 还有处理真正联网操作的类(MyHttpClient),主要采用了AsyncTask+HttpClient来处理联网操作。还有就是将得到的结果通过回调返回回去(ResponseListener),接下来就是我们提供给别人用的api接口方法的类(RequestHandler)。
RequestConfig.java
/**
* @className:RequestConfig.java
* @classDescription: 请求的相关配置类
*/
public class RequestConfig {
public String requestUrl; //请求路径
public Map<String, String> paramsMap; //请求参数
public List<NameValuePair> fileParams; //文件参数
public int timeOut; //请求超时时间
}
MyHttpClient.java
这是从服务器端请求返回的数据,由于代码太多,只贴出了部分代码,其中 MyHttpClient.getHttpClient(config)方法是对httpclient做了一些处理,包含获取数据buffersize大小和超时时间的设置。
/**
* 返回结果
* @param config
* @return
* @throws Exception
*/
private static String getResponseFromServer(RequestConfig config, String requestMethod) throws Exception {
String response = "";
HttpClient client = MyHttpClient.getHttpClient(config);
List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
HttpPost httpPost = null;
HttpGet httpGet = null;
if (config.requestUrl.startsWith("http://") || config.requestUrl.startsWith("https://")) {
//处理普通请求的参数
if (config.paramsMap != null) {
Iterator<String> v1 = config.paramsMap.keySet().iterator();
while (v1.hasNext()) {
String key = v1.next();
if (config.paramsMap.get(key) == null) {
continue ;
}
params.add(new BasicNameValuePair(key, config.paramsMap.get(key).toString()));
}
}
HttpResponse v2 = null;
if ("GET".equals(requestMethod)) {
httpGet = new HttpGet(config.requestUrl);
v2 = client.execute((HttpUriRequest) httpGet);
} else {
httpPost = new HttpPost(config.requestUrl);
httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
v2 = client.execute((HttpUriRequest) httpPost);
}
//记录返回的头文件
MyHttpClient.logHeaders(v2);
if (v2.getStatusLine().getStatusCode() == 200) {
response = EntityUtils.toString(v2.getEntity(), "UTF-8");
}
LogUtils.e(TAG, "stat code:" + String.valueOf(v2.getStatusLine().getStatusCode()));
httpPost.abort();
} else {
return "";
}
return response;
}
这里采用了AsyncTask对联网操作进行了处理,如果期间出现了异常将会在处理一次,这个在volley框架中也可以看得到。最后请求结果通过responseListener中返回。这里结果进行了封装listener.onResponse(CommonResult.resultWithData(result), result) 根据返回的json数据会初步解析下,得到结果的状态。
/**
* post的请求
* @param config
*/
public static void post(final RequestConfig config, final ResponseListener listener){
LogUtils.e(TAG, "请求路径 : " + config.requestUrl);
AsyncTask asyncTask = new AsyncTask<Object, Integer, String>(){
@Override
protected String doInBackground(Object... params) {
String result = null;
try {
result = MyHttpClient.getResponseFromServer(config, "POST");
} catch (Exception e) {
try {
result = MyHttpClient.getResponseFromServer(config, "POST"); // 错误了 在请求一次
} catch (Exception e1) {
e1.printStackTrace();
// 发生错误时, 将错误信息返回
if (listener != null) {
listener.onResponse(CommonResult.resultWithData(ResultCode.RESULT_CODE_FAILURE, e1.toString()), null);
}
}
}
return result;
}
protected void onPostExecute(String result) {
LogUtils.d(TAG, "返回的结果 : " + result);
if (listener != null) {
if (!TextUtils.isEmpty(result)) {
listener.onResponse(CommonResult.resultWithData(result), result);
}
}
};
};
asyncTask.executeOnExecutor(MyHttpClient.THREAD_POOL_EXECUTOR, 0);
}
ResponseListener.java
这里只有一个接口方法,因为我在CommonResult中做了处理,错误的结果也封装在一起了,得到结果时,需要判断commonResult的状态。然后做相应的数据处理,data为返回的json数据。
public interface ResponseListener {
void onResponse(CommonResult commonResult, String data);
}
RequestHandler.java
提供给别人使用的api接口,根据不同的情况调用不同的方法。
/**
* post的请求,多参数下的使用方式
* @param context
* @param url
* @param params
* @param listener
*/
public static void post(Context context, String url, Map params, int requestTimeout, ResponseListener listener) {
//构建请求配置参数
RequestConfig config = new RequestConfig();
config.requestUrl = url;
config.paramsMap = params;
config.timeOut = requestTimeout;
if (HttpUtils.checkedNetwork(context)) { //先判断有没有网络
MyHttpClient.post(config, listener);
} else {
if (listener != null) {
listener.onResponse(CommonResult.resultWithData(ResultCode.RESULT_CODE_NETWORK_FAILURE, context.getResources().getString(R.string.network_error)), null);
}
}
}
/**
*
* @param context
* @param url
* @param listener
*/
public static void post(Context context, String url, ResponseListener listener) {
RequestHanler.post(context, url, null, 0, listener);
}
/**
*
* @param context
* @param url
* @param params
* @param listener
*/
public static void post(Context context, String url, Map params, ResponseListener listener) {
RequestHanler.post(context, url, params, 0, listener);
}
总结
这里我只是简单的写了个网络请求的demo,其中大部分代码还没有贴上来,其中还有上传下载的部分,我知道这个连基本的框架各种难点都没有涉及到,我主要是写框架的大概思想。算是自己的一个简单的总结吧!
网友评论