Android 8.1 Doze模式分析(二)——Light Doze模式

article/2025/9/15 11:32:16

概述

LightDoze表示轻度doze模式,如果设备处于未充电且屏幕关闭状态,但未处于静止状态时,就会进入Light Doze模式,在LightDoze模式中,会定期进行维护,这种维护会持续N分钟,在维护状态(maintenance)时,会进行网络的访问,和同步、JobScheduler的操作,然后又会进入Idle状态,持续多次。之后如果设备仍旧保持静止,则会进入Deep Doze模式,因此,如果没有运动传感器,则无法检测设备是否处于静止,因此无法进入Deep Doze模式。

原理

在DeviceIdleController(以下简称DIC)中,定义了几个用来表示Light Doze模式有关的值,这些值及其意义如下:


//表示轻度doze模式
private int mLightState;
//mLightState状态值,表示设备处于活动状态
private static final int LIGHT_STATE_ACTIVE = 0;
//mLightState状态值,表示设备处于不活动状态
private static final int LIGHT_STATE_INACTIVE = 1;
//mLightState状态值,表示设备进入空闲状态前,需要等待完成必要操作
private static final int LIGHT_STATE_PRE_IDLE = 3;
//mLightState状态值,表示设备处于空闲状态,该状态内将进行优化
private static final int LIGHT_STATE_IDLE = 4;
//mLightState状态值,表示设备处于空闲状态,要进入维护状态,先等待网络连接
private static final int LIGHT_STATE_WAITING_FOR_NETWORK = 5;
//mLightState状态值,表示设备处于维护状态
private static final int LIGHT_STATE_IDLE_MAINTENANCE = 6;
//mLightState状态值,表示设备轻度Doze被覆盖,开始进入深度Doze模式
private static final int LIGHT_STATE_OVERRIDE = 7;

从上述代码中可知,共有7个状态类表示Light Doze模式的不同状态。接下来开始分析Light Doze的实现以及其七个状态之间的转换。

在第一部分中分析启动流程时,当DCI启动流程的最后,会调用becomeInactiveIfAppropriateLocked()方法和becomeActiveLocked()方法,这两个方法用来切换交互/不可交互状态,这里先看第一个方法:

void becomeInactiveIfAppropriateLocked() {//仅当屏幕灭屏且没充电时,才能进入Doze模式,mForceIdle是shell设置相关if ((!mScreenOn && !mCharging) || mForceIdle) {//处理深度Doze,该状态表示当前设备处于交互状态,即亮屏、有动作移动if (mState == STATE_ACTIVE && mDeepEnabled) {//该状态表示DeepDoze的不可交互状态mState = STATE_INACTIVE;//重置标记值、取消原有的用于DeepDoze的alarm等resetIdleManagementLocked();//设置DeepAlarm,时间为30minsscheduleAlarmLocked(mInactiveTimeout, false);//30mins}//进入轻度Doze模式if (mLightState == LIGHT_STATE_ACTIVE && mLightEnabled) {//处理LightDoze模式进入不可交互状态mLightState = LIGHT_STATE_INACTIVE;//取消用于LightDoze的定时Alarm,重置标记值resetLightIdleManagementLocked();//设置用于LightDoze模式的Alarm,到达时间后回调//mLightAlarmListener,时间为5minsscheduleLightAlarmLocked(mConstants.LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT);//5mins}}
}

如果要执行该方法,首要条件必须是灭屏且放电,或者mForceIdle为true,mForceIdle是用于在adb shell下使用命令设置的,因此分析时可忽略。
如果满足灭屏且放电,则分别进行DeepDoze和LightDoze的判断.这里先分析Light Doze的判断,如果当前LightDoze处于LIGHT_STATE_ACTIVE状态,且mLightEnabled为true,则进行如下的处理:

  • 1.将mLightState变为LIGHT_STATE_INACTIVE状态,表示不可交互状态(灭屏);
  • 2.重置LightDoze相关的工作和值;
  • 3.发送一个5mins的定时Alarm。

在DIC启动时,将mLightState设置为了LIGHT_STATE_ACTIVE,所以这个值是一个默认值。先来看第二点,调用了resetLightIdleManagementLocked(),该方法如下:

void resetLightIdleManagementLocked() {//取消mLightAlarmListener要接受的AlarmcancelLightAlarmLocked();
}
void cancelLightAlarmLocked() {if (mNextLightAlarmTime != 0) {mNextLightAlarmTime = 0;mAlarmManager.cancel(mLightAlarmListener);}
}

如果设有用于LightDoze的定时Alarm,则进行取消。
再来看看第三点,在scheduleLightAlarmLocked()方法中:

void scheduleLightAlarmLocked(long delay) {mNextLightAlarmTime = SystemClock.elapsedRealtime() + delay;//到达时间后,回调mLightAlarmListener.onAlarm()mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,mNextLightAlarmTime, "DeviceIdleController.light", mLightAlarmListener, mHandler);
}

结合第二点和第三点,可以认为重置了一个用于LightDoze的Alarm定时器。mLightAlarmListener用来接受Alarm的回调,定时器到达指定时间后,会触发mLightAlarmListener接口的onAlarm()方法,从而在onAlarm()中完成接下来的工作,该接口如下:

private final AlarmManager.OnAlarmListener mLightAlarmListener= new AlarmManager.OnAlarmListener() {@Overridepublic void onAlarm() {synchronized (DeviceIdleController.this) {//每次LightDoze的状态改变,都会调用该方法进行处理stepLightIdleStateLocked("s:alarm");}}
};

因此,当定时器到达时间后,通过onAlarm()方法调用stepLightIdleStateLocked()方法。stepLightIdleStateLocked()方法负责LightDoze模式的改变,在这个方法中根据不同的状态发送不同的Alarm定时器来改变状态。可以这样理解,LightDoze模式改变就是通过scheduleLightAlarmLocked()---onAlarm()---stepLightIdleStateLocked()---scheduleLightAlarmLocked()不断的循环来进行的,这样说可能不太明白,还是从代码进行分析,最后对它进行总结,该方法代码如下:

void stepLightIdleStateLocked(String reason) {//如果mLigthSate为LIGHT_STATE_OVERRIDE,说明DeepDoze处于Idle状态,由// DeepDoze将LightDoze覆盖了,因此不需要进行LightDoze了if (mLightState == LIGHT_STATE_OVERRIDE) {return;}switch (mLightState) {case LIGHT_STATE_INACTIVE://当前最小预算时间mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;//1min//表示LightDoze 进入空闲(Idle)状态的时间mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT;//5mins//LightDoze进入维护状态(maintenance)的开始时间mMaintenanceStartTime = 0;//如果有活动的操作或JobScheduler、Alarm处于活动状态,//再给他们一次机会进行关闭,break返回,//否则由于没有break,会进入下条case语句if (!isOpsInactiveLocked()) {//将状态置为LIGHT_STATE_PRE_IDLE状态mLightState = LIGHT_STATE_PRE_IDLE;//设置一个定时器,到达时间后用来处理LightDoze处于PRE_IDLE//状态的操作scheduleLightAlarmLocked(mConstants.LIGHT_PRE_IDLE_TIMEOUT);//10minsbreak;}case LIGHT_STATE_PRE_IDLE:case LIGHT_STATE_IDLE_MAINTENANCE:if (mMaintenanceStartTime != 0) {//维护状态的时长long duration = SystemClock.elapsedRealtime() - mMaintenanceStartTime;if (duration < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) {// mCurIdleBudget += (mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET-duration);} else {// mCurIdleBudget -= (duration-mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET);}}mMaintenanceStartTime = 0;//重置维护开始时间//设置一个定时器,到达时间后用来处理LightDoze处于IDLE状态的操作scheduleLightAlarmLocked(mNextLightIdleDelay);//计算下次进入Idle状态的mNextLightIdleDelay = Math.min(mConstants.LIGHT_MAX_IDLE_TIMEOUT,//900000,15mins(long)(mNextLightIdleDelay * mConstants.LIGHT_IDLE_FACTOR));if (mNextLightIdleDelay < mConstants.LIGHT_IDLE_TIMEOUT) {mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT;}//将LightDoze模式置为IDLE状态,开始进行一些限制mLightState = LIGHT_STATE_IDLE;addEvent(EVENT_LIGHT_IDLE);//申请一个wakelock锁,保持CPU唤醒mGoingIdleWakeLock.acquire();//处理LightDoze进入Idle状态后的操作mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON_LIGHT);break;case LIGHT_STATE_IDLE:case LIGHT_STATE_WAITING_FOR_NETWORK:if (mNetworkConnected || mLightState == LIGHT_STATE_WAITING_FOR_NETWORK) {//如果网络有链接或者当前LightDoze模式为等待网络状态,则进行维护,// 并将LightDoze模式退出IDLE状态,进入维护状态mActiveIdleOpCount = 1;mActiveIdleWakeLock.acquire();mMaintenanceStartTime = SystemClock.elapsedRealtime();// 保证10<=mCurIdleBudget<=30mins ,mCurIdleBudget是维护状态的时间if (mCurIdleBudget < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) {mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;} else if (mCurIdleBudget > mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET) {mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET;}//设置一个定时器,到达时间后用来处理LightDoze处于维护状态的操作scheduleLightAlarmLocked(mCurIdleBudget);mLightState = LIGHT_STATE_IDLE_MAINTENANCE;//进入维护状态addEvent(EVENT_LIGHT_MAINTENANCE);//处理LightDoze进入Maintenance状态后的操作mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);} else {//将LightDoze模式置为LIGHT_STATE_WAITING_FOR_NETWORK,//在进入维护状态前需要获取网络//设置一个定时器,到达时间后用来处理LightDoze处于//WAITING_FOR_NETWORK状态的操作scheduleLightAlarmLocked(mNextLightIdleDelay);//600000,5minsmLightState = LIGHT_STATE_WAITING_FOR_NETWORK;EventLogTags.writeDeviceIdleLight(mLightState, reason);}break;}
}

在这个方法中,处理了LightDoze所有的状态改变时的工作,同时也会在这个方法中进行状态的转换,各个case分析如下:

  • case LIGHT_STATE_INACTIVE:

这部分主要处理由INACTIVEIDLE/PRE_IDLE的过程。
第一次调用该方法时,LightDoze模式处于INACTIVE(不可交互状态)状态,因此会进入第一个case语句,在这个语句中,如果当前还有为处理完的任务,则会先进入IDLE状态之前的一个状态——PRE_IDLE状态,如果没有需要处理的任务,由于这里没有break,因此会继续执行到下一条case语句,将状态由INACTIVE设置为IDLE状态,并开始限制网络访问、Job延迟等处理;PRE_IDLE状态是为了再等待一次未处理完成的工作,这个状态持续5mins,直到下次Alarm时间到再次进入该方法,直接走第二条case语句。因此,在执行第二条语句之前,LightDoze处于PRE_IDLE或者INACTIVE状态。

  • case LIGHT_STATE_PRE_IDLE:
  • case LIGHT_STATE_IDLE_MAINTENANCE:

这部分主要处理由PRE_IDLE/INACTIVEIDLEMAINTENANCEIDLE的过程。在执行这两个case语句之前时,LightDoze处于PRE_IDLE或者INACTIVE状态,此时会变为IDLE状态;或者LightDoze处于MAINTENANCE,此时会变为IDLE状态。当LightDoze状态转为IDLE后,会通过Handler发送广播,通知IDLE状态的改变,开始做优化工作(无法访问网络、Job、同步延迟)。

  • case LIGHT_STATE_IDLE:
  • case LIGHT_STATE_WAITING_FOR_NETWORK:

这部分主要处理由IDLEWAITING_FOR_NETWORKWAITING_FOR_NETWORKMAINTENANCE的过程。当LightDoze状态由IDLE转换为MAINTENANCE后,会通过Handler发送广播,通知IDLE状态的改变,说明进入维护状态,开始做维护工作。
LightDoze的状态转换图如下:
这里写图片描述

下面我们就看当LightDoze状态转换为IDLEMAINTENANCE后,是如何进行功耗的优化和维护工作的。

在上面我们分析了,当由INACTIVE/PRE_IDLE状态进入IDLE状态时,和由IDLE/WAIT_FOR_NETWORK状态时,会通过Handler发送一个LightDoze模式改变的广播,通知接收器进行相应的处理,这里进行详细分析,进入IDLE状态时和进入维护状态时Handler中的相关操作如下:

@Override public void handleMessage(Message msg) {.............................switch (msg.what) {case MSG_REPORT_IDLE_ON://LightDoze模式进入IDLE状态case MSG_REPORT_IDLE_ON_LIGHT: {if (msg.what == MSG_REPORT_IDLE_ON) {//DeepDoze相关,这里略去........} else {//通知PMS设置DeepDoze模式不处于IDLE状态deepChanged = mLocalPowerManager.setDeviceIdleMode(false);//通知PMS设置轻度Doze模式处于IDLE状态lightChanged = mLocalPowerManager.setLightDeviceIdleMode(true);}try {//通知NetworkPolicyManager LightDoze进入IDLE状态mNetworkPolicyManager.setDeviceIdleMode(true);//通知BatteryStatsService统计LightDoze进入IDLE状态mBatteryStats.noteDeviceIdleMode(msg.what == MSG_REPORT_IDLE_ON? BatteryStats.DEVICE_IDLE_MODE_DEEP: BatteryStats.DEVICE_IDLE_MODE_LIGHT, null, Process.myUid());} catch (RemoteException e) {}//发送DeepDoze模式改变的广播if (deepChanged) {getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);}if (lightChanged) {//发送LightDoze模式改变的广播getContext().sendBroadcastAsUser(mLightIdleIntent,UserHandle.ALL);}//释放wakelock锁mGoingIdleWakeLock.release();} break;//退出IDLE状态时,包括DeepDozecase MSG_REPORT_IDLE_OFF: {final boolean deepChanged = mLocalPowerManager.setDeviceIdleMode(false);final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);try {mNetworkPolicyManager.setDeviceIdleMode(false);mBatteryStats.noteDeviceIdleMode(BatteryStats.DEVICE_IDLE_MODE_OFF,null, Process.myUid());} catch (RemoteException e) {}if (deepChanged) {incActiveIdleOps();getContext().sendOrderedBroadcastAsUser(mIdleIntent, UserHandle.ALL, null, mIdleStartedDoneReceiver,null, 0, null, null);}if (lightChanged) {incActiveIdleOps();getContext().sendOrderedBroadcastAsUser(mLightIdleIntent, UserHandle.ALL,null, mIdleStartedDoneReceiver,null, 0, null, null);}decActiveIdleOps();} break;}
}

从这部分代码可以知道,在LightDoze进入IDLE状态或退出IDLE状态时时,首先通知PMS、NetworkPolicyManager设置DeviceIdleMode为true或false,然后发送一个Intent为mLightIdleIntent的广播,该mLightIdleIntent是在启动时onBootPhase()中定义:

mLightIdleIntent = new Intent(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
mLightIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY| Intent.FLAG_RECEIVER_FOREGROUND);

因此,当LightDoze进入IDLE状态时或退出IDLE状态进入MAINTENANCE状态时,都会发送该广播,其他模块如果注册了该广播接受器,则会触发onReceive()方法进行处理。当前版本中注册了mLightIdleIntent的广播接收器的模块只有一处:DeviceIdleJobsController,该类是一个用于根据Doze模式状态控制”Job”的控制类,当Doze(LightDoze和DeepDoze)模式状态为IDLE时,该类中会限制所有除白名单外的应用的”Job”,当退出IDLE状态时,该类中会解除这些应用的”Job”限制,这里所指的”Job”,时Android L后实现的一个JobScheduler机制,允许开应用在符合某些条件时创建执行在后台的任务。接受广播方法如下:

private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {final String action = intent.getAction();//当DeepDoze或LightDoze的IDLE状态改变时,都会执行updateIdleMode()if (PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED.equals(action)|| PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)) {updateIdleMode(mPowerManager != null? (mPowerManager.isDeviceIdleMode()|| mPowerManager.isLightDeviceIdleMode()): false);} else if (PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED.equals(action)) {updateWhitelist();}}
};

再来看下DeviceIdleJobsController中updateIdleMode()方法:

void updateIdleMode(boolean enabled) {boolean changed = false;// Need the whitelist to be ready when going into idleif (mDeviceIdleWhitelistAppIds == null) {updateWhitelist();//更新白名单列表}synchronized (mLock) {if (mDeviceIdleMode != enabled) {changed = true;}mDeviceIdleMode = enabled;//遍历所有的JobmJobSchedulerService.getJobStore().forEachJob(mUpdateFunctor);}if (changed) {//回调到JobSchedulerService中,停止或开始JobmStateChangedListener.onDeviceIdleStateChanged(enabled);}
}

在这个方法中,通过JobSchedulerService回调onDeviceIdleStateChanged()方法对后台Jobs进行限制或运行,至于如何限制,涉及到JobScheduler相关内容,不再往下分析。
再此对上面分析内容进行一次总结:
当LightDoze进入IDLE/MAINTENANCE状态时,在Handler中:

  • 1.通知NetworkPolicyManagerService限制/打开网络;
  • 2.发送广播,DeviceIdleJobsController中进行接受,限制/运行JobService.

如此反复多次,如果设备依旧保持静止且灭屏,则30分钟后,DeepDoze的Alarm时间到,因此会进入DeepDoze模式。LightDoze模式转换图示如下:

这里写图片描述

核心

1.如何限制网络?

DeviceIdleController中仅仅调用NetworkPolicyManagerService提供的接口,具体如何限制在NetworkPolicyManagerService内部实现:

mNetworkPolicyManager.setDeviceIdleMode(true);

2.如何延迟Job?

进入退出LightDoze后发送广播,DeviceIdleJobController中进行了接收,接收后也是内部进行实现:

    // onReceiveprivate final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {final String action = intent.getAction();if (PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED.equals(action)|| PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)) {updateIdleMode(mPowerManager != null? (mPowerManager.isDeviceIdleMode()|| mPowerManager.isLightDeviceIdleMode()): false);} else if (PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED.equals(action)) {updateWhitelist();}}};

http://chatgpt.dhexx.cn/article/BF567ZeZ.shtml

相关文章

Doze模式时序调研

Doze模式 机型 Light idle Deep idle 时序 定制白名单 AppStandby BLE Scanning管控 华为P20 Pro 开启 64.5分钟进入deep idle 有 开启 禁止BLE scanning OPPO F11 Pro 开启 30分钟进入deep idle 有 开启 允许BLE scanning 小米 MI 8 Pro 开启 64.5分钟进入…

Android7.0 Doze模式分析(一)Doze介绍 DeviceIdleController

参考&#xff1a;http://blog.csdn.net/gaugamela/article/details/52981984 在Android M中&#xff0c;Google就引入了Doze模式。它定义了一种全新的、低能耗的状态。 在该状态&#xff0c;后台只有部分任务被允许运行&#xff0c;其它任务都被强制停止。 在之前的博客中分…

android 7.0低电耗Doze模式

从 Android 6.0&#xff08;API 级别 23&#xff09;开始&#xff0c;Android 引入了两个省电功能&#xff0c;可通过管理应用在设备未连接至电源时的行为方式为用户延长电池寿命。 低电耗(Doze)模式通过在设备长时间处于闲置状态时推迟应用的后台 CPU 和网络 Activity 来减少电…

Android O Doze模式的状态

现象 以下是BugReport日志 日志 STATE_ACTIVE 2,006: 11-17 10:24:59.876137 900 900 I DeviceIdleController: updateChargingLocked: chargingtrue 2,007: 11-17 10:24:59.876244 900 900 I DeviceIdleController: becomeActiveLocked, reason charging 2,25…

【Android】Doze模式识别与检测

从 Android 6.0&#xff08;API 级别 23&#xff09;开始&#xff0c;Android 引入了两个省电功能&#xff1a;Doze模式&#xff08;官方翻译为低电耗模式&#xff09;和 App Standby模式&#xff08;官方翻译为应用待机模式&#xff09;&#xff0c;可通过管理应用在设备未连接…

Android 8.1 Doze模式分析(一)——Doze简介和DeviceIdleController的启动

概述 Doze模式&#xff0c;官方翻译为低电耗模式&#xff0c;是Andoriod6.0增加的一项系统服务&#xff0c;主要目的是为了优化电池性能&#xff0c;增加电池续航时间&#xff0c;Doze模式又分两种模式&#xff1a;深度Doze模式(Deep Doze)和轻度Doze模式(Light Doze)&#xf…

Android 6.0的省电技术Doze作用影响以及避免方法

从android 6.0开始&#xff0c;谷歌引入了两项新的省电技术延长电池使用时间&#xff0c;分别是Doze&#xff08;休眠&#xff09;和App Standby&#xff08;app待命模式&#xff09;&#xff0c;只要app是运行在6.0&#xff08;api 23&#xff09;及以上的系统&#xff0c;无论…

Doze模式简介

Doze模式是自Android 6.0开始引入的两项省电功能的其中之一&#xff0c;还有一个就是appstandby&#xff0c;通过管理应用在设备未连接至电源时的行为方式&#xff0c;帮助用户延长电池寿命。当用户长时间未使用设备时&#xff0c;低电耗模式会延迟应用的后台 CPU 和网络活动&a…

Android中的Doze模式

概述 Android 6.0引入的Doze机制在于节省系统耗电量&#xff0c;保护电池&#xff0c;延长电池的使用时间。当设备未连接至电源&#xff0c;且长时间处于闲置状态时&#xff0c;系统会将应用进入Doze&#xff0c;置于App Standby模式。而最终的效果&#xff0c;能提升30%的电量…

Mock工具之Mockito实战

在实际项目中写单元测试的过程中我们会发现需要测试的类有很多依赖&#xff0c;这些依赖项又会有依赖&#xff0c;导致在单元测试代码里几乎无法完成构建&#xff0c;尤其是当依赖项尚未构建完成时会导致单元测试无法进行。为了解决这类问题我们引入了Mock的概念&#xff0c;简…

Mockito 入门

目录 1.什么是 Mock 测试&#xff1f;2.Mockito简介3.在 SpringBoot 单元测试中使用 Mockito3.1 Maven依赖&#xff1a;3.2 UserService.java3.3 User.java3.4 thenReturn系列方法&#xff08;测试桩&#xff09;3.5 thenThrow系列方法3.6 verify 系列方法 4.Spring中mock任何容…

Mock工具之Moco使用教程

目录 一、什么是Moco二、安装&配置三、接口配置&测试3.1 第一个简单的请求&#xff1a;3.2 Get请求&#xff1a;3.3 Post请求&#xff1a;3.4 返回值为Json格式的请求&#xff1a;3.5 带cookie信息才能访问的post请求&#xff1a;3.6 重定向请求&#xff1a;3.7 前后端…

mock功能

目标 了解mock的作用及使用场景&#xff1b; mock使用场景 mock&#xff1a;假的 前端程序员提到的mock数据的含义是&#xff1a;真的假数据 真的&#xff1a;符合接口规范要求的。 假数据&#xff1a;数据是人为创建出来的&#xff0c;不是真正的业务数据。 什么时候需…

mock的介绍

1.什么是mock mock测试是以可控的方式模拟真实的对象行为。程序员通常创造模拟对象来测试对象本身该具备的行为&#xff0c;很类似汽车设计者使用碰撞测试假人来模拟车辆碰撞中人的动态行为 2.为什么要使用mock 之所以使用mock测试&#xff0c;是因为真实场景很难实现或者短…

Mock介绍

mock的定义&#xff08;what&#xff09;&#xff1a; mock是在测试过程中&#xff0c;对于一些不容易构造/获取的对象&#xff0c;创建一个mock对象来模拟对象的行为 为什么要使用mock&#xff08;why&#xff09;&#xff1a; 在做单元测试过程中&#xff0c;经常会有以下的…

Mockito单元测试

文章目录 Mockito单元测试为什么要使用Mock?导入依赖import导入包使用Mock模拟测试某个类中的某个方法是否可以成功执行使用Mock模拟某个类的方法&#xff0c;自己给这个方法返回我们指定的值使用Mock模拟某个方法调用后会抛出指定的异常使用Mock模拟测试某个类中的某个方法(加…

javascript 中怎么判断为数字类型

javascript中判断变量是否为数字类型抄的方法有两种&#xff1a; 方法一&#xff1a; function isnum(s) { if(s!null){ var r,re; re /\d*/i; //\d表示数字,*表示匹配多个数字 r s.match(re); return (rs)?true:false; } return false; } 方法二&#xff1a; function isnu…

js判断字符串是不是一个纯数字

1.使用隐式转换判断 使用parseInt()/parseFloat()会把其他类型转换为数值&#xff0c;转换结果为数值或NaN,转换字符串的时候&#xff0c;头部内容有数值就会截取前面&#xff0c;如123456aff789bb转成123456&#xff0c;后面即使有数字也不会转换处理&#xff0c;开头如果是字…

javaScript 判断是否为数值类型的三种方法

第一种方法:isNaN(value) isNaN : isNaN() 函数用于检查其参数是否是非数字值。 返回true则判断为非数值。缺点&#xff1a;空字符串&#xff0c;空格 &#xff0c;null会做为数字0进行处理&#xff0c;结果为falsehttps://www.w3school.com.cn/js/jsref_isnan.anusp 第二种方法…

JS中判断变量是否为数字方法

推荐教程&#xff1a;《JavaScript视频教程》 JavaScript 是一种动态类型语言&#xff0c;这意味着解释器在运行时确定变量的类型。实际上&#xff0c;这也允许我们在相同的代码中使用相同的变量来存储不同类型的数据。如果没有文档和一致性&#xff0c;我们在使用代码时并不总…