Http 框架 RequestListener 空指针异常

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

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

★★★★

Bug 发现手段 >> Monkey 测试

测试环境

手工测试为何没发现?

报错信息

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)

问题排查

原因解析

在异步请求时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框架导入项目,实测问题没有再发生。

测试关注点

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


↙↙↙阅读原文可查看相关链接,并与作者交流