Android RecyclerView Adapter时段透明度设置异常问题排查与修复
问题:RecyclerView中仅部分过期时段Item透明度设置生效的原因及修复
我在Android应用里用RecyclerView展示服务器返回的时段数据,需求是:若服务器返回的时段结束小时早于当前小时,对应Item的透明度设为0.4,否则设为1.0。
编写的Adapter代码如下:
class HoursAdapter constructor(private val items: MutableList<Data>) : RecyclerView.Adapter<HoursAdapter.ViewHolder>() { private lateinit var binding: ItemVisitHoursBinding private lateinit var context: Context private val hoursList = mutableListOf<String>() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { binding = ItemVisitHoursBinding.inflate(LayoutInflater.from(parent.context), parent, false) context = parent.context return ViewHolder() } override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(items[position]) override fun getItemCount() = items.size inner class ViewHolder : RecyclerView.ViewHolder(binding.root) { @SuppressLint("SetTextI18n", "NotifyDataSetChanged") fun bind(item: Data) { binding.apply { // item.hour ==> 格式示例: 7-8 hoursTxt.text = item.hour // 置灰已过期时段 val endHour = item.hour.split("-")[1] Log.e("HoursLog", "End : $endHour --- Now : ${nowJustHour()}") if (endHour < nowJustHour()) { root.alpha = 0.4f } else { root.alpha = 1.0f } } } } }
Logcat输出:
End : 8 --- Now : 11 End : 9 --- Now : 11 End : 10 --- Now : 11 End : 11 --- Now : 11 End : 12 --- Now : 11 End : 13 --- Now : 11 End : 14 --- Now : 11 End : 15 --- Now : 11 End : 16 --- Now : 11 End : 17 --- Now : 11 End : 18 --- Now : 11 End : 19 --- Now : 11 End : 20 --- Now : 11 End : 21 --- Now : 11 End : 22 --- Now : 11 End : 23 --- Now : 11
当前时间为11点,按需求结束小时为8、9、10的Item都应半透明,但实际仅结束小时为10的Item生效。
问题原因
核心问题是用字符串字典序比较代替了数值大小比较:
- 字符串比较是按字符ASCII码逐位对比的,比如"8"和"11"对比时,第一个字符'8'的ASCII码大于'1',所以会判定"8" > "11",不会进入透明度设置分支
- 只有"10"和"11"对比时,第一位字符相同,第二位'0'的ASCII码小于'1',才会判定为真,因此只有该Item生效
修复方案
将endHour和当前小时都转换为整数类型后再做数值比较,修改后的bind方法如下:
@SuppressLint("SetTextI18n") fun bind(item: Data) { binding.apply { hoursTxt.text = item.hour // 将结束小时转为整数 val endHour = item.hour.split("-")[1].toInt() // 确保当前小时为整数(若nowJustHour()返回String,需转为Int) val currentHour = nowJustHour() // 若返回String则改为 nowJustHour().toInt() Log.e("HoursLog", "End : $endHour --- Now : $currentHour") if (endHour < currentHour) { root.alpha = 0.4f } else { root.alpha = 1.0f } } }
额外优化建议
- 避免ViewHolder复用错误:不要将
binding作为Adapter的成员变量,改为在ViewHolder内部持有独立的Binding实例:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val binding = ItemVisitHoursBinding.inflate(LayoutInflater.from(parent.context), parent, false) return ViewHolder(binding) } inner class ViewHolder(private val binding: ItemVisitHoursBinding) : RecyclerView.ViewHolder(binding.root) { // ... bind方法逻辑 }
- 移除不必要的刷新调用:删除
@SuppressLint("NotifyDataSetChanged")注解,bind方法内不要调用notifyDataSetChanged(),避免触发全量刷新影响性能 - 提前解析数据:可以在
Data类初始化时提前解析出结束小时并缓存,避免每次bind时重复调用split方法
内容的提问来源于stack exchange,提问作者Mohsen Mohebi
相关产品推荐
相关产品推荐

