记录

今天做了一个功能,设置一个心跳操作,根据接口返回时间再次请求接口,没响应或者弱网等异常情况,自动再次请求

由于要做一个SDK,不需要引用第三方包,所以用了CountDownTimer 倒计时和 AsyncTask网络请求
出现一个问题,接口正常返回时,可以进行倒计时操作,网络异常时,倒计时不执行
代码如下

网络请求方法:

private void requestHealth() {
            mOpenAppUrl = Constant.mReleaseOpenAppUrl;         
            new LophealthAsyncTask(context, mOpenAppUrl, lopHealthCallBack).execute();       
    }

请求回调:

private LopCallBack lopHealthCallBack = new LopCallBack() {
        @Override
        public void lopSuccess(String strSuccess) {
            try {
                JSONObject jsonObject = new JSONObject(strSuccess);
                
                    if (jsonObject.has("code") && 200 == jsonObject.getInt("code") && jsonObject.has("data") && 0 != jsonObject.getInt("data")) {
                        int timeData  = jsonObject.getInt("data");
                        countDownHealth(timeData);
                    }else {
                        countDownHealth(defautRequestTimes);
                    }             
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void lopError() {         
                countDownHealth(defautRequestTimes);       
        }
    };

倒计时:

private void countDownHealth(int time) {
LogUtils.e(“lopSuccess”, "time : " + time);
CountDownTimer timer = new CountDownTimer(time, 1000) {
@Override
public void onTick(long millisUntilFinished) {
}

    @Override
    public void onFinish() {
        requestHealth();
        cancel();
    }
}.start();

}

异步请求:

public class LophealthAsyncTask extends AsyncTask<String, Integer, String> {


    @SuppressLint("StaticFieldLeak")
    private Context mContext;
    private LopCallBack lopCallBack;
    private String mUrl = "";


    /**
     * @param mContext
     * @param url
     * @param productIds
     * @param channelCode
     * @param gaid
     */

    public LophealthAsyncTask(Context mContext, String url, LopCallBack lopCallBack) {
        this.mContext = mContext;    
        this.mUrl = url;      
        this.lopCallBack = lopCallBack;
    }

    /**
     * @param params
     * @return str
     */
    @Override
    protected String doInBackground(String... params) {
        String str = "";
        InputStream inputStream = null;

        try {
            URL url = new URL(mUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestProperty("Accept-Encoding", "identity");
            conn.setConnectTimeout(000);
            conn.setReadTimeout(000);
            setConnHeader(conn);
            conn.setDoInput(true);

            if (HttpURLConnection.HTTP_OK == conn.getResponseCode()) {
                LogUtils.e("success", " - -  - - - " + conn.getResponseCode());
                inputStream = conn.getInputStream();
                str = streamToString(inputStream);
                LogUtils.e("success----", " - -  - - - " + conn.getResponseCode());
            } else {
                LogUtils.e("error", conn.getResponseMessage() + " - -  - - - " + conn.getResponseCode());
                lopCallBack.lopError();
            }
            conn.disconnect();
        } catch (Exception e) {
            LogUtils.e("error----", e.getMessage());
            lopCallBack.lopError();
        }
        return str;
    }

    /**
     * set header parameter
     *
     * @param conn
     */
    private void setConnHeader(HttpURLConnection conn) {
        try {
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.setRequestProperty("Charset", "UTF-8");
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setRequestProperty("Accept-Encoding", "identity");
        } catch (Exception e) {
            LogUtils.e("header", e.getMessage());
        }
    }

    @Override
    protected void onPostExecute(String result) {

        if (!TextUtils.isEmpty(result)) {
            LogUtils.e("success", result);
            lopCallBack.lopSuccess(result);
        }
    }


    /**
     * @param is
     * @return Convert input stream information to strings
     */
    private String streamToString(InputStream is) {
        StringBuilder builder = new StringBuilder();
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        String con;
        try {
            while ((con = reader.readLine()) != null) {
                builder.append(con);
            }
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return builder.toString();
    }

    private String reverseString(String str) {
        char[] ch = str.toCharArray();
        StringBuffer sb = new StringBuffer();
        for (int i = ch.length - 1; i >= 0; i--) {
            sb.append(ch[i]);
        }
        return sb.toString();
    }

}

回调:

public interface LopCallBack {
    void lopSuccess(String strSuccess);

    void lopError();
}

一开始写的时候貌似没什么问题,信心满满的就上线了

上线后才发现很多问题,最明显的几个
,CountDownTimer,每执行一次就new 一个新线程,这得出现多少个?,而且cancel();位置也不对。
2,频繁请求未做处理
3,AsyncTask异常处理存在严重逻辑错误

而目前存在的测试错误是,当响应失败时,不会自动请求,直接停止了!
首先考虑以上问题,一点一点分析

问题1: 加全局控制

CountDownTimer timer;

    private void countDownHealth(int time) {
        if (timer != null) {
            timer.cancel();
            timer = null;
        }      
         timer = new CountDownTimer(time, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {
            }

            @Override
            public void onFinish() {
                requestHealth();
            }
        }.start();
    }

问题2:加一个简单的时间判断

private long defautRequestInterval = 60 * 1000;
 
 private void requestHealth() {
        LogUtils.e("requestHealth", "requestHealth");
        long currentTime = System.currentTimeMillis();
        if (currentTime - formerTime > defautRequestInterval) {
            formerTime = System.currentTimeMillis();
            mOpenAppUrl = Constant.mReleaseOpenAppUrl;
            LogUtils.e("request", "health");
            new LophealthAsyncTask(context, mOpenAppUrl,lopHealthCallBack).execute();
        }
    }

问题3: 首先考虑doInBackground、onPostExecute 在请求中的作用
doInBackground设置内容,onPostExecute是请求的回调
那lopCallBack.lopError() 放在 doInBackground就是错误的
应该在onPostExecute中执行
所以需要修改的是:

@Override
    protected void onPostExecute(String result) {
        if (!TextUtils.isEmpty(result)) {
            LogUtils.e("success", result);
            if (lopCallBack != null) {
                lopCallBack.lopSuccess(result);
            }
        } else {
            if (lopCallBack != null) {
                lopCallBack.lopError();
            }
        }
    }

调试总结:
**1,**写log,最好是每一行都加log,下一行的log打印了,上面的内容基本就执行了
**2,**写代码之前,一定要弄懂自己写的东西的原理,
最近发现很多写过的东西,都是反复修改,原因就是不懂原理,就知道复制粘贴,
用了之后不懂如何修改优化,出问题时,因为不懂原理找不到问题所在,容易考虑错误的方向。
出问题时千万不能,一直以为是别人的错误,认为以前是好好的,为什么会出错,然后就返回验证,去看,不去尝试。
如何尝试,首先要加log,定位问题的大致位置,查看添加的代码原理,先懂这个再去改。总是不相信代码有错,肯定浪费时间。
这也是提高效率的方式,先定位,然后懂原理,动手尝试,才能找准错误的位置。

**3,**今天又从同事那里学到一个技术点:
还是上面这个问题,我在加log测异常时,一直都只能执行到这句

LogUtils.e("lopSuccess", "time : timer" );

然后同事看到后,先在new CountDownTimer 后面加一个 log,证明这个会执行
然后看前后调用的逻辑,当看到执行的这个lopHealthCallBack时,打开了AsyncTask ,立马考虑到异步操作的逻辑问题,
然后就考虑异步会不会对我加的这个CountDownTimer 受到影响,知晓在doInBackground内执行的操作都是在线程内部的异步操作
然后就让我在把CountDownTimer的逻辑直接 放在了doInBackground中,发现,确实不执行,
这时,我正好想起 onPostExecute 里有callback 就成功了,
现在就很明显了,问题出在这里,应该在onPostExecute里才能调用CountDownTimer 成功
仔细一想AsyncTask的原理,onPostExecute就是对请求的响应,失败了也必须走这里

那这个问题就迎刃而解了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值