一个轻量级的网络架构

来源:互联网 发布: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();    }

0 0
原创粉丝点击