网络框架的简单封装

一. 前言(简述)
OkHttp是一个高效的HTTP库
Ø 支持 SPDY ,共享同一个Socket来处理同一个服务器所有请求
Ø 如果SPDY不可用,则通过连接池来减少请求延时;
Ø 无缝的支持GZIP来减少数据流量;
Ø 缓存响应数据来减少重复的网络请求。
二简述在项目中使用自己封装的网络框架
1.首先定义一个管理者OkHttpClientManager 这个类采用单例设计模式,直接上代码。

    private static OkHttpClientManager mInstance;
    public OkHttpClient mOkHttpClient;//可以在程序外调用OkHttpClientManager.mOkHttpClient.cancel
    private Handler mDelivery;
    private static final String TAG = "OkHttpClientManager";
    private OkHttpClientManager() {
        mOkHttpClient = new OkHttpClient();
        //OkHttp支持连接,读取和写入超时。
        mOkHttpClient.setConnectTimeout(10, TimeUnit.SECONDS);
        mOkHttpClient.setWriteTimeout(10, TimeUnit.SECONDS);
        mOkHttpClient.setReadTimeout(30, TimeUnit.SECONDS);
        //cookie enabled一种预定义策略,表示只接受来自原始服务器的 cookie。
        mOkHttpClient.setCookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER));
        mDelivery = new Handler(Looper.getMainLooper());
    }

  public static OkHttpClientManager getInstance() {
        if (mInstance == null) {
            synchronized (OkHttpClientManager.class) {
                if (mInstance == null) {
                    mInstance = new OkHttpClientManager();
                }
            }
        }
        return mInstance;
    }

这里给这个client设置了读写超时时间,设置cookie等属性值。
接下来我们就要写常见的Http请求了,当然常见的Http请求用的最多的是get和post啦,下面分别进行封装。

    /**
     * 异步的post请求
     *
     * @param url
     * @param callback
     * @param params
     */
    private void _postAsyn(String url, final INetClientHandler callback, Map<String, String> params) {
        Param[] paramsArr = map2Params(params);
        Request request = buildPostRequest(url, paramsArr);
        deliveryResult(callback, request);
    }

这里我给出了异步的执行post请求,那么这个INetClientHandler 到底是个什么鬼?往下看!

public interface INetClientHandler {
    //状态码为0 表示成功
    public void onSuccess(String response);
    //网络状态异常
    public void onNetFail();
    //状态码不为0  状态失败,toast错误信息
    public void onStateFail(IErrorBody iErrorBody);
    //只要访问网络成功都会执行此方法
    public void onFinish();
    //状态码不为0返回的JSON串
    public void onFailed(String response);

}

打开INetClientHandler 我们可以看出其实这就是个接口,仔细看看接口定义的几个方法,onSuccess,onFinish,onFailed,onStateFailed等接口回调,是不是感觉有种似曾相识的感觉,没错,我们在HttpUtils里面也知道成功和失败的回调,这里我只是把回调的方法写的详细点,(成功,失败,结束,网络状态异常,服务器异常等情况)。

    private Param[] map2Params(Map<String, String> params) {
        if (params == null) return new Param[0];
        int size = params.size();
        Param[] res = new Param[size];
        Set<Map.Entry<String, String>> entries = params.entrySet();
        int i = 0;
        for (Map.Entry<String, String> entry : entries) {
            res[i++] = new Param(entry.getKey(), entry.getValue());
        }
        return res;
    }

这段代码主要封装我们的post提交的map,我们把它封装成一个数组,因为往服务器里面传递的数据我用Map来存储。

    private Request buildPostRequest(String url, Param[] params) {
        if (params == null) {
            params = new Param[0];
        }
        FormEncodingBuilder builder = new FormEncodingBuilder();
        for (Param param : params) {
            if (!CommonUtil.isEmpty(param.value)) {
                builder.add(param.key, param.value);
            }
        }
        RequestBody requestBody = builder.build();
        return new Request.Builder()
                .url(url)
                .tag(TAG)
                .post(requestBody)
                .build();
    }

注:这里的Param封装了键值对

    public static class Param {
        public Param() {
        }
        public   String key;
        public   String value;
        public Param(String key, String value) {
            this.key = key;
            this.value = value;
        }
    }

这一段代码相信大家都能看懂,只是封装了一个请求而已,看到这里,我们怎样传一个请求呢,往下看

 private void deliveryResult(final INetClientHandler callback, Request request) {
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(final Request request, final IOException e) {
                sendFailedStringCallback(request, e, callback);
            }

            @Override
            public void onResponse(final Response response) {
                try {
                    final String string = response.body().string();
                    sendSuccessResultCallback(string, callback);
                } catch (IOException e) {
                    sendFailedStringCallback(response.request(), e, callback);
                }
            }
        });
    }

这部分传递的就是请求结果了,我们把请求后的结果自己去进行操作,来个callback吧!

    private void sendFailedStringCallback(final Request request, final Exception e, final INetClientHandler callback) {
        mDelivery.post(new Runnable() {
            @Override
            public void run() {
                if (callback != null) {
                    callback.onNetFail();//记得这里吗 是我们接口定义的回调啊
                    callback.onFinish();
                }
            }
        });
    }

这里给出了网络状态异常

    private void sendSuccessResultCallback(final Object object, final INetClientHandler callback) {
        mDelivery.post(new Runnable() {
            @Override
            public void run() {
                if (callback != null) {
                    Log.i("test", object.toString());
                    ResponseBody body = ResponseBody.parse(object.toString());
                    if (body.isOK()) {
                        callback.onSuccess(object.toString());
                        callback.onFinish();
                    } else {
                        IErrorBody ieb = IErrorBody.CODEERROR;
                        ieb.setCode(body.getCode());
                        ieb.setMessage(body.getMessage());
                        callback.onFailed(object.toString());
                        callback.onStateFail(ieb);
                        callback.onFinish();
                    }
                }
            }
        });
    }

这里就是我们成功时候的回调啦,client类封装完毕,但我们怎么给出去呢,我们提供了一个方法,调用就可以啦!

    //*************对外公布的方法************

    public static void postAsyn(String url, final    INetClientHandler callback, Map<String, String> params) {
        getInstance()._postAsyn(url, callback, params);
    }

这是封装内部做的事情,那么怎么使用呢?这就让NetManager登场啦!
举个栗子

    /**
     * 注册
     * @param absParams
     * @param handler
     */

    public static void regsiter(AbsHashParams absParams, final INetClientHandler handler){
        Map<String,String> map= ParamsHelper.getParams(absParams);
        OkHttpClientManager.postAsyn(UrlInterface.API_REGISTER, handler, map);
    }

显然这是项目中注册的接口,只需要直接调用就行啦 NetManager.regsiter(),当然我们要传递点参数啦 AbsHashParams 登场,这个类是个抽象类。

public abstract class AbsHashParams extends AbsParams{

    @Override
    public Map<String, String> getMap() {
        Map<String,String> map=new HashMap<>();
        //传递共有的参数,方便以后封板加密或者增加共有参数
        map.put("channel_id", "1");
//        if(CommonParams.getSign()!=null){
//            map.put("sign", CommonParams.getSign());
//
//            CommonUtil.getSign(context,"com.luochen.reader")
//        }

        map.put("sign", CommonUtil.getSign(AppUtils.getAppContext(),"com.luochen.reader"));

        map.put("device_id", CommonParams.getDevice_id());
        map.put("timestamp", System.currentTimeMillis() + "");

        if(StringUtils.isValid(CommonParams.getToken())){
            map.put("uid", CommonParams.getUid());
            map.put("token", CommonParams.getToken());
        }

//        map.put("uid", CommonParams.getUid());
//        map.put("token", CommonParams.getToken());
        getOtherParams(map);
        return map;
    }
    public abstract Map<String, String> getOtherParams(Map<String,String> map);
}

我们把每次需要的参数都放在上面的方法,如果需要其他的就重写getOtherParams()方法,返回个map就行了,上面的参数读者不必深究,无外乎就是token 签名 用户id等基础信息,这些读者可以根据自身项目去重新写。
注意:上面说到INetClientHandler ,当然我们不需要时刻的去重写不需要的接口,这违反了设计模式6大原则的内容,即我们不要依赖我们不需要的接口,即接口隔离原则。所以就得重写啦

public class NetClientHandler implements INetClientHandler {
    private Context context;
    public NetClientHandler(@NonNull Context context) {
        this.context = context;
    }
    @Override
    public void onSuccess(String response) {
        Log.i("test", "response=" + response);
    }
    @Override
    public void onNetFail() {
        if (context != null) {
//            ToasterHelper.show(context, "您的网络异常,请检查网络!!");
            Toast.makeText(context,"您的网络异常,请检查网络!!",Toast.LENGTH_SHORT).show();
        }
//        else if (TUtils.isValid(AppUtils.getAppContext())) {
//            ToasterHelper.show(context, "您的网络异常,请检查网络!!");
//        }
    }

    @Override
    public void onStateFail(IErrorBody iErrorBody) {
        if (!CommonUtil.isEmpty(iErrorBody)) {
            if(iErrorBody.getMessage()!=null){
//                ToasterHelper.show(context.getApplicationContext(), iErrorBody.getMessage().toString());
                Toast.makeText(context,iErrorBody.getMessage().toString(),Toast.LENGTH_SHORT).show();
            }
        }
        if (iErrorBody.getCode() == 1008) {
            return;
        } else {
            if (!CommonUtil.isEmpty(iErrorBody.getMessage()))
//                ToasterHelper.show(context, iErrorBody.getMessage());
            Toast.makeText(context,iErrorBody.getMessage(),Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onFinish() {
    }

    @Override
    public void onFailed(String response) {
    }
}
    //注册
    NetManager.regsiter(new AbsHashParams() {
            @Override
            public Map<String, String> getOtherParams(Map<String, String> map) {
            //所有传递的数据
                map.put("username","yuan");
                map.put("password","123");
                return map;
            }
        }, new INetClientHandler() {
            @Override
            public void onSuccess(String response) {
                //成功时  response返回的json
            }

            @Override
            public void onNetFail() {
//网络失败时  
            }

            @Override
            public void onStateFail(IErrorBody iErrorBody) {
//服务器异常
            }

            @Override
            public void onFinish() {
//结束时  这里可以给出关闭提示框等等
            }

            @Override
            public void onFailed(String response) {
//失败时
            }
        });

这里我们给出了具体处理方法,对服务器错误的处理,对网络错误的处理,如果不用就让父类处理,如果想其他的就重写这个方法。处理特殊的需求。至此,本次的封装OkHttp主要的类就到这里了,难免代码有误,请指正。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值