You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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
        }
    }
}

额外优化建议

  1. 避免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方法逻辑
}
  1. 移除不必要的刷新调用:删除@SuppressLint("NotifyDataSetChanged")注解,bind方法内不要调用notifyDataSetChanged(),避免触发全量刷新影响性能
  2. 提前解析数据:可以在Data类初始化时提前解析出结束小时并缓存,避免每次bind时重复调用split方法

内容的提问来源于stack exchange,提问作者Mohsen Mohebi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 13:05:05