本方案采用RecyclerView的payload机制实现
RecyclerView局部刷新机制——payload
实现点击条目实现某一个条目的倒计时 和 所有条目一起倒计时
下面给出具体代码实现:
//列表中的倒计时刷新测试
class RefreshTimeActivity : BaseActivity() {
private val binding by lazy { ActivityRefreshTimeBinding.inflate(layoutInflater) }
private val viewModel: viewModel by inject()
private lateinit var refreshTimeAdapter: RefreshTimeAdapter
private val mList = mutableListOf<Apis.WanBanner>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
initView()
initObserver()
initData()
}
override fun initView() {
super.initView()
binding.swipeList.setOnRefreshListener {
viewModel.getBanners()
}
refreshTimeAdapter = RefreshTimeAdapter(this, mList)
binding.rvList.layoutManager = LinearLayoutManager(this)
binding.rvList.adapter = refreshTimeAdapter
}
override fun initObserver() {
super.initObserver()
viewModel.getBanners.observe(this, Observer {
if (it.isSucceed()) {
it.data()?.let { list ->
mList.clear()
mList.addAll(list)
addTestTime()
refreshTimeAdapter.notifyDataSetChanged()
binding.swipeList.isRefreshing = false
}
}
})
}
private fun addTestTime(){
for (item in mList.withIndex()){
//3600秒 = 1小时
val time = System.currentTimeMillis()+(item.index+1).times(3600000).toLong()
item.value.startTime = time
}
}
override fun initData() {
super.initData()
viewModel.getBanners()
}
class RefreshTimeAdapter(private val context: Context, private val list: List<Apis.WanBanner>) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val binding = ItemWanBinding.inflate(LayoutInflater.from(parent.context))
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is RefreshTimeAdapter.ViewHolder) {
val item = list[position]
holder.binding.tvTitle.text = item.title
holder.binding.tvStartTime.text = "开售时间:${TimeUtils.getTime(item.startTime)}"
Glide.with(context).load(item.imagePath).apply(
RequestOptions.bitmapTransform(
RoundedCorners(20)
)
)
.into(holder.binding.ivWan)
//1.点击Item倒计时
//holder.binding.tvTime.setOnClickListener {
// notifyItemChanged(holder.layoutPosition, "123");
//}
//2.所有Item直接倒计时
CoroutineScope(Dispatchers.Main).launch{
notifyItemChanged(holder.layoutPosition, "payload");
}
}
}
override fun onBindViewHolder(
holder: RecyclerView.ViewHolder,
position: Int,
payloads: MutableList<Any>
) {
super.onBindViewHolder(holder, position, payloads)
if (payloads.isEmpty()) {
onBindViewHolder(holder, position)
} else {
if (holder is RefreshTimeAdapter.ViewHolder) {
val item = list[position]
CoroutineScope(Dispatchers.Main).launch {
holder.binding.tvTime.text = "开售倒计时:${item.startTime.calculateTime()}"
delay(1000)
notifyItemChanged(holder.layoutPosition, "payload")
}
}
}
}
override fun getItemCount(): Int {
return list.size
}
inner class ViewHolder(val binding: ItemWanBinding) : RecyclerView.ViewHolder(binding.root)
}
}
val twoFormat = DecimalFormat("00")
fun Long.calculateTime(): String {
//val currentTime = SystemClock.elapsedRealtime()
val currentTime = System.currentTimeMillis()
val remains = this - currentTime
if (remains <= 0) {
return ""
}
val day = remains / (24 * 60 * 60 * 1000)
val hour = remains / (60 * 60 * 1000) % 24
val minutes = remains / (60 * 1000) % 60
val second = remains / 1000 % 60
return if (day > 0) {
"${day}天${hour}小时${minutes}分"
} else {
"${twoFormat.format(hour)}:${twoFormat.format(minutes)}:${twoFormat.format(second)}"
}
}
addTestTime方法:每个item的时间间隔1小时,
使用notifyItemChanged 只更新单个条目的单个view,
CoroutineScope 开启协程延迟一秒后再次更新
布局:activity_refresh_time
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipe_list"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</LinearLayout>
至此,简单的列表倒计时就实现了。