一、Bug背景
在使用RadioGroup和Viewpager时,会互相监听,即Viewpager.addOnPageChangeListener{}和RadioGroup.setOnCheckedChangeListener
在触发viewpager的onPageSelected的时候,根据位置去设置radiogroup里的radiobutton的状态
即navRadioGroup.check(R.id.nav_radio_button_1)
在触发RadioGroup的onCheckedChanged的时候,根据位置去设置viewpager页面,
即Viewpager.currentItem
bug表现:
之前的需求,只做页面和radiogroup的切换,因为功能的表现是正常的。
但是现在因为切换指定页面的时候,需要请求接口来刷新页面,然后今天在自测的时候,发现同一个接口会疯狂请求好几个!!!这样虽然在页面上看不出什么感觉,但是从性能上来说是非常不利的。
二、BUG原因
其实在写这个代码的时候我就想过,再选中某个页面的时候,去设置对应的radiobutton的状态的时候,回调了onCheckedChanged,又在这里面设置viewpager的currentItem,设置了currentItem就会回调onPageSelected,岂不是无限循环。
三、源码分析
错误方法:
最开始想的很简单,既然你要重复调用,那我就设置个变量来进行控制,
override fun onPageSelected(position: Int) {LogUtils.e("init data", "onPageSelected position:$position isPageChange: $isPageChange")if (isPageChange) {isPageChange = falsereturn}isPageChange = true
。。。。。逻辑代码
}
后面发现不行,因为他不知会多调用一次,可能是好几次。
正确方法
后面去看了setCurrentItem和RadioGroup.check的源码,发现
public void check(@IdRes int id) {// don't even botherif (id != -1 && (id == mCheckedId)) {return;}if (mCheckedId != -1) {setCheckedStateForView(mCheckedId, false);}if (id != -1) {setCheckedStateForView(id, true);}setCheckedId(id);}private void setCheckedStateForView(int viewId, boolean checked) {View checkedView = findViewById(viewId);if (checkedView != null && checkedView instanceof RadioButton) {((RadioButton) checkedView).setChecked(checked);}}
看那三个方法里面的代码,在满足条件的情况下,会有不止一次的onCheckedChanged的回调,所有是这儿出了问题。
四、解决代码
使用RadioButton#setChecked 代替 RadioGroup #check
binding.fragmentContainerViewpager.addOnPageChangeListener(object :ViewPager.OnPageChangeListener {override fun onPageScrolled(position: Int,positionOffset: Float,positionOffsetPixels: Int) {}override fun onPageSelected(position: Int) {LogUtils.e("init data", "onPageSelected position:$position isPageChange: $isPageChange")if (position != 0 && !AppConstant.getIsLogin()) {homeFragment.toLogin()binding.navRadioGroup.check(R.id.nav_radio_button_1)binding.fragmentContainerViewpager.currentItem = 0return}when (position) {0 -> {binding.navRadioGroup.findViewById<RadioButton>(R.id.nav_radio_button_1).isChecked=true}1 -> {binding.navRadioGroup.findViewById<RadioButton>(R.id.nav_radio_button_2).isChecked = true}2 -> {binding.navRadioGroup.findViewById<RadioButton>(R.id.nav_radio_button_2).isChecked=true}}}override fun onPageScrollStateChanged(state: Int) {}})
原因:使用public void setChecked(boolean checked)最后只会调用一次onCheckedChanged方法