平方X

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 4664|回复: 0

[Android] RadioGroup调用check(id)方法时,onCheckedChanged被执行多次

[复制链接]

414

主题

709

帖子

3602

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3602
QQ
发表于 2016-7-17 09:37:28 | 显示全部楼层 |阅读模式
参考:
RadioGroup调用check(id)方法时,onCheckedChanged方法被执行多次解决办法
RadioGroup calls onCheckChanged() three times
遇到这个问题的时候,我是看了源码的,但是没认真看,以为出问题了。
参考了上面两篇之后,确定是源码的原因,于是又认真看了源码
解决方案是直接调用RadioButton.setChecked(),可以findViewById或者getChildAt
原因是
1.首先看RadioGroup.check(id)
  1. public void check(@IdRes int id) {
  2.         // don't even bother
  3.         if (id != -1 && (id == mCheckedId)) {
  4.             return;
  5.         }

  6.         if (mCheckedId != -1) {
  7.             //1.1
  8.             setCheckedStateForView(mCheckedId, false);
  9.         }

  10.         if (id != -1) {
  11.             //1.2
  12.             setCheckedStateForView(id, true);
  13.         }
  14.         //1.3
  15.         setCheckedId(id);
  16.     }
复制代码

2.注意上面的setCheckedId(id)方法,在这个方法中调用的onCheckedChanged
  1. private void setCheckedId(@IdRes int id) {
  2.         mCheckedId = id;
  3.         if (mOnCheckedChangeListener != null) {
  4.             mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
  5.         }
  6.     }
复制代码

3.也就是说被执行2次(如果还没有选中项)或3次(已经有选中项了),都是在setCheckedId(id)中执行的。
在check(id)中调用setCheckedStateForView()执行了1或2次,最后直接执行了1次。
接下来看setCheckedStateForView()中是怎么调用的:
  1. private void setCheckedStateForView(int viewId, boolean checked) {
  2.         View checkedView = findViewById(viewId);
  3.         if (checkedView != null && checkedView instanceof RadioButton) {
  4.             ((RadioButton) checkedView).setChecked(checked);
  5.         }
  6.     }
复制代码

4.跳转到了RadioButton的setChecked()方法
  1. public void setChecked(boolean checked) {
  2.         if (mChecked != checked) {
  3.             mChecked = checked;
  4.             ...
  5.             if (mOnCheckedChangeListener != null) {
  6.                 mOnCheckedChangeListener.onCheckedChanged(this, mChecked);
  7.             }
  8.             ...
  9.         }
  10.     }
复制代码

5.在RadioGroup中的申明
  1.     private CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener;
复制代码

6.在RadioGroup中的初始化
  1.     mChildOnCheckedChangeListener = new CheckedStateTracker();
复制代码

7.CheckedStateTracker
  1.     private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener {
  2.         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
  3.             // prevents from infinite recursion
  4.             if (mProtectFromCheckedChange) {
  5.                 return;
  6.             }

  7.             mProtectFromCheckedChange = true;
  8.             if (mCheckedId != -1) {
  9.                 setCheckedStateForView(mCheckedId, false);
  10.             }
  11.             mProtectFromCheckedChange = false;

  12.             int id = buttonView.getId();
  13.             setCheckedId(id);
  14.         }
  15.     }
复制代码

整理一下。
1 RadioGroup.check(id)
    1.1 RadioGroup.setCheckedStateForView(mCheckedId, false);
    1.2 RadioGroup.setCheckedStateForView(id, true);
    1.3 RadioGroup.setCheckedId(id);
2 RadioGroup在setCheckedId中调用RadioGrouponCheckedChanged
3 RadioGroup.setCheckedStateForView调用RadioButton.setChecked(boolean checked)
4 RadioButton.setChecked调用RadioButton.mOnCheckedChangeListener
5 RadioButton.mOnCheckedChangeListener是RadioGroup.mChildOnCheckedChangeListener
6 RadioGroup.mChildOnCheckedChangeListener是new RadioGroup.CheckedStateTracker();
7 RadioGroup.CheckedStateTracker 调用RadioGroup.setCheckedId
我是平方X~
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|手机版|Archiver|平方X ( 冀ICP备14018164号 )

GMT+8, 2024-4-20 15:53 , Processed in 0.127384 second(s), 21 queries .

技术支持:Powered by Discuz!X3.4  © 2001-2013 Comsenz Inc.

版权所有:Copyright © 2014-2018 平方X www.pingfangx.com All rights reserved.

快速回复 返回顶部 返回列表