利用Timer实现倒计时

  1. @BindView(R.id.send) Button send;//发送验证码
  2. private int time = 60;//倒计时
  3. private Timer timer;
  4. private Handler handler = new Handler() {
  5. public void handleMessage(android.os.Message msg) {
  6. switch (msg.what) {
  7. case 1:
  8. send.setText(time + "S");
  9. break;
  10. case 2:
  11. send.setEnabled(true);
  12. send.setText("重新发送");
  13. break;
  14. }
  15. }
  16. };
  17. @OnClick({R.id.send, R.id.next})
  18. public void onClickIv(View v) {
  19. switch (v.getId()) {
  20. case R.id.send:
  21. send.setEnabled(false);
  22. getVerificationCode();
  23. break;
  24. }
  25. }
  26. //定时器
  27. private void setTimer() {
  28. timer = new Timer();
  29. TimerTask task = new TimerTask() {
  30. @Override
  31. public void run() {
  32. time--;
  33. if (time > 0) handler.sendEmptyMessage(1);
  34. else {
  35. handler.sendEmptyMessage(2);
  36. destoryTimer();
  37. }
  38. }
  39. };
  40. timer.schedule(task, 0, 1000);
  41. }
  42. private void destoryTimer() {
  43. if (timer != null) {
  44. timer.cancel();
  45. timer = null;
  46. }
  47. }
  48. @Override
  49. protected void onDestroy() {
  50. super.onDestroy();
  51. destoryTimer();
  52. }
当然也可以不用Handler而用其他更精简的API,比如:
  1. TimerTask task = new TimerTask() {
  2. @Override
  3. public void run() {
  4. runOnUiThread(new Runnable() {
  5. @Override
  6. public void run() {
  7. time--;
  8. if (time > 0) send.setText(time + "S");
  9. else {
  10. send.setEnabled(true);
  11. send.setText("重新发送");
  12. destoryTimer();
  13. }
  14. }
  15. });
  16. }
  17. };

利用Handler实现倒计时

  1. handler.sendMessageDelayed(handler.obtainMessage(1), 1000);
  2. final Handler handler = new Handler() {
  3. public void handleMessage(Message msg) {
  4. switch (msg.what) {
  5. case 1:
  6. time--;
  7. if (time > 0) {
  8. send.setText(time + "S");
  9. handler.sendMessageDelayed(handler.obtainMessage(1), 1000);
  10. } else {
  11. send.setEnabled(true);
  12. send.setText("重新发送");
  13. }
  14. }
  15. }
  16. };
类似的实现方式
  1. Handler handler = new Handler();
  2. handler.postDelayed(runnable, 1000);
  3. Runnable runnable = new Runnable() {
  4. @Override
  5. public void run() {
  6. time--;
  7. if (time > 0) {
  8. send.setText(time + "S");
  9. handler.postDelayed(this, 1000);
  10. } else {
  11. send.setEnabled(true);
  12. send.setText("重新发送");
  13. }
  14. }
  15. };

利用CountDownTimer实现

  1. CountDownTimer timer = new CountDownTimer(60000, 1000) {
  2. @Override
  3. public void onTick(long millisUntilFinished) {
  4. send.setText(time + "S");
  5. }
  6. @Override
  7. public void onFinish() {
  8. send.setEnabled(true);
  9. send.setText("重新发送");
  10. }
  11. };

GitHub上星星最多的倒计时控件


CountdownView:Android倒计时控件,使用Canvas绘制,支持多种样式
  1. compile 'com.github.iwgang:countdownview:2.1.3'
XML
  1. <cn.iwgang.countdownview.CountdownView
  2. android:layout_width="wrap_content"
  3. android:layout_height="wrap_content" />
基本使用
  1. CountdownView mCountdownView = (CountdownView)findViewById(R.id.countdownView);
  2. mCountdownView.start(995550000); // 毫秒
  3. // 或者自己编写倒计时逻辑,然后调用updateShow来更新UI
  4. for (int time=0; time<1000; time++) {
  5. mCountdownView.updateShow(time);
  6. }
动态显示设置, 支持所有xml中的配置项来使用java代码设置
  1. mCountdownView.dynamicShow(DynamicConfig dynamicConfig)

倒计时结束后回调

  1. mCountdownView.setOnCountdownEndListener(OnCountdownEndListener);

指定间隔时间回调

  1. mCountdownView.setOnCountdownIntervalListener(long, OnCountdownIntervalListener);

RecyclerView中倒计时方案1【最简单】

这种方案在数据量特别小(即List的size()特别小),且刷新item及计算倒计时耗费的时间特别短时适用,否则,将会产生巨大的时间延迟。
1、更改数据源(即重新设置倒计时剩余时间)
  1. //定时器,用于刷新GridView的数据源
  2. private void setQryTimer() {
  3. cancelQryTimer();
  4. qryTimer = new Timer();
  5. qryTimer.schedule(new TimerTask() {
  6. @Override
  7. public void run() {
  8. runOnUiThread(new Runnable() {
  9. public void run() {
  10. if (fixRpList != null && fixRpList.size() > 0) {
  11. for (FixRpBean item : fixRpList) {
  12. if (item.diff_time >= 0) item.diff_time = item.diff_time - 1000L;
  13. }
  14. if (fixRpDialog != null) fixRpDialog.upDate(fixRpList);
  15. }
  16. }
  17. });
  18. }
  19. }, 0, 1000);
  20. }
2、刷新item(建议使用RecyclerView的局部刷新功能)
  1. public void upDate(List<FixRpBean> redPacketList) {
  2. list.clear();
  3. list.addAll(redPacketList);
  4. mRecyclerView.getAdapter().notifyDataSetChanged();//建议使用RecyclerView的局部刷新功能
  5. }

RecyclerView中倒计时方案2【推荐】

核心思想为:利用System.currentTimeMillis()帮我们计算倒计时。
并且:在onViewAttachedToWindow时重新开始倒计时,在onViewDetachedFromWindow时关闭倒计时。
  1. /**
  2. * 复用 本地的计时器 —— System.currentTimeMillis(), 不必自行计时
  3. */
  4. public class RecyclerViewActivity extends Activity {
  5. private List<ItemInfo> mDataList;
  6. @Override
  7. protected void onCreate(Bundle savedInstanceState) {
  8. super.onCreate(savedInstanceState);
  9. setContentView(R.layout.activity_recyclerview);
  10. initData();
  11. RecyclerView recyclerView = (RecyclerView) findViewById(R.id.rv);
  12. recyclerView.setAdapter(new MyAdapter(this, mDataList));
  13. recyclerView.setLayoutManager(new LinearLayoutManager(this));
  14. recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
  15. recyclerView.setItemAnimator(new DefaultItemAnimator());
  16. }
  17. private void initData() {
  18. mDataList = new ArrayList<>();
  19. for (int i = 1; i < 20; i++) {
  20. mDataList.add(new ItemInfo(i * 20 * 1000));
  21. }
  22. // 校对倒计时
  23. long curTime = System.currentTimeMillis();
  24. for (ItemInfo itemInfo : mDataList) {
  25. itemInfo.endTime = curTime + itemInfo.countdown;
  26. }
  27. }
  28. static class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
  29. private Context mContext;
  30. private List<ItemInfo> mDatas;
  31. public MyAdapter(Context context, List<ItemInfo> datas) {
  32. this.mContext = context;
  33. this.mDatas = datas;
  34. }
  35. @Override
  36. public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  37. return new MyViewHolder(LayoutInflater.from(mContext).inflate(R.layout.list_item, parent, false));
  38. }
  39. @Override
  40. public void onBindViewHolder(MyViewHolder holder, int position) {
  41. holder.bindData(mDatas.get(holder.getAdapterPosition()));
  42. }
  43. @Override
  44. public int getItemCount() {
  45. return mDatas.size();
  46. }
  47. //**************************************************关键代码****************************************
  48. @Override
  49. public void onViewAttachedToWindow(MyViewHolder holder) {
  50. super.onViewAttachedToWindow(holder);//父类中为空代码
  51. holder.refreshTime(mDatas.get(holder.getAdapterPosition()).endTime - System.currentTimeMillis());
  52. }
  53. @Override
  54. public void onViewDetachedFromWindow(MyViewHolder holder) {
  55. super.onViewDetachedFromWindow(holder);
  56. holder.countdownView.stop();
  57. }
  58. //**************************************************关键代码****************************************
  59. }
  60. static class MyViewHolder extends RecyclerView.ViewHolder {
  61. public CountdownView countdownView;
  62. public MyViewHolder(View itemView) {
  63. super(itemView);
  64. countdownView = (CountdownView) itemView.findViewById(R.id.countdownView);
  65. }
  66. public void bindData(ItemInfo itemInfo) {
  67. refreshTime(itemInfo.endTime - System.currentTimeMillis());
  68. }
  69. public void refreshTime(long leftTime) {
  70. if (leftTime > 0) {
  71. countdownView.start(leftTime);
  72. } else {
  73. countdownView.stop();//停止计时器,mCustomCountDownTimer.stop();
  74. countdownView.allShowZero();//所有计时清零,即mCountdown.setTimes(0, 0, 0, 0, 0);
  75. }
  76. }
  77. }
  78. static class ItemInfo {
  79. public long countdown;
  80. /*
  81. 根据服务器返回的countdown换算成手机对应的开奖时间 (毫秒)
  82. [正常情况最好由服务器返回countdown字段,然后客户端再校对成该手机对应的时间,不然误差很大]
  83. */
  84. public long endTime;
  85. public ItemInfo(long countdown) {
  86. this.countdown = countdown;
  87. }
  88. }
  89. }

RecyclerView中倒计时方案3【最麻烦】

这种方案为:自己维护倒计时,再调用countdownView.updateShow来刷新显示
并且:在onResume时开启倒计时,在onPause及onDestroy时关闭倒计时。
个人极其不推荐这种方案,既麻烦又低效。
  1. /*
  2. 自己维护倒计时任何,再调用countdownView.updateShow来刷新显示
  3. */
  4. public class RecyclerViewActivity2 extends AppCompatActivity {
  5. private MyAdapter mMyAdapter;
  6. private List<ItemInfo> mDataList;
  7. @Override
  8. protected void onCreate(Bundle savedInstanceState) {
  9. super.onCreate(savedInstanceState);
  10. setContentView(R.layout.activity_recyclerview);
  11. initData();
  12. RecyclerView recyclerView = (RecyclerView) findViewById(R.id.rv);
  13. mMyAdapter = new RecyclerViewActivity2.MyAdapter(this, mDataList);
  14. recyclerView.setAdapter(mMyAdapter);
  15. recyclerView.setLayoutManager(new LinearLayoutManager(this));
  16. recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
  17. recyclerView.setItemAnimator(new DefaultItemAnimator());
  18. }
  19. private void initData() {
  20. mDataList = new ArrayList<>();
  21. for (int i = 1; i < 20; i++) {
  22. mDataList.add(new ItemInfo(1000 + i, "RecyclerView_测试标题_" + i, i * 20 * 1000));
  23. }
  24. // 校对倒计时
  25. long curTime = System.currentTimeMillis();
  26. for (ItemInfo itemInfo : mDataList) {
  27. itemInfo.setEndTime(curTime + itemInfo.getCountdown());
  28. }
  29. }
  30. @Override
  31. protected void onResume() {
  32. super.onResume();
  33. if (null != mMyAdapter) mMyAdapter.startRefreshTime();
  34. }
  35. @Override
  36. protected void onPause() {
  37. super.onPause();
  38. if (null != mMyAdapter) mMyAdapter.cancelRefreshTime();
  39. }
  40. @Override
  41. public void onDestroy() {
  42. super.onDestroy();
  43. if (null != mMyAdapter) mMyAdapter.cancelRefreshTime();
  44. }
  45. static class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
  46. private Context mContext;
  47. private List<ItemInfo> mDatas;
  48. private final SparseArray<MyViewHolder> mCountdownVHList;
  49. private Handler mHandler = new Handler();
  50. private Timer mTimer;
  51. private boolean isCancel = true;
  52. public MyAdapter(Context context, List<ItemInfo> datas) {
  53. this.mContext = context;
  54. this.mDatas = datas;
  55. mCountdownVHList = new SparseArray<>();
  56. startRefreshTime();
  57. }
  58. public void startRefreshTime() {
  59. if (!isCancel) return;
  60. if (null != mTimer) mTimer.cancel();
  61. isCancel = false;
  62. mTimer = new Timer();
  63. mTimer.schedule(new TimerTask() {
  64. @Override
  65. public void run() {
  66. mHandler.post(mRefreshTimeRunnable);
  67. }
  68. }, 0, 10);
  69. }
  70. public void cancelRefreshTime() {
  71. isCancel = true;
  72. if (null != mTimer) {
  73. mTimer.cancel();
  74. }
  75. mHandler.removeCallbacks(mRefreshTimeRunnable);
  76. }
  77. @Override
  78. public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  79. return new MyViewHolder(LayoutInflater.from(mContext).inflate(R.layout.list_item, parent, false));
  80. }
  81. @Override
  82. public void onBindViewHolder(MyViewHolder holder, int position) {
  83. ItemInfo curItemInfo = mDatas.get(position);
  84. holder.bindData(curItemInfo);
  85. // 处理倒计时
  86. if (curItemInfo.getCountdown() > 0) {
  87. synchronized (mCountdownVHList) {
  88. mCountdownVHList.put(curItemInfo.getId(), holder);
  89. }
  90. }
  91. }
  92. @Override
  93. public int getItemCount() {
  94. return mDatas.size();
  95. }
  96. @Override
  97. public void onViewRecycled(MyViewHolder holder) {
  98. super.onViewRecycled(holder);
  99. ItemInfo curAnnounceGoodsInfo = holder.getBean();
  100. if (null != curAnnounceGoodsInfo && curAnnounceGoodsInfo.getCountdown() > 0) {
  101. mCountdownVHList.remove(curAnnounceGoodsInfo.getId());
  102. }
  103. }
  104. private Runnable mRefreshTimeRunnable = new Runnable() {
  105. @Override
  106. public void run() {
  107. if (mCountdownVHList.size() == 0) return;
  108. synchronized (mCountdownVHList) {
  109. long currentTime = System.currentTimeMillis();
  110. int key;
  111. for (int i = 0; i < mCountdownVHList.size(); i++) {
  112. key = mCountdownVHList.keyAt(i);
  113. MyViewHolder curMyViewHolder = mCountdownVHList.get(key);
  114. if (currentTime >= curMyViewHolder.getBean().getEndTime()) {
  115. curMyViewHolder.getBean().setCountdown(0);// 倒计时结束
  116. mCountdownVHList.remove(key);
  117. notifyDataSetChanged();
  118. } else {
  119. curMyViewHolder.refreshTime(currentTime);
  120. }
  121. }
  122. }
  123. }
  124. };
  125. }
  126. static class MyViewHolder extends RecyclerView.ViewHolder {
  127. private TextView mTvTitle;
  128. private CountdownView mCvCountdownView;
  129. private ItemInfo mItemInfo;
  130. public MyViewHolder(View itemView) {
  131. super(itemView);
  132. mTvTitle = (TextView) itemView.findViewById(R.id.tv_title);
  133. mCvCountdownView = (CountdownView) itemView.findViewById(R.id.cv_countdownView);
  134. }
  135. public void bindData(ItemInfo itemInfo) {
  136. mItemInfo = itemInfo;
  137. if (itemInfo.getCountdown() > 0) {
  138. refreshTime(System.currentTimeMillis());
  139. } else {
  140. mCvCountdownView.allShowZero();
  141. }
  142. mTvTitle.setText(itemInfo.getTitle());
  143. }
  144. public void refreshTime(long curTimeMillis) {
  145. if (null == mItemInfo || mItemInfo.getCountdown() <= 0) return;
  146. mCvCountdownView.updateShow(mItemInfo.getEndTime() - curTimeMillis);
  147. }
  148. public ItemInfo getBean() {
  149. return mItemInfo;
  150. }
  151. }
  152. static class ItemInfo {
  153. private int id;
  154. private String title;
  155. private long countdown;
  156. /*
  157. 根据服务器返回的countdown换算成手机对应的开奖时间 (毫秒)
  158. [正常情况最好由服务器返回countdown字段,然后客户端再校对成该手机对应的时间,不然误差很大]
  159. */
  160. private long endTime;
  161. public ItemInfo(int id, String title, long countdown) {
  162. this.id = id;
  163. this.title = title;
  164. this.countdown = countdown;
  165. }
  166. public int getId() {
  167. return id;
  168. }
  169. public void setId(int id) {
  170. this.id = id;
  171. }
  172. public String getTitle() {
  173. return title;
  174. }
  175. public void setTitle(String title) {
  176. this.title = title;
  177. }
  178. public long getCountdown() {
  179. return countdown;
  180. }
  181. public void setCountdown(long countdown) {
  182. this.countdown = countdown;
  183. }
  184. public long getEndTime() {
  185. return endTime;
  186. }
  187. public void setEndTime(long endTime) {
  188. this.endTime = endTime;
  189. }
  190. }
  191. }
2017-6-12

Android 发送验证码 简易代码的更多相关文章

  1. 手机发送验证码—.net代码

    注册过程中,短信发送验证码流程如下: (1).用户提交手机号码,申请湖区验证码 (2).网站按照预制规则生成验证码 (3).网站将用户手机号码和验证码发送到短信平台 (4).将制定内容发送到制定手机号 ...

  2. jQuery手机发送验证码倒计时代码

    <!DOCTYPE> <html> <head> <meta charset="UTF-8"> <script type=&q ...

  3. Android发送验证码的倒计时button

    1 直接上图 2 原理 原理非常easy,就是把对应的倒计时逻辑等封装到一个控件中,并向外部提供接口. 3 代码 import java.util.Timer; import java.util.Ti ...

  4. android发送短信代码(短信内容超长处理)

    一条短信只可容纳70个中文,所以当短信长度超过70个中文字符时程序就要特殊处理了. 有两种方式: 1.通过sendTextMessage()方法依次发送拆分后的短信,该方式有个弊端就是用户会分条收到短 ...

  5. jQuery实现的手机发送验证码倒计时效果代码分享

    这是一款基于jquery实现的手机发送验证码倒计时效果代码,可实现实时显示秒数倒计时的功能,还可实现对手机号码格式验证的功能,是一款常用的网站注册发送手机验证码特效代码. 效果描述:注册一个网站,当需 ...

  6. 网易云信,发送验证码短信C#版代码

    网易云信发送短信代码(C# 版)....需要注意SHA1 String有转换小写!!!! using System; using System.Collections.Generic; using S ...

  7. Android接受验证码自动填入功能(源码+已实现+可用+版本兼容)

    实际应用开发中,会经常用到短信验证的功能,这个时候如果再让用户就查看短信.然后再回到界面进行短信的填写,难免有多少有些不方便,作为开发者.本着用户至上的原则我们也应该来实现验证码的自动填写功能,还有一 ...

  8. js实现发送验证码倒计时按钮

    在写注册页面时,有时候需要发送注册邮件来获取验证码,但是为了防止多次重复发送邮件, 必须让按钮隔一段时间后才能再次使用. 代码如下: <html> <head> <met ...

  9. 前端 js 发送验证码

    1. 代码如下: <html> <head> <meta charset="utf-8"> <title></title> ...

随机推荐

  1. Discuz!源代码阅读笔记之common.inc.php文件【1】

    <?php /* [Discuz!] (C)2001-2007 Comsenz Inc. This is NOT a freeware, use is subject to license te ...

  2. Python 环境

    文章出处:http://www.cnblogs.com/winstic/,请保留此连接 总结一下自己使用python过程中安装三方包的方法 Python 安装 Python的安装非常简单,本人使用的w ...

  3. 无线通信技术协议-6LoWPAN

    6LoWPAN:基于IPv6的低速无线个域网标准,即IPv6 over IEEE 802.15.4. 注:6LoWPAN的协议栈实现在Contiki(完整的一套6LoWPAN协议栈).Zephyr(6 ...

  4. Infinite Scroll–无限分页

    一.前言 现在有很多网站都有这样的交互 1.当你往下浏览页面时,页面会自动去异步加载数据. 无限分页效果 infinite scroll 效果图 –ifxoxo.com 2.在页面下方有一个“点击加载 ...

  5. jquery升级换代

    其实从去年开始1.9以上新版的jquery已不再支持toggle方法和live方法. live用on方法替代. 话说这个方法确实挺方便的,那么怎么交替点击呢,html的checked属性我觉得不是很好 ...

  6. 查看Ubuntu操作系统位数

    查看系统是32位还是64位 #查看long的位数,返回32或64 getconf LONG_BIT

  7. 温习H3C S5500的VLAN配置

    这,才是我想要的... ACCESS还是TRUNK TYPE?

  8. 利用低成本的MCU的UART驱动智能卡

    在银行.身份识别和电信市场中,对安全和增强的功能性不断增长的需要,增加了全球范围智能卡的使用.另一方面,这也使得对安全性较低的磁条卡的使用量下降. 然而,所需的基于智能卡系统中,适当的通信系统的硬件和 ...

  9. c# 基础连接已经关闭: 连接被意外关闭,错误的解决

    原文:c# 基础连接已经关闭: 连接被意外关闭,错误的解决 调试一个使用HttpWebRequest模拟提交表单的程序的时候频繁出现上述错误提示,google了一下发现了几个解决方案.1.在appli ...

  10. MySQL 没有索引 锁全表

    <h3 class="title" style="box-sizing: inherit; margin: 8px 0px 15px; padding: 0px; ...