一、问题描述

前几天APP突然爆出个问题,recyclerview中的item点击没反应,低概率,之前一直没遇到过。

二、问题原因

复现后看log发现,代码在点击事件中加个isFastClick判断,如果是用户频繁点击的话返回true不执行点击事件,而问题出现的时候就一直返回true,但是并没有频繁点击。

问题代码如下,加打印后发现curClickTime - lastClickTime这个值一直是负数,也就是说curClickTime小于之前的lastClickTime。测试的设备的系统时间设置的是自动网络更新,设备会同步Internet时间服务器的时间,当同步新的时间比之前的时间小时,就导致了时间差出现负数。

    private static final int MIN_CLICK_DELAY_TIME = 500;private static long lastClickTime;public static boolean isFastClick() {boolean flag = true;long curClickTime = System.currentTimeMillis();if ((curClickTime - lastClickTime) >= MIN_CLICK_DELAY_TIME) {flag = false;lastClickTime = curClickTime;}Log.d("isFastClick","flage = " + flag);return flag;}

三、解决办法

由于网络时间的不稳定性,在时间间隔的统计时可以使用:SystemClock.elapsedRealtime() ,它是系统启动到当前时刻经过的时间,包括了系统睡眠经过的时间。在CPU休眠之后,它依然保持增长。因此该判断方法可以修改为如下代码:

    private static final int MIN_CLICK_DELAY_TIME = 500;private static long lastClickTime;public static boolean isFastClick() {boolean flag = true;long curClickTime = SystemClock.elapsedRealtime();if ((curClickTime - lastClickTime) >= MIN_CLICK_DELAY_TIME) {flag = false;lastClickTime = curClickTime;}Log.d("isFastClick","flage = " + flag);return flag;}

四、系统时间网络同步

System.currentTimeMillis()获取的是当前系统时间,设置中自动同步网络时间开关也是默认开始的,上面的问题根本原因是自动更新时间后,更新后的时间小于之前的时间,于是看了下系统时间的更新机制,按照自己理解简单梳理了下流程,详细大家可以去看博客Android9.0 本地时区和本地时间的自动更新机制。

Android通过网络同步时间有两种方式:NITZ和NTP,它们使用的条件不同,可以获取的信息也不一样。

1、相关概念

  • NITZ:Network Identity and Time Zone(网络标识和时区),是一种用于自动配置本地的时间和日期的机制,需要运营商支持(通过CS网络),可从运营商获取时间和时区具体信息。目前国内电信、移动都支持NITZ方式更新时间日期,而联通目前不支持。

  • NTP:Network Time Protocol(网络时间协议),用来同步网络中各个计算机的时间的协议。在手机中,NTP更新时间的方式是通过GPRS或wifi向特定服务器获取时间信息,只能更新时间,无法更新时区。

2、NITZ更新流程

第一种:当运营商基站发出更新时间的消息,基站附近的手机接收到对应消息后,最终会通过ServiceStateTracker类方法进行解析设置,流程如下:

(1)当运营商基站发出更新时间、时区的消息;

NITZ消息是基站发送的,手机等设备只能被动接收,一般在下面几种情况下会收到:
1、设备开机第一次注册网络;
2、手机丢网在注网络(如开关飞行模式);
3、跨地区,小基站信息发生变化;

(2)设备收到消息后通过RIL层上报EVENT_NITZ_TIME事件到ServiceStateTracker;

(3)ServiceStateTracker类handler收到消息后,继续调用setTimeFromNITZString方法设置运营商发送的时间和时区信息;

(4)最终在setAndBroadcastNetworkSetTime里调用SystemClock.setCurrentTimeMillis(time)设置系统时间,并发送广播ACTION_NETWORK_SET_TIME通知NetworkTimeUpdateService去更新NITZ设置时间mNitzTimeSetTime;

(5)最终在setAndBroadcastNetworkSetTimeZone里调用alarmManager.setTimeZone(zoneId);设置系统时区,并发送广播ACTION_NETWORK_SET_TIMEZONE;

第二种:ServiceStateTracker类初始化时会注册监听Settings.Global.AUTO_TIME和Settings.Global.AUTO_TIME_ZONE,Setting中开关会改变这两个设置,触发NITZ时间自动更新。

(1)数据库里的Settings.Global.AUTO_TIME和Settings.Global.AUTO_TIME_ZONE发生变化;

(2)回调到NitzStateMachine类中,由handleAutoTimeEnabled和handleAutoTimeZoneEnabled,更新时间计算方式:

long elapsedRealtime = mTimeServiceHelper.elapsedRealtime();
long adjustedCurrentTimeMillis = mSavedNitzTime.mValue + (elapsedRealtime - mSavedNitzTime.mElapsedRealtime)

(3)最终仍然是调用setAndBroadcastNetworkSetTimesetAndBroadcastNetworkSetTimeZone去更新时间。

3、NTP更新流程

NTP更新用到的变量说明,以下间阈值都可以在config文件中修改,路径: /frameworks/base/core/res/res/values/config.xml:

  • mPollingIntervalMs://较长的时间间隔,当同步时间成功后的下一次自动同步的时间间隔,默认为24小时
  • mPollingIntervalShorterMs://较短的时间间隔,当同步时间失败后的下一次自动同步的时间间隔,默认为1分钟
  • mTryAgainTimesMax://当同步时间失败后,会重新尝试同步的次数,默认是3次
  • mTimeErrorThresholdMs://时间会更新的阈值,只有服务器上的时间和设备时间相差超过这个阈值时,才会更新时间,默认是5s

整体流程如下:
(1)SystemServer中调用startOtherServices()创建NetworkTimeUpdateService类实例;

(2)NetworkTimeUpdateService初始化注册监听NITZ时间变化广播、Alarm定时更新时间、网络状态变化以及系统设置中自动更新时间开关的变化(注册NITZ广播ACTION_NETWORK_SET_TIME来更新mNitzTimeSetTime);

(3)NetworkTimeUpdateService类中,Handler中三个事件EVENT_AUTO_TIME_CHANGED,EVENT_POLL_NETWORK_TIME、EVENT_NETWORK_CHANGED中一个发生变化时,会主动触发系统时间更新;

(4)收到事件后执行onPollNetworkTime(int event),里面调用onPollNetworkTimeUnderWakeLock(int event),时间更新的时候要调用wakeLock,让CPU处于运行状态,防止休眠

(5)最终调用SystemClock.setCurrentTimeMillis(mTime.currentTimeMillis())更新系统时间,该更新具体流程如下图。

系统时间更新具体流程:

参考文章:
高并发下,使用System.currentTimeMillis()计算时间差出现负数
Android9.0 本地时区和本地时间的自动更新机制
Android时间更新

Android - System.currentTimeMillis()计算时间差出现负数(NITZ和NTP机制学习)相关推荐

  1. java时间格式转换_Java中System.currentTimeMillis()计算方式与时间的单位转换

    学会与时间赛跑才能赢得时间的尊重,把握好每一天,趁年轻! java中获取系统当前时间相信大家都会,这是经常用到的也是非常简单的,但还是要经常回顾下一些小细节哦! 一.时间的单位转换 1秒=1000毫秒 ...

  2. System.currentTimeMillis()计算方式与时间的单位转换

    一.时间的单位转换 1秒=1000毫秒(ms) 1毫秒=1/1,000秒(s) 1秒=1,000,000 微秒(μs) 1微秒=1/1,000,000秒(s) 1秒=1,000,000,000 纳秒( ...

  3. android 时间差 秒_Android进阶之使用时间戳计算时间差

    本文实例为大家分享了Android使用时间戳计算时间差的具体代码,供大家参考,具体内容如下 因当前项目需要计算时间差,进行数据处理,所以在Csdn上找了一下,之后修修补补是可以用的,建议大家如果用到项 ...

  4. System.currentTimeMillis()的计算方式

    一.时间的单位转换 1秒=1000毫秒(ms) 1毫秒=1/1,000秒(s) 1秒=1,000,000 微秒(μs) 1微秒=1/1,000,000秒(s) 1秒=1,000,000,000 纳秒( ...

  5. System时间计算方式与的单位转换

    一.时间的单位转换 1秒=1000毫秒(ms) 1毫秒=1/1,000秒(s) 1秒=1,000,000 微秒(μs) 1微秒=1/1,000,000秒(s) 1秒=1,000,000,000 纳秒( ...

  6. java时间单位_System.currentTimeMillis()计算方式与时间的单位转换

    一.时间的单位转换 1秒=1000毫秒(ms) 1毫秒=1/1,000秒(s) 1秒=1,000,000 微秒(μs) 1微秒=1/1,000,000秒(s) 1秒=1,000,000,000 纳秒( ...

  7. System.currentTimeMillis()用法及其计算方式与时间的单位转换

    System.currentTimeMillis()的作用是返回当前的计算机时间,格式为当前计算机时间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数 时间的单位转换 1秒=10 ...

  8. java中调用System.currentTimeMillis()获取当前时间来求出时间差及程序执行的时间

    package com.test;import java.util.Scanner; //String的连接1000次 class StringOperate{private String str;p ...

  9. Android 系统(214)---Android 7.1.1时间更新NITZ和NTP详解

    Android 7.1.1时间更新NITZ和NTP详解 1.NTP和NITZ简介 最近在项目中遇到手机首次插上移动卡时不能自动更新时间的问题,就特意跟了下Android系统中手机时间更新有两种方式NT ...

最新文章

  1. linux基础命令 echo
  2. 选择排序(C++版)
  3. jquery.validation.js 使用
  4. editor修改样式 vue_手摸手Electron + Vue实战教程(三)
  5. chrom浏览器-F2使用方法一
  6. 方法的反射---反射学习笔记(二)
  7. pytorch之embedding
  8. 对于一个十进制数A,将A转换为二进制数,然后按位逆序排列,再转换为十进制数(Java)
  9. Spring中部署Activiti流程定义的三种姿势
  10. 2018.12.24-bzoj-2565-最长双回文串
  11. android接收串口发送字符,android发送接收uart串口代码 - 源码下载|通讯/手机编程|android开发|源代码 - 源码中国...
  12. sqlplus连接Oracle的正确语法
  13. 二叉树遍历之先序遍历算法(非递归、递归)入门详解
  14. 调用Windows远程桌面应用
  15. linux steam安装目录,如何在Linux系统的服务器中安装steamCMD,常用steam游戏安装指令有哪些...
  16. 《墨菲定律》读书笔记
  17. Jeffery C. Hill
  18. 复盘:C语言中int a[][3]={1,2,3,4,5,6,7,8}什么意思,int a[3][]又是什么意思,结果为10的是
  19. 什么是SSH 以及常见的ssh 功能
  20. ISTQB- TTA大纲

热门文章

  1. uos统信操作系统安装打印机~
  2. virtualbox四种网络连接方式及其设置方法
  3. 电脑重启出现蓝屏提示“beginning dump of physical memory”解决方法
  4. 简单几步,让微信小程序变身 H5 网页
  5. 百度深度学习--手写数字识别之数据处理
  6. python函数练习题详解_Python练习题详解之函数3(小白友好)
  7. Python爬虫—Scrapy框架—Win10下载安装
  8. JAVA pdf转图片 图片ocr文字
  9. Metabase学习教程:提问-3
  10. TensorFlow学习笔记之 bmp格式、txt格式数据转换成tfrecord 格式