最近在做聊天室相关内容,也就是类似于常见的聊天功能。其中就难免会显示每条消息的时间,如果类似于微信或者QQ时间显示日期或者具体的时间那还好说,今天的消息显示的是HH:mm,昨天的是“昨天HH:mm”, 更早的是的是"MM月dd日 HH:mm",跟当前时间比较时,显示的时间都是一个,不存在刷新的问题。
但是,我们的显示是这样的:
一小时内:xx分钟前
一天内:xx小时前
昨天::昨天 HH:mm
前天:前天 HH:mm
更早的: MM月dd日 HH:mm
那么问题来了,如果是当天的消息,时间格式化后是跟当前的时间想关联的,如果界面一直不刷新,那么你刚刚发的消息就一直显示"刚刚",一分钟前发的消息一直显示"xx分钟前",完蛋,看来得实时刷新界面?
但是我们都知道RecyclerView刷新会导致我们的节目闪烁一下,那么如果做到不闪烁呢?
可能你会说给每个消息价格定时器或者线程,搞定时刷新,哭晕在厕所...这样既复杂,又容易出bug,也不好维护。
暂时想到的方案:给可见的item定时刷新
1.设置定时器,给每个item定时刷新
2.滚动时不刷新
private var timer: Timer? = timer(daemon = true, initialDelay = 0, period = 10_000) {
updateMessageTime()
}
fun updateMessageTime() {
if (container.recyclerView.scrollState != RecyclerView.SCROLL_STATE_IDLE ||
chatMessageAdapter.data.isEmpty()) {
return
}
val layoutManager = container.recyclerView.layoutManager as? LinearLayoutManager
val firstVisiblePosition = layoutManager?.findFirstVisibleItemPosition() ?: 0
val lastVisiblePosition = layoutManager?.findLastVisibleItemPosition() ?: 0
for (index in firstVisiblePosition..lastVisiblePosition) {
val viewHolder = container.recyclerView.findViewHolderForLayoutPosition(index) as? BaseViewHolder
?: continue
chatMessageAdapter.getItem(index)?.dataBean?.content?.message?.time?.let {
(container.context as? Activity)?.runOnUiThread {
viewHolder.setText(R.id.tv_time, DateTools.formatProfessionalArticlesForSecond(it / 1000))
}
}
}
}
3.滚动停止后手动刷新
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
when (newState) {
RecyclerView.SCROLL_STATE_IDLE -> {
messageUtil.updateMessageTime()
}
}
}
})
4.消息来了刷新
updateMessageTime();
如此,大概就实现了时间的定时刷新,因为更新的是可见item的tv_time的时间,所以界面不会出现闪烁问题。
Then end !
如果大家有好的方案可以告知一下,谢谢。