RecyclerView 倒计时和正计时方案
本章内容
- 一.方案制定
- 二.设计
- 三.编码
相信不少同学都会在这里栽跟头,在思考这个问题设计了两套方案,而我的项目需求中需要根据业务是否反馈来进行倒计时和正计时的操作。
一.方案制定
1.在Adapter中使用CountDownTimer2.修改数据源更新数据
3.只修改页面展示的Item
第一种方案:如果使用CountDownTimer来进行倒计时的话,会造成计时器时间错乱的问题。计时器会根据你更新UI的次数越走越快。
第二种方案:在数据量不大的情况下,是可以进行使用的。但是会存在资源浪费,这里会将没有显示到页面中的数据也会进行运算操作。
第三种方案:第二种方案比第二种方案设计上会更加节省资源,并且不会伴随第一种方案的及时错乱。
二.设计
-
创建RecyclerView.Adapter
-
需要在ViewHodler里面添加一个计时器组件,使用Handler就足够满足需求。我们需要在进入屏幕时,开启倒计时,在滑出屏幕后,停止计时器来节省CPU资源。
-
需要注意的是:进入屏幕会触发Recycler.Adapter的
onBindViewHolder()
函数,滑出屏幕会触发onViewRecycled()
。有以上准备,我们就可以进入撸码环节了。
三.编码
主要工作都在与RecyclerView.Holder中。
public class ChatItemHolder extends BaseViewHolder {
//用来判断是倒计时还是正计时
public boolean isCountdown;
//这个是我的业务逻辑,触发正反计时就看是否反馈信息
public boolean isFeedback;
//倒计时/正计时时间
public long delay;
//倒计时任务
private Runnable countdownRunnable = new Runnable() {
@Override
public void run() {
delay -= 1000;
if (delay == 0) {
isCountdown = false;
} else {
isCountdown = true;
}
updateTimerState();
}
};
//正计时任务
private Runnable positiveTimeRunnable = new Runnable() {
@Override
public void run() {
delay += 1000;
updateTimerState();
}
};
//启动倒计时
public void startCountdown() {
timerHandler.postDelayed(countdownRunnable, 1000);
}
//结束倒计时
public void endCountDown() {
timerHandler.removeCallbacks(countdownRunnable);
}
//启动正计时
public void startPositiveTime() {
timerHandler.postDelayed(positiveTimeRunnable, 1000);
}
//结束正计时
public void endPositiveTime() {
timerHandler.removeCallbacks(positiveTimeRunnable);
}
//更新UI
public void updateTimerState() {
if (isFeedback) { //如果已反馈关闭计时器
endCountDown();
endPositiveTime();
} else {//进行计时并显示的格式为1天1时1分1秒
long time = delay / 1000; //变成秒
long temp = time % (24 * 3600);
long day = time / (24 * 3600); //天
long hour = temp / 3600; //小时
long minute = temp % 3600 / 60; //分钟
long second = temp % 60; //秒
if (isCountdown) {
if (day == 0) {
setText(R.id.command_feedback_state, "反馈剩余时间:" + hour + "时" + minute + "分" + second + "秒");
} else {
setText(R.id.command_feedback_state, "反馈剩余时间:" + day + "天" + hour + "时" + minute + "分" + second + "秒");
}
setTextColor(R.id.command_feedback_state, Color.parseColor("#1890ff"));
setBackgroundResource(R.id.command_feedback_state,
R.drawable.shape_solid_null_stroke_1890ff_corner);
startCountdown();
} else {
if (day == 0) {
setText(R.id.command_feedback_state, "超时时间:" + hour + "时" + minute + "分" + second + "秒");
} else {
setText(R.id.command_feedback_state, "超时时间:" + day + "天" + hour + "时" + minute + "分" + second + "秒");
}
setTextColor(R.id.command_feedback_state, Color.parseColor("#ff001b"));
setBackgroundResource(R.id.command_feedback_state,
R.drawable.shape_solid_null_stroke_ff001b);
startPositiveTime();
}
}
}
public void display(CommandChatBean.Data.Records record) {
long time = DateUtil.ifsUtcStringToLocalForLong(record.getCzsx());
delay = time - System.currentTimeMillis();
isCountdown = delay > 0;
isFeedback = !TextUtils.isEmpty(record.getCcFksj());
delay = Math.abs(delay);
updateTimerState();
}
public void onRecycled() {
endCountDown();
endPositiveTime();
}
public ChatItemHolder(View view) {
super(view);
}
}
//recyclerView内写入的方法:该方法是为了关闭页面后可以移除所有计时任务
public void recycleTime() {
if (timerHandler != null) {
timerHandler.removeCallbacksAndMessages(null);
timerHandler = null;
}
}
我这里使用的是封装好的AdapterHelper,可以直接集成RecyclerView.ViewHolder进行获取控件在进行更新。替换我下面的代码逻辑:
setText(R.id.command_feedback_state, "超时时间:" + hour + "时" + minute + "分" + second + "秒");
} else {
setText(R.id.command_feedback_state, "超时时间:" + day + "天" + hour + "时" + minute + "分" + second + "秒");
}
setTextColor(R.id.command_feedback_state, Color.parseColor("#ff001b"));
setBackgroundResource(R.id.command_feedback_state,
R.drawable.shape_solid_null_stroke_ff001b);
RecyclerAdapter的onBindViewHolder(ChatItemHolder viewHolder,int position)
中使用方式:
···
if (!TextUtils.isEmpty(records.getCzsx()) && TextUtils.isEmpty(records.getCcFksj())) {
baseViewHolder.setVisible(R.id.command_feedback_state, true);
baseViewHolder.display(records);
}
if (TextUtils.isEmpty(records.getCzsx())) {
baseViewHolder.setVisible(R.id.command_feedback_state, false);
}
if (!TextUtils.isEmpty(records.getCcFksj())) {
baseViewHolder.setVisible(R.id.command_feedback_state, true);
baseViewHolder.setText(R.id.command_feedback_state,
"已反馈:" + DateUtil.ifsUtcStringToLocalForString(records.getCcFksj()));
baseViewHolder.setTextColor(R.id.command_feedback_state, Color.parseColor("#4BBA55"));
baseViewHolder.setBackgroundResource(R.id.command_feedback_state,
R.drawable.shape_solid_null_stroke_4bba55);
}
···
今天就分享到这里了,祝小伙伴新年快乐!