一个轻量级的网络架构
来源:互联网 发布:python和java哪个好 编辑:程序博客网 时间:2024/05/21 01:58
目前,Android有许多开源的网络架构,比如官方的volley。今天我讲一下如何去创建自己的网络架构。
首先,要考虑的是用起来方便,大部分的工作都在底层完成。其次,考虑缓存,不同的接口数据可以配置不同的缓存时间。最重要的是,同一个接口,不同参数时的缓存。
下面就是根据我们的项目定制的网络架构:
后端数据采用json传递给APP,APP调用接口的方式,采用URL直接拼接参数和JSON传递参数。
后端约定数据格式JSON: {data:"data",status:0,message:"OK"}
data里面是所需要的数据
status状态码,0表示正常返回;1,用户信息错误照成的错误,此时message里面提示信息直接展示给用户(比如密码不正确);
其他,服务器内部错误,message消息不展示给用户,BUG收集使用
访问接口需要做的工作:访问前,访问后
访问后做的工作:接口正确,返回数据;接口正确,返回数据为空,比如请求列表等操作,获取用户订单(用户没有订单)等。接口错误。
一个Activity中可能有几次访问,需要区分各个访问。
由以上需求,可以制定以下
interface
package lib.bz365.network;/** * 请求接口的回调 */public interface NetWorkCallBack { /** * 网络访问之前的操作 * @param order 标记返回结果 */ void onPreNetTask(int order); /** * 网络访问之后 * @param result 结果 * @param message 需要显示的消息 * @param order 标记返回结果 */ void onFinishFromNet(String result, String message, int order); /** * 网络访问错误 * @param message 需要显示的消息 * @param order 标记返回结果 */ void onErrorFromNet(String message, int order); /** * 返回数据为空 * @param order 标记返回结果 * @param message 需要显示的消息 */ void onDataIsEmpty(int order, String message);}
下面,看以下缓存
我这里将缓存分成了五级,不缓存,秒,分,时,天,并在assets/XML中配置
<?xml version="1.0" encoding="utf-8"?><nodes> <!-- url: cache_type: 0 不缓存,1 秒,2 分,3 时,4 天 cache_value: 缓存对应数值 --><!--缓存时间6小时--> <node cache_type="3" cache_value="6" url="" /></nodes>
这里的url并不带参数,用来配置每个接口的缓存级别,可以创建三个xml,分别配置开发,测试,生产
一般情况下,开发时不使用缓存
缓存文件存储在应用内置缓存文件夹中,通过判断缓存文件的创建更新时间,来判断是否需要更新缓存
缓存的bean:
package lib.bz365.network;public class NetNodeBean { private String url; private int cache_type; private int cache_value; public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public int getCache_type() { return cache_type; } public void setCache_type(int cache_type) { this.cache_type = cache_type; } public int getCache_value() { return cache_value; } public void setCache_value(int cache_value) { this.cache_value = cache_value; } @Override public String toString() { return "NetNodeBean [url=" + url + ", cache_type=" + cache_type + ", cache_value=" + cache_value + "]"; }}
xml解析的类:
package lib.bz365.network;import java.io.IOException;import java.io.InputStream;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import javax.xml.parsers.ParserConfigurationException;import org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.NodeList;import org.xml.sax.SAXException;import com.bz365.project.application.BZApplication;import com.bz365.project.application.ConstantValues;public class XMLParser { public static NetNodeBean parser(String targetUrl) { NetNodeBean netNodeBean = null; InputStream inputStream; try { if (ConstantValues.isDevelop) { inputStream = BZApplication.getInstance().getAssets() .open("net_test.xml"); } else { inputStream = BZApplication.getInstance().getAssets() .open("net.xml"); } DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory .newInstance(); DocumentBuilder builder = documentBuilderFactory .newDocumentBuilder(); Document doc = builder.parse(inputStream); Element rootElement = doc.getDocumentElement(); NodeList items = rootElement.getElementsByTagName("node"); for (int i = 0; i < items.getLength(); i++) { Element node = (Element) items.item(i); String url = node.getAttribute("url"); if (url.equals(targetUrl)) { String cache_type = node.getAttribute("cache_type"); String cache_value = node.getAttribute("cache_value"); netNodeBean = new NetNodeBean(); netNodeBean.setUrl(url); netNodeBean.setCache_type(Integer.parseInt(cache_type)); netNodeBean.setCache_value(Integer.parseInt(cache_value)); break; } else { continue; } } } catch (IOException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } return netNodeBean; }}
缓存文件的操作类:
package lib.bz365.network;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import lib.bz365.util.DebugUtil;import android.os.AsyncTask;import com.bz365.project.application.BZApplication;public class FileCache { public static void saveCache(String fileName, String result) { FileAsyncTask asyncTask = new FileAsyncTask(fileName, result); asyncTask.execute(); } public static String getCache(String fileName){ String result = ""; File file = new File(BZApplication.getInstance().getCacheDir(), fileName); if(!file.exists()){ DebugUtil.LogD("cache", "缓存为空"); return result; } FileInputStream inputStream; try { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); inputStream = new FileInputStream(file); byte[] data = new byte[1024]; int len = 0; while((len = inputStream.read(data))!=-1){ outputStream.write(data, 0, len); } result = new String(outputStream.toByteArray(), "UTF-8"); DebugUtil.LogD("cache", "从文件中提取" + outputStream.toString()); inputStream.close(); outputStream.close(); DebugUtil.LogD("cache", "从文件中提取"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return result; } public static long getFileUpdateTime(String fileName){ File file = new File(BZApplication.getInstance().getCacheDir(), fileName); if(!file.exists()){ DebugUtil.LogD("cache", "缓存为空"); return 0l; } return file.lastModified(); } private static class FileAsyncTask extends AsyncTask<String, Void, String>{ private String fileName; private String result; public FileAsyncTask(String fileName, String result){ this.fileName = fileName; this.result = result; } @Override protected String doInBackground(String... arg0) { File file = new File(BZApplication.getInstance().getCacheDir(), fileName); if(file.exists()){ file.delete(); } try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } FileOutputStream outputStream; try { outputStream = new FileOutputStream(file); outputStream.write(result.getBytes()); outputStream.close(); DebugUtil.LogD("cache", "保存到文件"); } catch (Exception e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(String result) { } }}
下面就是网络访问类,这里,调用网络接口时,不用考虑缓存,和接口返回的数据判断:
package lib.bz365.network;import java.util.Date;import lib.bz365.util.DebugUtil;import lib.bz365.util.MD5;import lib.bz365.util.StringUtil;import org.json.JSONException;import org.json.JSONObject;import com.bz365.project.application.BZApplication;import com.bz365.project.application.ConstantValues;import android.os.AsyncTask;public class AsynTaskForNet extends AsyncTask<String, Void, String> { /** * 需要单独对待的状态码 */ private int mark_Status; /** * 是否有特殊标记 */ private boolean hasMark; /** * 标记返回 */ private int order; private NetWorkCallBack callBack; public AsynTaskForNet(NetWorkCallBack callBack, int order) { this.hasMark = false; this.callBack = callBack; this.order = order; } public AsynTaskForNet(int mark_Status, NetWorkCallBack callBack, int order) { this.mark_Status = mark_Status; this.hasMark = true; this.callBack = callBack; this.order = order; } /** * * @param url * URL * @param connect * URL后拼接的参数 * @param jsonString * 参数 */ public void getDatafromNet(String url, String connect, String jsonString) { execute(url, connect, jsonString); } /** * 是否需要保存缓存数据 */ private boolean saveCache; @Override protected String doInBackground(String... arg0) { if (isCache(arg0[0], arg0[1], arg0[2])) { return getCache(arg0[0], arg0[1], arg0[2]); } else { return WebServiceClient.doPostJson(arg0[0] + arg0[1], arg0[2]); } } @Override protected void onPreExecute() { callBack.onPreNetTask(order); } @Override protected void onPostExecute(String result) { if (StringUtil.isEmpty(result)) { callBack.onErrorFromNet("网络错误,请稍后再试", order); return; } try { JSONObject jsonObject = new JSONObject(result); int status = jsonObject.getInt("status"); String message = jsonObject.getString("message"); String data = jsonObject.getString("data"); if (status == 0) { if ("null".equals(data) || "[]".equals(data) || "{}".equals(data) || StringUtil.isEmpty(data)) { callBack.onDataIsEmpty(order, message); } else { if (saveCache) FileCache.saveCache(cacheMark, result); callBack.onFinishFromNet(result, message, order); } } else { if (hasMark && status == mark_Status) { if (saveCache) FileCache.saveCache(cacheMark, result); callBack.onFinishFromNet(result, message, order); } else { if (status == 1) { callBack.onErrorFromNet(message, order); } else { callBack.onErrorFromNet("网络错误,请稍后再试", order); } } } } catch (JSONException e) { e.printStackTrace(); callBack.onErrorFromNet("网络错误,请稍后再试", order); } } private String cacheMark; /** * 判断是否需要缓存 * * @param url * @param connect * @param jsonString * @return */ private boolean isCache(String url, String connect, String jsonString) { cacheMark = MD5.getMessageDigest((url + connect + jsonString) .getBytes()); NetNodeBean netNodeBean = XMLParser.parser(url); if (netNodeBean != null) { int cache_type = netNodeBean.getCache_type(); int cache_value = netNodeBean.getCache_value(); long cacha_time = 0l; long file_time = FileCache.getFileUpdateTime(cacheMark); if (cache_type == 0) { saveCache = false; return false; } else if (cache_type == 1) { saveCache = true; cacha_time = cache_value * 1000; } else if (cache_type == 2) { saveCache = true; cacha_time = cache_value * 1000 * 60; } else if (cache_type == 3) { saveCache = true; cacha_time = cache_value * 1000 * 60 * 60; } else if (cache_type == 4) { saveCache = true; cacha_time = cache_value * 1000 * 60 * 60 * 24; } if (file_time == 0) { return false; } long cur_time = new Date().getTime(); if ((cur_time - cacha_time) < file_time) { saveCache = false; return true; } } return false; } /** * 返回缓存数据 * * @param url * @param connect * @param jsonString * @return */ private String getCache(String url, String connect, String jsonString) { return FileCache.getCache(cacheMark); }}
下面是网络访问类;Android5.0后不支持httpclient,所以采用httpurlclicent
package lib.bz365.network;import com.bz365.project.utils.statistics.StatisicsUtil;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.OutputStream;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.net.URLEncoder;import lib.bz365.util.CommonUtils;import lib.bz365.util.DebugUtil;import lib.bz365.util.StringUtil;import lib.bz365.util.SystemOutUtil;public class WebServiceClient { public static String doPostJson(String urlString, String jsonString) { try { URL url = new URL(urlString); SystemOutUtil.systemOut(urlString); HttpURLConnection http = (HttpURLConnection) url.openConnection(); http.setRequestProperty("android-version", CommonUtils.getVersionCode()); http.setRequestProperty("app_channel", URLEncoder.encode(StatisicsUtil.getChannel(), "UTF-8")); http.setRequestMethod("POST"); http.setRequestProperty("Content-Type", "application/json"); http.setDoOutput(true); http.setDoInput(true); http.setUseCaches(false); System.setProperty("sun.net.client.defaultConnectTimeout", "10000");// 连接超时30秒 System.setProperty("sun.net.client.defaultReadTimeout", "10000"); // 读取超时30秒 if (!StringUtil.isEmpty(jsonString)) { OutputStream os = http.getOutputStream(); DebugUtil.LogD(jsonString.toString()); os.write(jsonString.toString().getBytes("UTF-8"));// 传入参数 os.flush(); os.close(); } http.connect(); DebugUtil.LogD("httpcode=" + http.getResponseCode()); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte[] data = new byte[1024]; int len = 0; if (null != http.getInputStream()) while ((len = http.getInputStream().read(data)) != -1) { outputStream.write(data, 0, len); } String message = new String(outputStream.toByteArray(), "UTF-8"); DebugUtil.LogD(message); SystemOutUtil.systemOut(message); return message; } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return "失败"; }}
使用:
/** * 雷达图页面 */public class RadarActivity extends AppBaseActivity implements RadarView.OnSelectItemListener, NetWorkCallBack,
@Override public void onPreNetTask(int order) { showProgress(); } @Override public void onFinishFromNet(String result, String message, int order) { closeProgress(); DebugUtil.LogE("result", result); try { surpriseData = JsonUtils.toBean(result, new TypeToken<SurpriseData>() { }.getType()); //TODO } catch (AppException e) { e.printStackTrace(); } } @Override public void onErrorFromNet(String message, int order) { closeProgress(); ShowToast(message); } @Override public void onDataIsEmpty(int order, String message) { closeProgress(); }
- 一个轻量级的网络架构
- 自己动手写一个轻量级的Android网络请求框架
- 自己动手写一个轻量级的Android网络请求框架
- 一个轻量级的单写多读锁
- 一个轻量级的信号量
- 一个轻量级网络通信开发库源码
- 我的一个网络层架构
- tiny-blog项目设计介绍(一个基于LAMP架构的轻量级博客系统)
- 一个轻量级的事件对象
- 一个轻量级的分页框架
- peewee 一个轻量级的ORM
- nanobar一个轻量级的进度条
- 一个易用的轻量级的网络爬虫(Easy to use lightweight web crawler)
- 对AF的二次封装--ELNetworking(一个轻量级的iOS网络层)
- 继文章‘’ 自己动手写一个轻量级的Android网络请求框架‘’后续------增加缓存功能
- 继文章‘’ 自己动手写一个轻量级的Android网络请求框架‘’补充------增加进度回调
- 轻量级微服务框架的通信架构
- 轻量级网络
- Python爬虫入门六之Cookie的使用
- SQL 查询每个人第一次考试成绩
- Mysql数据库DML操作delete不支持表的别名操作
- C#递归遍历树节点并且存储
- android ViewDragHelper介绍
- 一个轻量级的网络架构
- 文件夹路径 String savePath ="D:\\web\\new\\DownLoad";
- Android Studio使用Git创建分支,合并分支
- Python爬虫入门七之正则表达式
- bzoj2594
- 你应该知道的AssetBundle管理机制
- iOS应用程序生命周期
- cmake使用一例
- UISearchBar 和 UISearchController