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