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

来源:互联网 发布:tensorflow gpu 测试 编辑:程序博客网 时间:2024/05/23 18:23

最近项目有需要实现不点击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被回调了。
在此记录心得,避免下次再犯。