移动测试基础 Bug日志分析实战 Http 框架 RequestListener 空指针异常

Heyniu · 2016年07月15日 · 最后由 Heyniu 回复于 2016年07月24日 · 1972 次阅读

Http 框架 RequestListener 空指针异常

项目 Http 框架基于OkHttp二次封装

影响程度 >> 在弱网情况下异步请求接口时快速关闭页面必现

★★★★

Bug 发现手段 >> Monkey 测试

测试环境

  • Android平台手机一台
  • 网络限速为2G
  • Monkey测试

手工测试为何没发现?

  • Monkey测试有一种尽快跑完种子的机制,容易出现打开一个页面 (Activity) 后马上关闭
  • 手工测试一般不会打开一个页面又马上关闭,故较难发现

报错信息

java.lang.NullPointerException: Attempt to invoke interface method 
'void com.y.http.async.RequestListener.onComplete(java.lang.String, int)' on a null object reference
at com.y.http.async.HttpRequest$1.handleMessage(HttpRequest.java:42)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5438)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:629)

问题排查

  • 同步请求 >> 正常
  • 异步请求 >> 正常
  • 异步请求网络差 >> 正常
  • 异步请求网络差 + Listener销毁 >> 空指针异常

原因解析

在异步请求时Callback等待服务器返回数据,此时Activity被用户关闭,ListenerActivityonDestroy方法被回收,待服务器返回数据时,Callback回调给监听器ListenerListener调用onComplete()方法回调给Activity作数据处理,由于此时Listener为空,所以调用listener.onComplete()方法报错。

@Override
    protected void onDestroy() {
        super.onDestroy();
        if (listener != null) {
            listener = null;
        }
    }
@Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            super.handleMessage(msg);
            switch (msg.what) {
            case HANDLER_SUCCESS:
                int taskId = msg.arg1;
                String result = (String)msg.obj;
                listener.onComplete(result, taskId);
                break;
            case HANDLER_EXCEPTION:
                taskId = msg.arg1;
                BaseException e = (BaseException)msg.obj;
                listener.onException(e, taskId);
                break;
            case HANDLER_CANCEL:
                listener.onCancel();
                break;
            default:
                break;
            }
        }

解决方案

在异步请求Callback回调给ListenerListener调用方法前判空即可(由于此时Activity已经销毁,所以Listener为空,直接return是可行的)。

@Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            super.handleMessage(msg);
            if (listener == null) {
                return;
            }
            switch (msg.what) {
            case HANDLER_SUCCESS:
                int taskId = msg.arg1;
                String result = (String)msg.obj;
                listener.onComplete(result, taskId);
                break;
            case HANDLER_EXCEPTION:
                taskId = msg.arg1;
                BaseException e = (BaseException)msg.obj;
                listener.onException(e, taskId);
                break;
            case HANDLER_CANCEL:
                listener.onCancel();
                break;
            default:
                break;
            }
        }

验证代码

用修改后的Http框架导入项目,实测问题没有再发生。

测试关注点

多留意弱网情况下的测试。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 0 条回复 时间 点赞
Heyniu [该话题已被删除] 中提及了此贴 07月19日 17:02
Heyniu [该话题已被删除] 中提及了此贴 07月24日 14:19
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册