通用网络框架,可支持okhttp3,volley等

本文介绍了一个清晰的三层网络框架设计思路,包括底层网络调用、中间层封装和应用层调用。详细展示了如何实现网络请求、回调接口及错误处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为什么会突然想写这个呢,一个是太长时间没碰博客了,忙着做项目,另一个是接手了几个烂项目,才知道这东西又多么重要!!被坑的

言归正传,做一个网络框架,需要做到什么呢?

层次分明,这里我归类为三层

1)底层网络调用,所有的网络都会经过底层这里,方便做统一的管理   BaseHttpRequest

(家里总要有一个管事的)

2)中间层封装,为了隔离代码与底层,并且方便开发者处理网络接口,这里统一将网络接口封装到一起,方便看,方便改    NetRequest

                

3)应用层调用,好的接口调用在应用层应该就只有一行代码,这样不会有过多的冗余的东西要处理。


                                                                                    层思想很丰满,现实很骨感,素不素感觉还是无从下手!!!

1.先选择网络框架(其实你选啥都一样,我这种设计所有网络框架通吃!!),这里选择afinal作为示例。

2.准备好jar包丢到libs目录下,网上随便下一个就好了,afinal_0.5.1_bin.jar

3.创建BaseHttpRequest.class

1 )先写构造函数,无论何时都会需要上下文滴,并初始化fh

public BaseHttpRequest(Context context) {
    this.context = context;
    fh = getFh();
}

public FinalHttp getFh() {
    if (fh == null) {
        fh = new FinalHttp();
        fh.configTimeout(30 * 1000); // 设置超时连接 10秒
    }
    return fh;
}

2)考虑到用get请求选择太少了,毕竟不安全,这里直接用POST,需要用GET自己稍微改一下就好了。

做这一步先你要知道一个东西,我们网络请求网络接口的时候,一般服务器域名是不会变的,变的只是不同接口调用不同的service跟传不同的params参数

所以,调用post请求之前,先把url的各部分传递过来,组装成url后并打印,方便调试。

serviceAction:service的访问路径

requestId:简单的标示,这样的话在同一个页面调用多个网络接口时候,可以区分,这个跟startActivityforResult时候多传个参数是同个道理。

url:服务器地址

params:接口封装好的参数,是键值对格式

ifShosDialog:考虑网络请求时候一般都需要考虑弱网情况,所以这里加个字段判断是否需要显示加载框,一定不要写死,因为实际应用中往往会有需求是偷偷调接口,那时候就不要加载框了~createLoadingDialog我就不贴代码了,你根据你喜欢自己画吧。

这里需要注意一点:不同公司后台肯定要有自己的规范,所以这里要提前约定好,网络请求成功之后返回统一的格式是什么,这里就跟后台商量好了,如果成功就会返回succ,数据统一丢到data里面,失败就返回error_msg

{"rsp_code":"succ","data":{"version_code":57,"version_name"}

public void doPostRquest(String serviceAction, final int requestId, String url, AjaxParams params,
                         final boolean ifShowDialog) {
    Log.i("zyl", "requestURL:" + url + serviceAction + "?" + params.toString());
    fh.post(url + serviceAction, params, ajaxcallback = new AjaxCallBack<Object>() {
        @Override
        public void onStart() {
            super.onStart();
            if (ifShowDialog) {
                if (loadingDialog == null) {
                    createLoadingDialog(context, "数据加载中...");
                }
                loadingDialog.show();
            }
        }

        @Override
        public void onSuccess(Object t) {
            super.onSuccess(t);
            loadingDialog.dismiss();
            String result = t.toString();
            try {
                JSONObject json = new JSONObject(result);
                String rspCode = json.getString("rsp_code");
                Log.v("zyl", "onSuccess:" + result);
                if (rspCode.equals("succ")) {
                    String data = json.getString("data");
                    ResultEntity resultEntity = new ResultEntity("", data, requestId);
                    Message message = new Message();
                    message.what = HANDLER_WHAT_SUCESS;
                    message.obj = resultEntity;
                    baseHandler.sendMessage(message);
                } else {
                    String msg = json.getString("error_msg");
                    if (msg.contains("token")) {
                      	//token失效重新登录这里严谨一点应该返回固定的code,收到这信号就去重新登录就对了。
                        baseHandler.sendEmptyMessageDelayed(EXIT, 0);
                    } else {
                        Message message = new Message();
                        message.what = HANDLER_WHAT_FAIL;
                        ResultEntity resultEntity = new ResultEntity(msg, "", requestId);
                        message.obj = resultEntity;
                        baseHandler.sendMessage(message);
                    }
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        /**
         * 处理请求失败的回调函数
         */
        @Override
        public void onFailure(Throwable t, int errorNo, String strMsg) {
            Log.i("zyl", "onAfinalFail:" + strMsg);
            if (loadingDialog != null) {
                loadingDialog.dismiss();
            }
            super.onFailure(t, errorNo, strMsg);
            Message message = new Message();
            message.what = HANDLER_WHAT_NET;
            ResultEntity resultEntity = new ResultEntity("", "", requestId);
            message.obj = resultEntity;
            baseHandler.sendMessage(message);
        }
    });
}


就是这么简单!!网络请求成功之后拿到了data,然后将数据封装到下面的实体bean里面,成功的时候一般我关心data,失败的时候我们关心失败的原因msg.   

public class ResultEntity {
    String msg;             //失败原因
    String data;            //成功返回数据
    int requestId;          //请求的标示,区分不同的网络请求

    public ResultEntity(String msg, String data, int requestId) {
        this.msg = msg;
        this.data = data;
        this.requestId = requestId;
    }
}
ok,到这里我们已经从onSuccess拿到接口调用成功的数据或者被拒绝原因,从onFailure拿到网络调用失败的原因

那么,怎么传回给NetRequest,再传回应用层呢??????????

写个回调接口:

public interface IOnHttpListener {
    /**
     * 网络请求失败(没有网络或连接服务器原因)
     *
     * @param requestId
     */
    void onAfinalFail(int requestId);

    /**
     * 网络请求成功,拿到想要的数据result,一般msg用不上。
     *
     * @param requestId
     * @param result
     */
    void onExecuteSuccess(int requestId, String result, String msg);

    /**网络通的,但请求方式有误或者数据有误失败;
     * 返回失败信息
     *
     * @param requestId
     *            请求id
     * @param result
     *            失败提示
     */
    void onExecuteFail(int requestId, String msg);
}

回调用法就很简单了吧。在Activity实现这个接口,重写下面三个方法

public class MainActivity extends BaseActivity implements IOnHttpListener {
    private NetRequest netRequest;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(com.netframework.R.layout.activity_main);
        netRequest = new NetRequest(this);
        netRequest.requestCheckVersion(1,true);
    }


    @Override
    public void onAfinalFail(int requestId) {
        Log.v("zyl","onAfinalFail requestId :"+requestId);
    }

    @Override
    public void onExecuteSuccess(int requestId, String result, String msg) {

    }

    @Override
    public void onExecuteFail(int requestId, String msg) {

    }
}
到这里可能有人会说我骗你,只写一行代码就能调用接口???

看来我只能放绝招了,修改为一下:

new NetReuest(this).requestCheckVersion(1,true);

哈哈。开玩笑,实际上还是不建议这样写,还是参考上面的写法吧。这样同个页面NetRequest不用重复new

有的同学有点懵逼。底层BaseHttpRequest 写好了,应用层调用代码也写好了,那么中间层NetRequest该怎么写呢?

先看构造:

/**
 * 给Activity调用
 *
 * @param context
 */
public NetRequest(Context context) {
    this.context = context;
    this.listener = (IOnHttpListener) context;
    request = new BaseHttpRequest(context);
    request.setHttpListener(listener);
}

/**
 * 给Fragment调用
 *
 * @param listener
 * @param context
 */
public NetRequest(IOnHttpListener listener, Context context) {
    this.context = context;
    request = new BaseHttpRequest(context);
    request.setHttpListener(listener);
}

能看懂为什么Fragment调用要多传个参数么,因为Activity本身就继承Context,所以直接就是实现我们接口的那个实例 。

这里补充一下BaseHttpRequest的一个方法,方便将示例对象从Activity->NetRequest->BaseHttpRequest

public void setHttpListener(IOnHttpListener httpListener) {
    this.httpListener = httpListener;
}

BaseHttpRequest调用接口之后拿到状态,我们就可以通过这个IOnHttpListener传回去。是不是觉得一切都在套路中。。冥冥之中自有安排。

 * 把服务器原始结果进行处理
 */
private Handler baseHandler = new Handler() {
    public void handleMessage(Message msg) {
        ResultEntity result = (ResultEntity) msg.obj;
        switch (msg.what) {
            case HANDLER_WHAT_SUCESS:
                if (httpListener != null)
                    httpListener.onExecuteSuccess(result.requestId, result.data, result.msg);
                break;
            case HANDLER_WHAT_FAIL:
                if (httpListener != null)
                    httpListener.onExecuteFail(result.requestId, result.msg);
                break;
            case HANDLER_WHAT_NET:
                if (httpListener != null)
                    httpListener.onAfinalFail(result.requestId);
                break;
            case EXIT:

                break;
            default:
                break;
        }
    }
};

最后的最后,我回到中间层补充完最后那段代码,

netRequest.requestCheckVersion(1,true);

1.这个接口很简单,我需要参数就是包名而已

2.requestData 传递serviceAction,requestId,ifShowDialog,params

3.requestData则调用网络基类中的那个request

private BaseHttpRequest request;    //网络请求的基类

/**
 * @param requestId    网络请求id,用于区分同个页面的不同网络请求
 * @param ifShowDialog 是否显示提示框
 */
public void requestData(String serviceAction, int requestId, boolean ifShowDialog, AjaxParams params) {
    request.requestData(serviceAction, requestId, ifShowDialog, params);
}


结束!!!!!!!!!!终于写完了,到了这里,有的同学会说,不是说所有网络框架通吃么,那么怎么换呢?你要做的只是把底层那个BaseHttpRequst的post请求方式改为你那个网络框架的post请求方式,其他全都不用变。。毕竟思想是一样的,大道至简!!






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值