• 浅谈Android客户端项目框架


    Android也有些时间了,一边工作,一边学习,一边积累,只有遇到问题了,花时间去研究,自己的能力才能提升,刀如果不用,慢慢的就会生锈应该也是这个道理吧!上个月公司项目服务器框架进行的一些调整,但是当时自己的项目没有移植框架,还是前人的代码,一下子差点没把我搞死,真是筋疲力尽,一个周末两天全部加班赶,结果赶出来的质量还非常差,等改完了之后大概稳定下来,自己赶紧抽闲余时间把自己的框架移植进去,我的框架是自己慢慢琢磨积累的,拿出来给大家分享一下,有不对的地方,欢迎大家批评指正,谢谢!

    首先,我们要搞客户端的框架,我们就需要考虑一下客户端要作的所有事情:
    1、封装业务数据,用来向服务器发请求
    2、连接服务器,发送网络请求
    3、拿到响应结果,解析数据,给回到自己的界面进行逻辑判断,控制界面显示
    4、根据数据控制自己的界面显示

    以上四点是我所考虑的客户端需要作的事情,第四点我们就不说了,只要拿到了数据 ,界面控制,我们自己实现就可以了,这个时候,服务器的任何异常也影响不了我们,那我们的框架就是基于前三点考虑了。

    结合这次我们公司服务器修改的过程说一下,应该更容易理解:

    服务器之前的框架:只有一个HP,客户端调用的时候,只需要连接HP服务器就可以了,封装业务数据格式如下

    返回的json字符串格式如下图

    就几个字段,非常好解析

    服务器之后的框架:ESB、ACC、HP,一下子多了两个,ESB是整体控制的,就是说你的所有业务调用的时候,不能再调用HP了,必须走ESB,ESB拿到数据后再进行纷发;ACC是账户中心业务,是从之前HP中分离出来的,也就是说之前业务中有属于账户中心的,现在的执行流程是先到ESB,ESB再纷发给ACC,ACC执行完后,把结果给ESB,ESB再将数据返回给客户端,而且ESB封装数据格式和ACC封装数据格式还不一样,ESB数据封装如下:



    ACC数据封装如下:


    外边多加了一层,返回结果数据字段也不一样,这时候大家就明白客户端框架的重要性了!!
    试想一下,如果我们的项目没有框架,回来的数据都是在Activity中处理,根据服务器返回的数据取结果,那服务器的依赖性特别大,如果服务器稍微有点变动,那我们就死定了,每个Activity都要改,工作量大如山啊,而且很容易出错!Android本身强调高内聚,低偶合,这个道理也非常适用于我们客户端和服务器的交互,那我们现在要搭建的框架最应该考虑的,就是不受或者尽量少受服务器影响,不因为服务器变化而产生大的变化,所以,我自己总结出了我自己的客户端项目框架

    其中Common类的大致方法如下:

    /**

    * @param context
    * @param method调用的接口名称
    * @param data调用接口的业务数据
    * @param urltype调用的url地址
    * @param second调用接口的备用字段
    * @return
    */
    public static ResponseBean getHttpResult(RequestBean request){
    ResponseBean response=new ResponseBean();
    String result="";
    HttpResponse httpResponse = returnResponse(request.urltype,request.data.toString());
    try {
    result = EntityUtils.toString(httpResponse.getEntity());
    if (httpResponse != null
    && httpResponse.getStatusLine().getStatusCode() == 200) {
    //服务器utf-8编码,转换为本地GBK编码
    if("0".equals(Constants.isEsb)){
    result=new String(result.getBytes("iso-8859-1"),"utf-8");
    }
    } else {// 请求失败

    }
    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    if(TextUtils.isEmpty(result)){
    response.code="-1";
    response.msg="网络请求失败";
    return response;
    }else{
    return parseResultToBean(result,request,response);
    }
    }


    /**
    * 解析http请求回来的结果
    * @param resulthttp请求返回的字符串
    * @param request请求的完整数据
    * @param response封装好的响应信息
    * @return
    */
    private static ResponseBean parseResultToBean(String result,RequestBean request,ResponseBean response){
    try{
    JSONObject json=new JSONObject(result);
    if("0".equals(request.packtype)){
    response.code=json.getString("resp_code");
    response.msg=json.getString("resp_desc");
    response.data=(JSONObject) json.get("data");
    if("1".equals(response.code)){
    if(Constants.ACC_SYSTEM.equals(request.system)){
    response.code=response.data.getString("resp_code");
    response.msg=response.data.getString("resp_desc");
    if(response.data.has("data")){
    response.array=(JSONArray) response.data.get("data");
    }
    return response;
    }else{
    response.code=response.data.getString("errcode");
    response.msg=response.data.getString("msg");
    if(response.data.has("data")){
    response.array=(JSONArray) response.data.get("data");
    }
    return response;
    }
    }else{
    return response;
    }
    }else{
    if(Constants.ACC_SYSTEM.equals(request.system)){
    response.code=json.getString("resp_code");
    response.msg=json.getString("resp_desc");
    if(json.has("data")){
    response.array=(JSONArray) json.get("data");
    }
    return response;
    }else{
    response.code=json.getString("errcode");
    response.msg=json.getString("msg");
    if(json.has("data")){
    response.array=(JSONArray) json.get("data");
    }
    return response;
    }
    }
    }catch(Exception e){
    e.printStackTrace();
    response.code="-2";
    response.msg="解析结果失败";
    return response;
    }
    }

    /**
    * 封装业务数据
    * @param request

    */
    public static void packRequestData(RequestBean request){
    if(Constants.ACC_SYSTEM.equals(request.system)){
    if("0".equals(request.packtype)){
    request.data=packESBJsonData(request.context, request.data, request.method);
    }else{
    request.data=packCommonJson(request.data, request.context, request.method, request.system);
    }
    }else if(Constants.HP_SYSTEM.equals(request.system)){
    request.data=packCommonJson(request.data, request.context, request.method, request.system);
    if("0".equals(request.packtype)){
    request.data=packESBJsonData(request.context, request.data, request.backupmethod);
    }
    }
    }


    我们可以看到,我只需要构建RequestBean和ResponseBean就可以了,服务器的任何变化,我们只需要在parseResultToBean(将结果解析为Bean)、packRequestData(封装请求数据)这两个方法中屏蔽完,我们要传回给Activity的解析结果,所有的字段都是我们自己定义好的,简单解析如下:

    private void cancleBind(final int type, final String openid) {
    pDialog.show();
    ThreadPool.getInstance().addTask(new Thread(){
    public void run(){
    try {
    if (type == 1) {
    QQInfo.logout(mTencent, BandAccountActivity.this);
    }
    JSONObject data = new JSONObject();
    data.put("bindtype", type+"");
    data.put("userid", Constants.userId);

    RequestBean request=new RequestBean(); 
    request.context=BandAccountActivity.this; 
    request.method="huicloud_remove_bind_sns"; 
    request.backupmethod="";
    request.packtype=Constants.isEsb; 
    request.data=data; 
    request.urltype=Constants.ACC_SYSTEM; 
    request.res="";
    request.array=null;
    request.system=Constants.ACC_SYSTEM; 
    Common.packRequestData(request); 
    ResponseBean response=Common.getHttpResult(request);
    if("1".equals(response.code)){
    handler.obtainMessage(4, type).sendToTarget();
    }else{
    handler.obtainMessage(5, type).sendToTarget();
    }
    Log.d(Constants.TAG, "===BandAccountActivity===取消绑定结果==="
    + response.toString() + "===请求数据===" + request.toString());
    } catch (Exception e) {
    // TODO: handle exception
    e.printStackTrace();
    handler.obtainMessage(2,"网络错误").sendToTarget();
    }
    }
    });
    }


    看到这里,大家基本大致明白我写这篇文章的目的了吧,再次强调一下,我们搭建自己客户端的框架,核心思想就是:产生客户端高内聚,降低与服务端的耦合性!!!
    而RequestBean和ResponseBean的各自属性,大家就可以根据自己的需要来定了,我目前定的属性如下:

    RequestBean:

    /**
    * 上下文环境
    */
    public Context context;

    /**
    * 调用的接口名称
    */
    public String method;

    /**
    * 调用接口的备用字段
    * 因为调用呼朋系统且要经过ESB时,外层接口名称为upeng_app,内层才是真正的业务数据名称
    * 当调用呼朋系统时,此字段必不可少
    */
    public String backupmethod;

    /**
    * 按什么样的要求封装数据
    */
    public String packtype;

    /**
    * 调用接口的业务数据
    */
    public JSONObject data;

    /**
    * 调用接口的url地址
    */
    public String urltype;

    /**
    * 调用接口的备用字段
    */
    public String res;

    /**
    * 备用的array类型
    */
    public JSONArray array;

    /**
    * 调用哪个业务系统
    */
    public String system;

    ResponseBean的属性:

    /**
    * 请求结果码
    */
    public String code;

    /**
    * 请求结果信息
    */
    public String msg;

    /**
    * 按哪种方式解析结果
    */
    public String packtype;

    /**
    * 结果数据
    */
    public JSONObject data;

    /**
    * 备用的结果数据
    */
    public JSONObject res;

    /**
    * 备用的存放多个对象
    */
    public JSONArray array;

    /**
    * 结果为string时,用此字段
    */
    public String result;

    大家在解析结果时,只需要在Common类的parseResultToBean方法中,根据服务器变化后的方式,随意添加自己解析结果的方式就可以了,自己的这个小框架也经过了一些项目的锻炼,自己感觉非常好用,推荐给大家,如果大家有好的提议,欢迎交流,我的QQ:1531074759,自己的框架理解就讲到这。


    转自:http://m.blog.csdn.net/blog/sinat_22657459/41009951
  • 相关阅读:
    松软科技web课堂:SQLServer之UCASE() 函数
    松软科技web课堂:SQLServer之HAVING 子句
    SQLServer之GROUP BY语句
    松软科技web课堂:SQLServer之SUM() 函数
    松软科技web课堂:SQLServer之MIN() 函数
    SQLServer之MAX() 函数
    松软科技web课堂:SQLServer之LAST() 函数
    松软科技带你学开发:SQL--FIRST() 函数
    松软科技带你学开发:SQL--COUNT() 函数
    NodeJS初介
  • 原文地址:https://www.cnblogs.com/miaozhenzhong/p/5931001.html
Copyright © 2020-2023  润新知