最近面试时,面试官问了一个列表倒计时效果如何实现,现在记录一下。
运行效果图
实现思路
实现方法主要有两个:
1.为每个开始倒计时的item启动一个定时器,再做更新item处理;
2.只启动一个定时器,然后遍历数据,再做再做更新item处理。
经过思考,包括性能、实现等方面,决定使用第2种方式实现。
实现过程
数据实体
复制代码
1
2
3
4
5
6
7
8
9/** * 总共的倒计时的时间(结束时间-开始时间),单位:毫秒 * 例: 2019-02-23 11:00:30 与 2019-02-23 11:00:00 之间的相差的毫秒数 */ private long totalTime; /** * 倒计时是否在暂停状态 */ private boolean isPause = true;
倒计时
Timer
复制代码
1mTimer.schedule(mTask, 0, 1000);
TimerTask
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25class MyTask extends TimerTask { @Override public void run() { if (mList.isEmpty()) { return; } int size = mList.size(); CountDownTimerBean bean; long totalTime; for (int i = 0; i < size; i++) { bean = mList.get(i); if (!bean.isPause()) {//不处于暂停状态 totalTime = bean.getTotalTime() - 1000; if (totalTime <= 0) { bean.setPause(true); bean.setTotalTime(0); } bean.setTotalTime(totalTime); Message message = mHandler.obtainMessage(1); message.arg1 = i; mHandler.sendMessage(message); } } } }
线程交互更新item
复制代码
1
2
3
4
5
6
7
8
9
10mHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { switch (msg.what) { case 1: notifyItemChanged(msg.arg1, "update-time"); break; } } };
性能优化方面
1.调用notifyItemChanged()方法后,不要更新整个item(比如说item包含图片,不需要变的),所以要重写onBindViewHolder( Holder , int , List )方法:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16@Override public void onBindViewHolder(@NonNull Holder holder, int position, @NonNull List<Object> payloads) { if (payloads.isEmpty()) { onBindViewHolder(holder, position); return; } //更新某个控件,比如说只需要更新时间信息,其他不用动 CountDownTimerBean bean = mList.get(position); long day = bean.getTotalTime() / (1000 * 60 * 60 * 24); long hour = (bean.getTotalTime() / (1000 * 60 * 60) - day * 24); long min = ((bean.getTotalTime() / (60 * 1000)) - day * 24 * 60 - hour * 60); long s = (bean.getTotalTime() / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60); holder.tvTime.setText("剩余时间: " + day + "天" + hour + "小时" + min + "分" + s + "秒"); holder.btnAction.setText(bean.isPause() ? "开始" : "暂停"); holder.btnAction.setEnabled(bean.getTotalTime() != 0); }
2.销毁资源操作:
复制代码
1
2
3
4
5
6
7
8
9
10
11/** * 销毁资源 */ public void destroy() { mHandler.removeMessages(1); if (mTimer != null) { mTimer.cancel(); mTimer.purge(); mTimer = null; } }
RecyclerView.Adapter部分源码
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148public class CountDownTimerAdapter extends RecyclerView.Adapter<CountDownTimerAdapter.Holder> { private static final String TAG = "CountDownTimerAdapter->"; private List<CountDownTimerBean> mList;//数据 private Handler mHandler;//线程调度,用来更新列表 private Timer mTimer; private MyTask mTask; public CountDownTimerAdapter() { mList = new ArrayList<>(); mHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { switch (msg.what) { case 1: notifyItemChanged(msg.arg1, "update-time"); break; } } }; mTask = new MyTask(); } public void bindAdapterToRecyclerView(@NonNull RecyclerView view) { view.setAdapter(this); } /** * 设置新的数据源 * * @param list 数据 */ public void setNewData(@NonNull List<CountDownTimerBean> list) { destroy(); mList.clear(); mList.addAll(list); notifyDataSetChanged(); if (mTimer == null) { mTimer = new Timer(); } mTimer.schedule(mTask, 0, 1000); } /** * 销毁资源 */ public void destroy() { mHandler.removeMessages(1); if (mTimer != null) { mTimer.cancel(); mTimer.purge(); mTimer = null; } } @NonNull @Override public Holder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_count_down_timer, viewGroup, false); return new Holder(view); } @Override public void onBindViewHolder(@NonNull Holder holder, int position, @NonNull List<Object> payloads) { if (payloads.isEmpty()) { onBindViewHolder(holder, position); return; } //更新某个控件,比如说只需要更新时间信息,其他不用动 CountDownTimerBean bean = mList.get(position); long day = bean.getTotalTime() / (1000 * 60 * 60 * 24); long hour = (bean.getTotalTime() / (1000 * 60 * 60) - day * 24); long min = ((bean.getTotalTime() / (60 * 1000)) - day * 24 * 60 - hour * 60); long s = (bean.getTotalTime() / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60); holder.tvTime.setText("剩余时间: " + day + "天" + hour + "小时" + min + "分" + s + "秒"); holder.btnAction.setText(bean.isPause() ? "开始" : "暂停"); holder.btnAction.setEnabled(bean.getTotalTime() != 0); } @Override public void onBindViewHolder(@NonNull final Holder holder, int position) { holder.ivIcon.setImageResource(R.mipmap.ic_launcher_round); final CountDownTimerBean bean = mList.get(position); long day = bean.getTotalTime() / (1000 * 60 * 60 * 24); long hour = (bean.getTotalTime() / (1000 * 60 * 60) - day * 24); long min = ((bean.getTotalTime() / (60 * 1000)) - day * 24 * 60 - hour * 60); long s = (bean.getTotalTime() / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60); holder.tvTime.setText("剩余时间: " + day + "天" + hour + "小时" + min + "分" + s + "秒"); holder.btnAction.setText(bean.isPause() ? "开始" : "暂停"); holder.btnAction.setEnabled(bean.getTotalTime() != 0); holder.btnAction.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (bean.isPause()) { bean.setPause(false); holder.btnAction.setText("暂停"); } else { bean.setPause(true); holder.btnAction.setText("开始"); } } }); } @Override public int getItemCount() { return mList.size(); } class Holder extends RecyclerView.ViewHolder { private ImageView ivIcon; private TextView tvTime; private Button btnAction; Holder(@NonNull View itemView) { super(itemView); ivIcon = itemView.findViewById(R.id.iv_icon); tvTime = itemView.findViewById(R.id.tv_time); btnAction = itemView.findViewById(R.id.btn_action); } } class MyTask extends TimerTask { @Override public void run() { if (mList.isEmpty()) { return; } int size = mList.size(); CountDownTimerBean bean; long totalTime; for (int i = 0; i < size; i++) { bean = mList.get(i); if (!bean.isPause()) {//不处于暂停状态 totalTime = bean.getTotalTime() - 1000; if (totalTime <= 0) { bean.setPause(true); bean.setTotalTime(0); } bean.setTotalTime(totalTime); Message message = mHandler.obtainMessage(1); message.arg1 = i; mHandler.sendMessage(message); } } } } }
项目地址:Android利用RecyclerView实现列表倒计时效果
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持靠谱客。
最后
以上就是殷勤毛豆最近收集整理的关于Android利用RecyclerView实现列表倒计时效果的全部内容,更多相关Android利用RecyclerView实现列表倒计时效果内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复