四行代码解决RadioGroup.clearCheck()方法返回两次onCheckedChanged

四行代码解决RadioGroup.clearCheck()方法返回两次onCheckedChanged

本文原创,转载请注明出处。欢迎关注我的 简书
安利一波我写的开发框架:MyScFrame喜欢的话就给个Star

场景

当我们使用RadioGroup一般都会设置OnCheckedChangeListener,比如下面这种方式

        mScRadioGroup.setOnCheckedChangeListener(new ScRadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(ScRadioGroup group, @IdRes int checkedId) {
                switch (checkedId) {
                    case R.id.radiobtn_1:
                        break;
                    case R.id.radiobtn_2:
                        break;
                    default:
                        break;
                }
            }
        });

然而,在调用RadioGroup.clearCheck()方法的时候,你会发现onCheckedChanged回调了两次,一次是之前设置的RadioButton的id,一次是id=-1。
如果我们把一些逻辑写在onCheckedChanged中,就会比较尴尬,百度搜索了下,通常的做法是直接使用下面这种方式设置按钮是否被点击,废弃掉onCheckedChanged这个回调

((RadioButton) ScRadioGroup.findViewById(R.id.radiobtn_1)).setChecked(true);

今天,我要教大家另外一种方法,四行代码搞定这个问题。
在说方法之前,让我们先来了解下为什么调用clearCheck()方法的时候会触发两次回调?

源码分析

1.RadioButton选中状态变更监听器:

    private void init() {
        mChildOnCheckedChangeListener = new CheckedStateTracker();
        mPassThroughListener = new PassThroughHierarchyChangeListener();
        super.setOnHierarchyChangeListener(mPassThroughListener);
    }

查看RadioGroup源码,在init()方法里面我们可以看到这样一行

        mChildOnCheckedChangeListener = new CheckedStateTracker();

查看CheckedStateTracker()就是RadioButton选中状态变更监听器,我们继续往下看

    private class CheckedStateTracker implements
            CompoundButton.OnCheckedChangeListener {
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            // prevents from infinite recursion
            if (mProtectFromCheckedChange) {
                return;
            }
            mProtectFromCheckedChange = true;
            //mCheckedId 表示之前选中的RadioButton的id
            if (mCheckedId != -1) {
                //该方法就是取消相对应RadioButton的选中状态
                setCheckedStateForView(mCheckedId, false);
            }
            mProtectFromCheckedChange = false;
            int id = buttonView.getId();
            //该方法是设置mCheckedId  = id,并且回调onCheckedChanged()
            setCheckedId(id);
        }
    }

从代码上我们可以知道,CheckedStateTracker()就是监听RadioButton选中状态的变更,那么当我们调用clearCheck()的时候,是不是会触发它呢?打印下log你就知道了!这里我就不贴log了。

2.clearCheck()方法具体都做了什么:

    public void clearCheck() {
        check(-1);
    }

真简单,只做了一件事,就是穿一个id=-1到check()方法里面去,我们接着往下看

    public void check(int id) {
        // don't even bother
        if (id != -1 && (id == mCheckedId)) {
            return;
        }
        //这里会先把所有按钮设置成false
        if (mCheckedId != -1) {
            setCheckedStateForView(mCheckedId, false);
        }
        //然后设置指定id的按钮变成true
        if (id != -1) {
            setCheckedStateForView(id, true);
        }
        //最后通知监听器
        setCheckedId(id);
    }

大家看到了把,这里先是把之前设置的RadioButton变更成未选中状态,然后再将这次设置的RadioButton变更成选中状态,最后通知监听器并设置mCheckedId。
顺便贴下setCheckedId()方法给大家看吧

    private void setCheckedId(int id) {
        mCheckedId = id;
        if (mOnCheckedChangeListener != null) {
            mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
        }
    }

看到了没,就这么简单。

3.分析问题:

好了,源码分析完毕,现在我们来分析下为什么会产生2次回调。
通过之前的源码,我们可以看到,当调用setCheckedStateForView()方法的时候,会触发CheckedStateTracker()。不信?你打印log看看。
当我们调用clearCheck()方法清空选中项的时候,他先会触发一次CheckedStateTracker(),在该方法里面会调用一次setCheckedId(),然后再check()方法最后又会调用一次setCheckedId(),总共两次。问题找到了!!鲜花刷起来,掌声在哪里?666刷起来!!

4.解决问题:

既然已经找到问题所在了,那么现在我来教大家四行代码解决这个问题,不啰嗦了,直接上代码直观点

    private boolean mClearClick = false;//判断是否是来自ClearClick()方法

    private void setCheckedId(int id) {
        mCheckedId = id;
        if (mOnCheckedChangeListener != null) {
            mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
        }
        mClearClick = false;
    }

    public void clearCheck() {
        /**
         * 解决调用RadioGroup的clearCheck()方法,onCheckedChanged方法仍被执行
         * 在clearCheck开启mClearClick
         * 在CheckedStateTracker中判断mClearClick是否为true,是的话不去调用setCheckedId方法
         * 在setCheckedId方法里面关闭mClearClick
         */
        mClearClick = true;
        check(-1);
    }


    private class CheckedStateTracker implements
            CompoundButton.OnCheckedChangeListener {
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            // prevents from infinite recursion
            if (mProtectFromCheckedChange) {
                return;
            }
            mProtectFromCheckedChange = true;
            if (mCheckedId != -1) {
                setCheckedStateForView(mCheckedId, false);
            }
            mProtectFromCheckedChange = false;
            int id = buttonView.getId();
            if (!mClearClick) {
                setCheckedId(id);
            }
        }
    }

解决了,查看下,当调用clearCheck()方法的时候,只会返回一次回调,是id=-1的回调。O啦!

欢迎大家留言指出我的不足。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容