广告
返回顶部
首页 > 资讯 > 移动开发 >Handler实现倒计时功能
  • 782
分享到

Handler实现倒计时功能

2024-04-02 19:04:59 782人浏览 八月长安
摘要

本文实例为大家分享了Handler实现倒计时功能的具体代码,供大家参考,具体内容如下 1、需求 1.1 实现目标 当后台传递一个时间戳时,与当前系统时间做时间差,并转换为时分秒,作为

本文实例为大家分享了Handler实现倒计时功能的具体代码,供大家参考,具体内容如下

1、需求

1.1 实现目标

当后台传递一个时间戳时,与当前系统时间做时间差,并转换为时分秒,作为商品活动的倒计时;

如下图所示:

1.2 实现步骤

自定义View

1、实现倒计时功能,封装成方法;
2、初始化倒计时功能,及布局文件;
3、通过Handler中的post()或sendMessage()方法向主线程传递消息,不对刷新UI;
4、对外暴露一个方法,接收后台传入的时间戳;

在Activity中实现
通过自定义View中的方法,接收时间戳;

2、封装成自定义view

2.1 倒计时功能

方法名 processCountMsg()


private boolean processCountMsg() {
        if (hou == 0 && min == 0 && sec == 0) {
            Toast.makeText(getContext(), "时间到", Toast.LENGTH_SHORT).show();
            return false;
        }
        if (sec > 0) {
            sec--;
        } else {
            sec = 59;
            if (min == 0) {
                min = 59;
                hou--;
            } else {
                min--;
            }
        }
        String hour, minute, second;
        hour = (hou < 10) ? "0" + hou : "" + hou;
        minute = (min < 10) ? "0" + min : "" + min;
        second = (sec < 10) ? "0" + sec : "" + sec;

        tv_hour.setText(hour);
        tv_min.setText(minute);
        tv_sec.setText(second);
        return true;
    }

2.2 初始化倒计时功能及布局文件

初始化代码 init()


private void init() {
        //TODO  LayoutInflater中inflate三个参数代表含义
     LayoutInflater.from(getContext()).inflate(R.layout.layout_countdown_time, this, true);
        tv_hour = findViewById(R.id.btn_countdown_hour);
        tv_min = findViewById(R.id.countdown_min);
        tv_sec = findViewById(R.id.countdown_sec);
        runnable = new Runnable() {
            @Override
            public void run() {
                boolean needProcess = processCountMsg();
                if(!needProcess)return;
                //没隔一秒再次执行一次run方法,实现倒计时功能
                mHandler.postDelayed(this, 1000);
            }
        };
    }

布局文件


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="Http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="horizontal"
    android:layout_margin="10dp">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="距结束:"
        android:textColor="#DAA520"
        android:textSize="20dp"/>
    <TextView
        android:id="@+id/btn_countdown_hour"
        android:layout_width="31dp"
        android:layout_height="30dp"
        android:layout_marginRight="2dp"
        android:background="@drawable/countdown_shape"
        android:gravity="center"
        android:textColor="@color/white" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=":"/>
    <TextView
        android:id="@+id/countdown_min"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_marginRight="2dp"
        android:background="@drawable/countdown_shape"
        android:textColor="@color/white"
        android:gravity="center"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=":"/>
    <TextView
        android:id="@+id/countdown_sec"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:background="@drawable/countdown_shape"
        android:textColor="@color/white"
        android:gravity="center"/>
</LinearLayout>

2.3 提供对外方法,处理时间戳

使用post() 发送消息


public void setData(long curDate) {
        //TODO
        String time;
        //计算时间戳与系统时间的时间差,单位为秒
        int timeDifference = (int) (curDate - System.currentTimeMillis());
        //将总秒数转化为时分秒
        if (timeDifference < 60) {
            time = String.fORMat("00:00:%02d", timeDifference % 60);
        } else if (timeDifference < 3600) {
            time = String.format("00:%02d:%02d", timeDifference / 60, timeDifference % 60);
        } else {
            time = String.format("%02d:%02d:%02d", timeDifference / 3600, timeDifference % 3600 / 60, timeDifference % 60);
        }
        //通过“:”分离时、分、秒
        String[] sArray = time.split(":");
        hou = Integer.parseInt(sArray[0]);
        min = Integer.parseInt(sArray[1]);
        sec = Integer.parseInt(sArray[2]);
        //通过Handler中的post()方法传递message
        mHandler.post(runnable);
    }

使用sendMessage发送消息


private Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case COUNT_MSG:
                    boolean needProcess = processCountMsg();
                    if(!needProcess)return;
                    Message message = Message.obtain();
                    message.what = COUNT_MSG;
                    mHandler.sendMessageDelayed(message, 1000);
                    break;
            }
        }
    };
   public void setData(long curDate) {
      ...............
        Message msg = Message.obtain();
        msg.what = COUNT_MSG;
        mHandler.sendMessage(msg);
    }

3、在Activity中实现


public class MainHandlerActivity extends AppCompatActivity {
    private CountDown mTime;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_handler);
        mTime = findViewById(R.id.view_countdown);
        mTime.setData(System.currentTimeMillis() + 10);
    }
}

4、遇到的问题总结

4.1 LayoutInflate

inflate(int resource,ViewGroup root,boolean attachToRoot)

resource:加载的布局id; root:在该布局的外部再嵌套一层父布局,但不是把当前布局放入到界面已有的布局中,比如xml界面,这个方法只是单穿的返回一个view对象。默认attachToRoot是true。
1、如果root为null,attachToRoot将失去作用,设置任何职都没有意义;
2、如果root不为null,attachToRoot设为true,则会给加载布局文件指定一个父布局,即root;
3、如果root不为null,attachToRoot设为false,则会将布局文件最外层的所有layout属性进行设置,当该view被添加到父view当中时,这些layout属性则自动生效。
4、在不设置attachToRoot参数的情况下,如果root不为null,attachToRoot参数默认为true。

4.2 Handler中post()与sendMessage()区别

post(Runnable r)


public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }
   private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }

sendMessage(msg)


public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }

总结:从源码分析,post(runnable)与sendMessage(msg)本质是一样的,最后返回的都是sendMessageDelayed(msg,0);post()通过调用getPostMessage()方法将Runnable赋值到Message的callback变量中;

消息处理:Looper从MessageQueue中取出Message之后,会调用dispatchMessage方法进行处理;


public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

dispatchMessage两种情况

1、如果Message的callback不为null,一般为通过post(Runnable)方式,会直接执行Runnable的run()。因此这里的Runnable实际上就是一个回调接口,跟线程Thread没有任何关系;

2、如果Message的callback为null,这种一般为sendMessage的方式,则会调用handlerMessage()方法进行处理;

4.3 Handler如何实现线程隔离的


final MessageQueue MQueue;
public static @Nullable Looper myLooper(){
  return sThreadLocal.get();
}

ThreadLocal是一个能创建线程局部变量的类。通过ThreadLocal提供的get和set方法,可以为每一个使用该变量的线程保存一份数据副本,且线程之间是不能相互访问,从而达到变量在线程间隔离、封闭的效果。

4.4 sendMessageDelayed()是如何实现的

向Message队列中插入Message时,会根据Message的执行时间排序,而消息的延时处理的核心实现是在获取Message的阶段,MessageQueue的next方法如下:


Message next(){
if (msg != null) {
                    if (now < msg.when) {
                        // Next message is not ready.  Set a timeout to wake up when it is ready.
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        // Got a message.
                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    // No more messages.
                    nextPollTimeoutMillis = -1;
                }
}

从MessageQueue中取出一个Message,但是当前的系统时间小于Message.when,因此会计算一个timeout,目的是实现在timeout时间段后再将UI线程唤醒,因此后续处理Message的代码只会在timeout时间之后才会被CPU执行;
如果当前系统时间大于或等于Message.when,那么会返回Message给Looper.loop().但是这个逻辑只能保证在when之前的消息不被处理,不能保证一定在when时被处理。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: Handler实现倒计时功能

本文链接: https://www.lsjlt.com/news/124231.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Handler实现倒计时功能
    本文实例为大家分享了Handler实现倒计时功能的具体代码,供大家参考,具体内容如下 1、需求 1.1 实现目标 当后台传递一个时间戳时,与当前系统时间做时间差,并转换为时分秒,作为...
    99+
    2022-11-12
  • vue实现倒计时功能
    本文实例为大家分享了vue实现倒计时功能的具体代码,供大家参考,具体内容如下 通过父组件传入的结束时间减去当前日期得到剩余时间 1.子组件部分 <div class="it...
    99+
    2022-11-11
  • Flutter实现倒计时功能
    本文实例为大家分享了Flutter实现倒计时功能的具体代码,供大家参考,具体内容如下 有一个需求,需要在页面进行显示倒计时,倒计时结束后,做相应的逻辑处理。 实现思路:在Flutte...
    99+
    2022-11-13
  • vue实现时间倒计时功能
    本文实例为大家分享了vue实现时间倒计时功能的具体代码,供大家参考,具体内容如下 需求: 做一个剩余支付时间倒计时的效果 效果图: 代码: <template> ...
    99+
    2022-11-12
  • Android实现时间倒计时功能
    本文实例为大家分享了Android实现时间倒计时功能展示的具体代码,供大家参考,具体内容如下效果展示MainActivity(主页面代码)public class MainActivity extends Activity { priva...
    99+
    2023-05-30
    android 倒计时 roi
  • Vue实现倒计时小功能
    很多项目中都需要实现倒计时功能,例:发送验证码。现在举例实现一个简单的倒计时按钮功能。简单布局,简单操作,简单效果,最主要的是思路和倒计时步骤理解!!! 例、代码如下: 要求:点击提...
    99+
    2022-11-12
  • 如何在Android中使用Handler与Countdowntimer实现一个倒计时功能
    本篇文章为大家展示了如何在Android中使用Handler与Countdowntimer实现一个倒计时功能,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。实现方法去除actionBar闪屏页面一般都...
    99+
    2023-05-31
    android handler countdowntimer
  • Android 简单实现倒计时功能
    在 Android 中倒计时功能是比较常用的一个功能,比如短信验证码,付款倒计时等。实现方式有Handler、Thread 等,但是实现起来都有点麻烦,其实Android已经为...
    99+
    2022-06-06
    倒计时 Android
  • Android实现订单倒计时功能
    先上效果图 1.activity_main.xml <?xml version="1.0" encoding="utf-8"?> <R...
    99+
    2022-06-06
    倒计时 Android
  • android实现倒计时功能代码
    效果图,每隔1秒,变换一下时间  xml: 代码如下: <RelativeLayout xmlns:android="http://schemas.andro...
    99+
    2022-06-06
    倒计时 Android
  • JS怎么实现倒计时功能
    本篇内容主要讲解“JS怎么实现倒计时功能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JS怎么实现倒计时功能”吧!HTML代码:<div id=...
    99+
    2022-10-19
  • python实现简单倒计时功能
    使用python实现简单倒计时exe,供大家参考,具体内容如下 使用tkinter制作界面实现倒计时功能。 使用time.sleep(1)实现 秒级 倒计时 使用...
    99+
    2022-11-12
  • React Native 中实现倒计时功能
    目录正文首次实现最终实现示例正文 在 React Native,该如何实现一个倒计时功能呢? 首次实现 表面看来很简单,譬如像下面这样: const timer = useRef&...
    99+
    2022-11-13
    React Native倒计时 React Native
  • Android中CountDownTimer 实现倒计时功能
    CountDownTimerCountDownTimer 是android 自带的一个倒计时类,使用这个类可以很简单的实现 倒计时功能CountDownTimer 的实现方式 new CountDownTimer(6000,100...
    99+
    2023-05-31
    countdowntimer 倒计时 tim
  • Android怎样实现倒计时功能
    这篇文章主要为大家展示了“Android怎样实现倒计时功能”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Android怎样实现倒计时功能”这篇文章吧。一. 已有倒计时方案存在的问题在开发倒计时功...
    99+
    2023-06-25
  • vue怎么实现时间倒计时功能
    本篇内容介绍了“vue怎么实现时间倒计时功能”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!需求:做一个剩余支付时间倒计时的效果效果图:代码:...
    99+
    2023-06-20
  • Android中Handler实现倒计时的两种方式
    背景:最近项目中,正好做到登录/注册这个功能块。它需要通过发送验证码,在规定的时间内用验证码来完成登录/注册。之前的项目中也有这个功能,但是觉得太复杂了,只好自己重新实现一遍。用Handler来做,觉得代码简介,逻辑也清楚。代码一://在向...
    99+
    2023-05-31
    handler 倒计时 roi
  • Android倒计时功能的实现代码
    好久没有写博客了,趁着年末,总结了下最近一年所遇到的一些技术问题,还有一些自定义控件,比如倒计时功能 首先倒计时的实现方式 1.Handler 2.Timer 3.RxJava...
    99+
    2022-06-06
    Android
  • Android基于CountDownTimer实现倒计时功能
    本文实例讲述了Android编程基于CountDownTimer实现倒计时功能的方法。分享给大家供大家参考,具体如下: 在逛论坛的时候,看到一个网友提问,说到了CountDow...
    99+
    2022-06-06
    倒计时 Android
  • Android利用Chronometer实现倒计时功能
    项目需要实现一个计时的功能,利用Chronometer虽然可以很方便的实现计时功能,但需要的却是一个倒计时控件。 百度了一下方法不少,倒计时的却没有,于是用Chronomete...
    99+
    2022-06-06
    倒计时 Android
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作