Android 开发之Okhttp网络请求日志打印

Android 开发之Okhttp 网络请求日志打印

网络请求是开发的日常工作内容之一,网络日志打印也有很多要注意及优化的部分,本文分享我在开发过程中编写的OkHttp网络请求日志打印方法实现

OkHTTP网络日志打印

直接用OKHTTP请求接口的方式

  1. 要在接口请求的回调方法内进行信息获取和打印 ,即在自定义的Callback实现类或实现对象中
public abstract class MyStringCallBack<T> implements CallBack{
	 	@Override
	   	 public void onFailure(Call call, final IOException e) {}
	    @Override
	    public void onResponse(Call call, final Response response) throws IOException {}
	}
  1. 当请求流程顺利进行完之后 再onResponse中进行获取网络请求信息和返回的信息打印集合;
    因为onResponse和onFailure都有Call对象,并且call能获取到请求信息,所以创建一个方法,用来获取网络请求信息

  2. private ArrayList<String> getLogRequstList(Call call) throws IOException {
        Request request = call.request();
        ArrayList<String> logArrays = new ArrayList<>();//声明集合用来保存要打印的log信息
        RequestBody requestBody = request.body();
        boolean hasRequestBody = requestBody != null;//获取请求的方法,地址
        String requestStartMessage = "--> " + request.method() + ' ' + URLDecoder.decode(request.url().toString() ,"UTF-8")+ ' ' ;
        if ( hasRequestBody) {
            requestStartMessage += " (" + requestBody.contentLength() + "-byte body)";
        }
        logArrays.add(requestStartMessage);//添加到集合中
        Headers headers = request.headers();
        logArrays.add("---------->REQUEST HEADER<----------");
        for (int i = 0, count = headers.size(); i < count; i++) {//header信息
            logArrays.add(headers.name(i) + ": " + headers.value(i));
        }
        if (!hasRequestBody) {//是否有body请求参数
            logArrays.add("--> END " + request.method());
        } else if (bodyEncoded(request.headers())) {
            logArrays.add("--> END " + request.method() + " (encoded body omitted)");
        } else {
            Buffer buffer = new Buffer();
            requestBody.writeTo(buffer);
    
            Charset charset = UTF8;
            MediaType contentType = requestBody.contentType();
            if (contentType != null) {
                charset = contentType.charset(UTF8);
            }
            if (isPlaintext(buffer)) {
                logArrays.add("---------->REQUEST BODY<----------");
    			//添加请求的body打印信息
                logArrays.add(URLDecoder.decode(buffer.readString(charset), "UTF-8"));
                logArrays.add("--> END " + request.method()
                        + " (" + requestBody.contentLength() + "-byte body)");
            } else {
                logArrays.add("--> END " + request.method() + " (binary "
                        + requestBody.contentLength() + "-byte body omitted)");
            }
        }
        return logArrays;    
    }
    
  3. 再创建一个返回信息打印信息方法

  4.  /**     *     * 获取返回的log信息     * @param response     * @return     * @throws IOException     */
    private ArrayList<String> getLogResponseList( Response response) throws IOException {     
       		String requestTime = response.request().header("requestTime");//为了计算耗时,在请求头中添加了请求时间
       		long tookMs =System.currentTimeMillis() - (requestTime == null ? 0 : Long.parseLong(requestTime));
            ArrayList<String> logArrays = new ArrayList<>();//打印信息集合
            ResponseBody responseBody = response.body();
            long contentLength = responseBody.contentLength();//此处不用betys()以免response关闭报错
            String bodySize = contentLength != -1 ? contentLength + "-byte" : "unknown-length";
            logArrays.add("<-- response code:" + response.code() + " message:" + response.message()+" contentlength:"+bodySize  );
            logArrays.add("<-- response url:"+URLDecoder.decode(response.request().url().toString(),"UTF-8")  );
            logArrays.add("<-- costtimes :  (" + tookMs + "ms"  + ')');
    
    
            if ( !HttpHeaders.hasBody(response)) {
                logArrays.add("<-- END HTTP");
            } else if (bodyEncoded(response.headers())) {
                logArrays.add("<-- END HTTP (encoded body omitted)");
            } else {
                BufferedSource source = responseBody.source();
                source.request(Long.MAX_VALUE); // Buffer the entire body.
                Buffer buffer = source.buffer();
    
                Charset charset = UTF8;
                MediaType contentType = responseBody.contentType();
                if (contentType != null) {
                    charset = contentType.charset(UTF8);
                }
                if (!isPlaintext(buffer)) {
                    logArrays.add("");
                    logArrays.add("<-- END HTTP (binary " + buffer.size() + "-byte body omitted)");
                    return logArrays;
                }
    
                logArrays.add("---------->RESPONSE BODY<----------");
                if (contentLength != 0) {//返回的参数
                    logArrays.add(GsonUtils.retractJson(buffer.clone().readString(charset)));
                }
    
                logArrays.add("<-- END HTTP (" + buffer.size() + "-byte body)");        }        
                return logArrays;
        }
    
  5. 最后创建打印方法,由于网络请求不在同一个线程,为了避免打印的信息错乱,多个请求返回信息输出不对应,我们要用到synchronized关键字来保证线程安全,也就是依次执行。为了保证可读性,还添加了视图框

  6. `

      `/**
     * 打印log
     * @param list
     */
    private synchronized void printLog(ArrayList<String> list,boolean info){
      int length = 0 ;//计算每行最长的长度
        StringBuilder sb = new StringBuilder();
        for(String str : list){
            if(str.indexOf("\n")>-1){//有换行的拆分处理
                String[] split = str.split("\n");
                for(String s : split){
                    s = s.replace("\t","    ");//缩进替换空格
                    if(length<s.length()){
                        length = s.length();
                    }
                }
            }else{
                if(length<str.length()){
                    length = str.length();
                }
            }
        }
        length+=14;//左右间距
        String head = "HTTP  REQUEST START";
        sb.append(" \n\n\n"+"\n");
        //打印头部
        String logHead = "┏"+getEmptyStr((length-head.length())/2,"━")+head+getEmptyStr((length-head.length())/2,"━")+"┓";
        sb.append(logHead+"\n");
        //打印内容
        for(String str : list){
            String logStr = "";
            if(str.indexOf("\n")>-1){//内部换行替换
                splitStr(str,logHead.length(),sb);
            }else{
                if(str.length()> logHead.length()){
                    outOflength(str,logHead.length(),sb);
                }else {
                    logStr = "┃      " + str + getEmptyStr((length - 14 - str.length()), " ");
                    //处理中文间距,保证打印无偏差
                    sb.append(logStr + getEmptyStr((logHead.length() - logStr.length() - 1 - hasCNchar(logStr)), " ") + "┃ \n");
                }
            }
        }
        String end = "HTTP  REQUEST END";
        //打印结尾
        sb.append("┗"+getEmptyStr((length-end.length())/2,"━")+end+getEmptyStr((length-end.length())/2,"━")+"┛\n");
        sb.append(" \n\n\n");
        //Logger.DEFAULT.log(sb.toString());//打印log,避免多个log语句,导致log输出时其他线程的log输出切入此输出阵列内
        String[] split = sb.toString().split("\n");
        for(String str : split){
            if(info) {
                MyLog.i(TAG, str);
            }else{
                MyLog.e(TAG, str);
            }
        }
    }`
    
  7. 接下来看一下打印效果
    在这里插入图片描述

  8. 到此 功能就写完了,我把源码放在一个Android开发分享的项目里,项目会陆续上传我自己写的多种工具类及框架,本文相关的 源码地址 http://www.hefan.space:1001/blob/share%2Fandroid.git/master/app%2Fsrc%2Fmain%2Fjava%2Fcom%2Frunt%2Fsharedcode%2Futils%2FPrintLogUtils.java;

  9. 也可以加QQ群交流技术

最后推荐一个我自己写的MVVM开源项目《Open MVVM》
(加群请进入文章结尾查看群号)

有问题请私信,留言,或者发送邮件到我扣扣邮箱 qingingrunt2010

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值