RadioGroup 的check(id)和他的子控件radiobutton 的setcheck(boolean)的区别

最近项目有需要实现不点击radiobutton来转换radiogroup的选择,之前一直用radiogroup的check方法来确定radiobutton的选择状态,但是今天遇到一个bug,上面的方法只适用于第一次确定radiogroup的选项,第一次后,再用之前的方法就会出现radiogroup的oncheckchanged方法针对上一次选用的radiobutton多调用一次,因为我的项目需要实现点击某个radiobutton时弹窗,结果是点击时正常弹窗,但是当我用radiogroup的check(id)切换checked时这货又给我弹窗一次,很是郁闷,于是进源码深究,终于发现问题:

以下是用radiogroup的check(id)的源码流程:

public void check(@IdRes int id) {
    // don't even bother
    if (id != -1 && (id == mCheckedId)) {
        return;
    }

    if (mCheckedId != -1) {
        setCheckedStateForView(mCheckedId, false);//如果选择的radiobutton和上次不一样,就会走到这条,先把上次选择的radiobutton的check修改为false
    }

    if (id != -1) {
        setCheckedStateForView(id, true);//把本次选择radiobutton的改为true
    }

    setCheckedId(id);
}
下面看 setCheckedStateForView( mCheckedId , false )里面:

private void setCheckedStateForView(int viewId, boolean checked) {
    View checkedView = findViewById(viewId);
    if (checkedView != null && checkedView instanceof RadioButton) {
        ((RadioButton) checkedView).setChecked(checked);//调用上次的radiobutton将其check改为false
    }
}
这个容易理解,再向下看:

public void setChecked(boolean checked) {
    if (mChecked != checked) {
        mChecked = checked;
        refreshDrawableState();
        notifyViewAccessibilityStateChangedIfNeeded(
                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);

        // Avoid infinite recursions if setChecked() is called from a listener
        if (mBroadcasting) {
            return;
        }

        mBroadcasting = true;
        if (mOnCheckedChangeListener != null) {//这个listenter是radiobutton的oncheckedchanged,为null,因为我们是用radiogroup设置oncheckedchanged
            mOnCheckedChangeListener.onCheckedChanged(this, mChecked);
        }
        if (mOnCheckedChangeWidgetListener != null) {//这个就是针对radiobutton的parent控件radiogroup的oncheckedchanged,不为空,进里面方法
            mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked);//这个方法就是调用oncheckedchanged方法
        }

        mBroadcasting = false;            
    }
}
问题就是上面的方法了,这个方法我们通过[(RadioButton) checkedView).setChecked(checked);//调用上次的radiobutton将其check改为false]
方法进来的,传的是false,是要把radiobutton改check为false,结果这货直接走到了radiogroup的oncheckchanged回调,让我们要取消checked的radiobutton又checked了一次,(坑爹啊)再回到最上面的radiogroup的check(id)中的setCheckId方法,把本次选择的radiobutton的id传入radiobutton的oncheckchanged回调。
private void setCheckedId(@IdRes int id) {
    mCheckedId = id;
    if (mOnCheckedChangeListener != null) {
        mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
    }
}
OK,相信你已经看明白了,使用radiogroup的check(id)方法切换radiobutton会使radiogroup的oncheckchanged对上次选择的radiobutton进行多余的一次回调,导致我的项目出现了弹窗问题。
解决方案,直接用radiobutton的setchecked(true)方法,就可以避免上次的radiobutton被回调了。
在此记录心得,避免下次再犯。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值