Android 自定义控件 这样子写Handler正确吗?

发布于 2022-09-11 23:48:13 字数 2723 浏览 15 评论 0

在写自定义控件时,IDE提示这样子写可能会发生泄漏

image.png

提示可能发生泄漏的代码

private class CustomHandler extends Handler {
    @Override
    public void handleMessage(@NonNull Message msg) {
        super.handleMessage(msg);
        if (animCurrentPage < animMaxPage && animCurrentPage >= 0) {
            invalidate();
            if (animState == ANIM_NULL) {
                return;
            }
            if (animState == ANIM_CHECK) {
                animCurrentPage++;
            } else if (animState == ANIM_UNCHECK) {
                animCurrentPage--;
            }
            this.sendEmptyMessageDelayed(0, animDuration / animMaxPage);
            Log.e("CustomHandler", "animCurrentPage:" + animCurrentPage);
        } else {
            if (isCheck) {
                animCurrentPage = animMaxPage - 1;
            } else {
                animCurrentPage = -1;
            }
            invalidate();
            animState = ANIM_NULL;
        }
    }
}

通过搜索引擎搜索到结果后,修改后的代码

private static class CustomHandler extends Handler {
    private final WeakReference<CheckView> mCheckView;

    CustomHandler(CheckView checkView) {
        mCheckView = new WeakReference<>(checkView);
    }

    @Override
    public void handleMessage(@NonNull Message msg) {
        super.handleMessage(msg);
        CheckView checkView = mCheckView.get();
        if (checkView != null) {
            int animCurrentPage = checkView.animCurrentPage;
            int animMaxPage = checkView.animMaxPage;
            int animState = checkView.animState;
            if (animCurrentPage < animMaxPage && animCurrentPage >= 0) {
                checkView.invalidate();
                if (animState == ANIM_NULL) {
                    return;
                }
                if (animState == ANIM_CHECK) {
                    checkView.animCurrentPage++;
                } else if (animState == ANIM_UNCHECK) {
                    checkView.animCurrentPage--;
                }
                this.sendEmptyMessageDelayed(0, checkView.animDuration / animMaxPage);
                Log.e("CustomHandler", "animCurrentPage:" + animCurrentPage);
            } else {
                if (checkView.isCheck) {
                    checkView.animCurrentPage = animMaxPage - 1;
                } else {
                    checkView.animCurrentPage = -1;
                }
                checkView.invalidate();
                checkView.animState = ANIM_NULL;
            }
        }
    }
}

请问一下,这样子修改后,是否就可以解决泄漏的问题呢?我通过LeakCanary检测后并没有发现什么,但是我不知道这样子写是否规范?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不寐倦长更 2022-09-18 23:48:13

可以这样写,但是建议在View被销毁的时候比如onDetachedFromWindow回调方法将发的delay的消息移除掉

你是想要写一个匿名内部类。因为非静态的内部类为在Java编译成字节码后也是一个独立的类,但是为了达到内部类访问外部类中的成员变量和方法的功能,字节码中会持有外部类的一个对象的引用,才可以在两个独立类里面互相访问。如果你发送延迟Message的时候,Message 的成员变量target会持有Handler的引用,而这个匿名内部类Handler的对象又持有View的对象的引用。所以造成了该View对象不能及时被回收掉

如果改成静态的匿名内部类,该类只能访问外部类的静态方法和静态变量,所以不会持有外部类的实例对象。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文