当利用RadioGroup中的onCheckedChanged 会发现被调用多次,为什么呢?
接下来让我们来看看Android 中的源码。
从RadioGroup的check方法切入
public void check(@IdRes int id) {
// don't even bother
if (id != -1 && (id == mCheckedId)) {
return;
}
//如果上一个有选中的,先把上一个选中的给取消选中
if (mCheckedId != -1) {
setCheckedStateForView(mCheckedId, false);
}
//再将现在当前点击给选中
if (id != -1) {
setCheckedStateForView(id, true);
}
//调用自己的监听方法
setCheckedId(id);
}
从上面的源码中 我们可以看到两个方法 setCheckedStateForView 和 setCheckedId
接下来我们来看下这两个方法的实现
setCheckedId
private void setCheckedId(@IdRes int id) {
mCheckedId = id;
if (mOnCheckedChangeListener != null) {
mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
}
final AutofillManager afm = mContext.getSystemService(AutofillManager.class);
if (afm != null) {
afm.notifyValueChanged(this);
}
}
从源码中可以看到,只要调用了setCheckedId方法就会调用一次onCheckedChanged方法
setCheckedStateForView
setCheckedStateForView() 方法是用来切换 RadioButton 的选中状态的,里面没有看到直接的监听方法的调用,但有调用 radioButton 的 setChecked ()方法
private void setCheckedStateForView(int viewId, boolean checked) {
View checkedView = findViewById(viewId);
if (checkedView != null && checkedView instanceof RadioButton) {
((RadioButton) checkedView).setChecked(checked);
}
}
继续跳,跳到最后会发现 setCheckedStateForView 调用了 setCheckedId方法
这么一看!
真相大白
因为RadioGroup中的check() 方法中调用了两个方法 setCheckedStateForView 和setCheckedId, 其中setCheckedId 会直接触发 onCheckedChanged()方法,而setCheckedStateForView 中的逻辑会最终调用 setCheckedId,所以 onCheckedChanged() 会被调用多次。
因此 解决RadioGroup #check 多次调用onCheckedChanged 的方法就是:
RadioButton#setChecked 代替 RadioGroup #check
For example :
((RadioButton) mResultTabGroup.findViewById(R.id.audio_book_search_announcer_tab_btn)).setChecked(true)