软件编程
位置:首页>> 软件编程>> Android编程>> Android如何利用RecyclerView实现列表倒计时效果实例代码

Android如何利用RecyclerView实现列表倒计时效果实例代码

作者:冬季穿短裤  发布时间:2023-01-24 08:08:53 

标签:android,recyclerview,倒计时

前言

最近面试时,面试官问了一个列表倒计时效果如何实现,然后脑袋突然懵的了O(∩_∩)O,现在记录一下。

运行效果图

Android如何利用RecyclerView实现列表倒计时效果实例代码

实现思路

实现方法主要有两个:

1.为每个开始倒计时的item启动一个定时器,再做更新item处理;

2.只启动一个定时器,然后遍历数据,再做再做更新item处理。

经过思考,包括性能、实现等方面,决定使用第2种方式实现。

实现过程

数据实体


/**
* 总共的倒计时的时间(结束时间-开始时间),单位:毫秒
* 例: 2019-02-23 11:00:30 与 2019-02-23 11:00:00 之间的相差的毫秒数
*/
private long totalTime;
/**
* 倒计时是否在暂停状态
*/
private boolean isPause = true;

倒计时

Timer


mTimer.schedule(mTask, 0, 1000);

TimerTask


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);
   }
  }
 }
}

线程交互更新item


mHandler = 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


@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.销毁资源操作:


/**
 * 销毁资源
 */
public void destroy() {
 mHandler.removeMessages(1);
 if (mTimer != null) {
  mTimer.cancel();
  mTimer.purge();
  mTimer = null;
 }
}

RecyclerView.Adapter部分源码


public 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);
   }
  }
 }
}
}

项目地址

源码

来源:https://www.cnblogs.com/qq714081644/p/6547192.html

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com