Android SMS应用如何在API请求返回后更新会话列表条目添加红点标识
实现方案
1. 调整单条目布局(无需新建布局模板)
直接在原有single_sms_small_layout.xml布局中增加默认隐藏的红点控件,比动态替换布局成本更低:
- 首先在drawable目录新建圆形红色背景
shape_red_circle.xml:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid android:color="#FF0000" /> </shape>
- 在
single_sms_small_layout.xml的根ConstraintLayout中添加红点控件,默认隐藏:
<View android:id="@+id/redDot" android:layout_width="8dp" android:layout_height="8dp" android:background="@drawable/shape_red_circle" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent" android:layout_marginTop="4dp" android:layout_marginEnd="4dp" android:visibility="gone"/>
- 同时在
MyHolder类中新增红点控件的绑定引用。
2. 扩展数据模型增加标记字段
给会话列表使用的数据实体类新增标记字段,用来存储接口返回的分类结果:
// 示例为Conversation数据类,替换为你实际使用的实体类名 data class Conversation( // 原有字段保持不变 val id: Long, // 必须保留短信的唯一标识,用来后续定位条目 var isNeedMark: Boolean? = null // 新增字段:null=未请求,false=不需要标记,true=需要显示红点 )
3. 改造Adapter逻辑实现局部更新
核心逻辑是接口回调后只更新对应位置的条目,避免全量刷新列表:
override fun onBindViewHolder(holder: MyHolder, position: Int) { val currentSms = dataList[position] // 先根据已有标记字段控制红点显隐 holder.redDot.visibility = if (currentSms.isNeedMark == true) View.VISIBLE else View.GONE // 原有其他绑定逻辑保持不变 // 发起异步接口请求,注意不要直接用当前position做后续定位,列表滑动时ViewHolder会复用,position会变化 val targetSmsId = currentSms.id // 你的异步HTTP请求逻辑,替换为实际请求代码 requestSmsType(currentSms) { result -> // result为接口返回的0/1 // 先通过唯一ID找到当前短信在列表中的实际位置 val actualPosition = dataList.indexOfFirst { it.id == targetSmsId } if (actualPosition < 0) return@requestSmsType // 该条目已被移除,无需处理 // 更新数据类的标记字段 dataList[actualPosition].isNeedMark = result == 1 // 仅刷新单条条目,不会触发全列表重绘 notifyItemChanged(actualPosition) } }
4. 可选优化(避免请求错乱和内存泄漏)
如果列表滑动频繁,可给ViewHolder绑定请求任务标记,每次复用时取消上一个未完成的请求,避免旧请求返回后更新错误条目:
- 在
MyHolder中新增变量存储请求任务:var currentRequestJob: Job? = null - 每次
onBindViewHolder执行时先取消上一个任务:holder.currentRequestJob?.cancel() - 新发起的请求赋值给
holder.currentRequestJob,页面销毁时遍历取消所有未完成的请求即可。
内容的提问来源于stack exchange,提问作者Juan
相关产品推荐
相关产品推荐

