OpenHarmony 源码解析之SystemUi—Statusbar(TS)

作者:董伟

简介

SystemUI应用是OpenHarmony中预置的系统应用,为用户提供系统相关信息展示及交互界面,包括系统状态、系统提示、系统提醒等,例如系统时间、电量信息。

本文主要分析batterycomponent、clockcomponent、wificomponent三大组件:

  1. 导入batteryInfo模块,监听系统电池事件,实时获取电池电量状态
  2. 导入时间模块,调用JS内置函数,实时获取系统时间、日期、星期信息
  3. 导入Wifi模块,监听设备Wlan通信与连接事件,实时获取Wifi开关、供电、连接名等信息

架构图

目录

                    /applications/standard/systemui
                        ├── build.gradle                    # 全局编译配置文件
                        ├── settings.gradle                 # 编译模块配置文件
                        ├── LICENSE                         # 许可文件
                        ├── common                          # 通用工具类目录
                        ├── entry                           # entry模块目录
                        ├── signature                       # 证书文件目录
                        ├── features                        # 子组件目录
                        │   ├── batterycomponent            # 电池组件
                        │   ├── clockcomponent              # 时间组件
                        │   ├── control                     # 控制中心组件
                        │   ├── navigationservice           # 导航栏服务组件
                        │   ├── noticeitem                  # 通知子组件
                        │   ├── notificationservice         # 通知服务组件
                        │   ├── signalcomponent             # sim卡信号组件
                        │   ├── wificomponent               # wifi组件
                        ├── product                         # SystemUI总体功能目录
                            ├── navigationBar               # 导航栏模块目录
                            ├── statusbar                   # 状态栏模块目录
                            ├── systemDialog                # 系统弹框模块目录

batterycomponent

简介

电池组件只需监听‘usual.event.BATTERY_CHANGED’即电池变化事件即可,监听到电池变化,便获取一次电池的状态信息,实时获取电池的状态信息(是否在充电,电量百分比),以实现以下功能:

1.自动在充电时展示更醒目的图标,比如填充绿色、带闪电等

2.动态展示电量百分比变化

官方接口文档

https://developer.harmonyos.com/cn/docs/documentation/doc-references/js-apis-battery-info-0000001100730486

源码地址

https://gitee.com/nicklaus0602/applications_systemui/tree/master/features/batterycomponent

导入模块

import BatteryInfo from '@ohos.batteryInfo';			
import BatterySubscriber from '@ohos.commonEvent';		

申明变量与初始化

var mBatterySoc;
var mBatteryCharging;

let mProgress = Constants.DEFAULT_PROGRESS;
let mBatteryEventSubscriber = null;
let mBatteryEventSubscribeInfo = {
  events: ['usual.event.BATTERY_CHANGED']
}

export class BatteryStatus {
  /**
    * 自定义页面初始化函数,由此函数开始一层一层调用下一个函数,将当前类导出后,只需调用此初始化函数即可完成对Battery模块的使用
    * 这里使用AppStorage.SetAndLink('batterySoc', 0)来跨页面关联数据,只需要在另一个页面中导入当前自定义组件, 	
 	* 并使用@StorageLink('batterySoc')batterySoc: number = 1,即可关联变量mBatterySoc与batterySoc,然后在本页面修改mBatterySoc的值,
 	* 另一个页面的变量batterySoc值也会跟着变动。
 	* 
 	* 页面初始化 即注册订阅事件,监听mBatteryEventSubscribeInfo中的事件
 	*
 	*/
    initBatteryStatus() {
      Log.showInfo(TAG, 'initBatteryStatus');
      mBatterySoc = AppStorage.SetAndLink('batterySoc', 0);
      mBatteryCharging = AppStorage.SetAndLink('batteryCharging', false);
      if (mBatteryEventSubscriber == null) {
        this.registerBatteryListener();
      }
      this.getBatteryStatus();
    }

    uninitBatteryStatus() {
      Log.showInfo(TAG, 'uninitBatteryModel');
      this.unregisterBatteryListener();
    }

}

订阅与回调

/**
   * Subscribe Battery events   创建订阅
   */
private registerBatteryListener() {
  Log.showInfo(TAG, 'registerBatteryListener start');
  BatterySubscriber.createSubscriber(
    mBatteryEventSubscribeInfo,
    this.createBatterySubscriberCallBack.bind(this)
  );
}

/**
 * Unsubscribe Battery events  取消订阅
 *
 */
private unregisterBatteryListener() {
  Log.showInfo(TAG, 'unregisterBatteryListener');
  BatterySubscriber.unsubscribe(mBatteryEventSubscriber, () => {
    Log.showInfo(TAG, `unregister Battery Status Listener ===============`);
  });
}

/**
   * Callback of the subscriber 订阅回调,输出日志
   *
   * @param {Object} err - error returns from the caller
   * @param {Object} data - data returns from the caller
   */

private createBatterySubscriberCallBack(err, data) {
  Log.showInfo(TAG, `Subscriberregister createBatterySubscriberCallBack err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`);
  mBatteryEventSubscriber = data;
  BatterySubscriber.subscribe(mBatteryEventSubscriber, this.batterySubscriberCallBack.bind(this));
}

/**
   * Callback of the events  事件回调
   若err.code == 0,表示函数执行正常,此时判断事件是否为'usual.event.BATTERY_CHANGED',如果该事件发生,即调用电池模块内的函数来获取电池状态信息
   *
   * @param {Object} err - error returns from the caller
   * @param {Object} data - data returns from the caller
   */

private batterySubscriberCallBack(err, data) {
  Log.showInfo(TAG, `batterySubscriberCallBack err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`);
  if (err.code == 0) {
    if (data.event == 'usual.event.BATTERY_CHANGED') {
      this.getBatteryStatus();
    }
  } else {
    Log.showInfo(TAG, 'Subscriberregister error when subscribing ========');
  }
}

获取电池状态、电量

/**
   *  获取电池状态和剩余电量
   */
private getBatteryStatus() {
  Log.showInfo(TAG,'getBatteryStatus')

  // 调用BatteryInfo.batterySOC获取电量值
  let batterySoc = BatteryInfo.batterySOC;

  // 调用BatteryInfo.chargingStatus获取充电状态枚举值
  let batteryCharging = BatteryInfo.chargingStatus;

  if (null == batterySoc) {
    // Set the battery Soc as full when there is no battery hardware 设备无电池硬件时,电量默认为满电
    batterySoc = mProgress;
  }
  if (batterySoc <= 0) {
    // 确保电量值不为负数
    batterySoc = Math.abs(batterySoc) * Constants.PERCENT_NUMBER;
  }

  this.checkBatteryStatus(batteryCharging, (result) => {               
    let batteryStatus = result;
    // 检查电池的充电状态 将电量的值赋给mBatterySoc,
    mBatterySoc.set(batterySoc);
    // 电池状态赋给mBatteryCharging
    // 0是false,1、2、3是true
    mBatteryCharging.set(batteryStatus);
  });
}

/**
   * 传入参数charging,根据charging的值来赋boolean值给batteryStatus,charging为0时表示电池未充电
   表示电池充电状态的枚举:
   NONE 	0  	表示电池充电状态未知
   ENABLE 	1 	表示电池充电状态为使能状态
   DISABLE	2	表示电池充电状态为停止状态
   FULL	    3	表示电池充电状态为已充满状态
   *
   * @param {number} charging - the battery charging status
   * @param {object} callback - Function callback
   */
private checkBatteryStatus(charging, callback) {
  Log.showInfo(TAG, `checkBatteryStatus charging: ${charging}`);
  let batteryStatus;
  switch (charging) {
    case Constants.NONE:
      batteryStatus = false;
      break;
    case Constants.DISABLE:
    case Constants.ENABLE:
    case Constants.FULL:
      batteryStatus = true;
      break;
    default:
      batteryStatus = false;
      break;
  }
  callback(batteryStatus);
}

Wificomponent

注:官方暂无WifiInfo模块的接口文档,只有“import wifi from ‘@ohos.wifi’”模块的相关文档,二者部分属性的枚举值相同,可以稍做参考。

wifi 模块地址:https://developer.harmonyos.com/cn/docs/documentation/doc-references/js-apis-wlan-0000001121342036

简介

wifi模块需要监听的事件较多,需要监听以下事件:

1.连接事件’usual.event.wifi.CONN_STATE’,

2.供电事件’usual.event.wifi.POWER_STATE’(常用于路由器等设备)

3.连接名事件’WIFI_CONNECT_NAME’,

通过监听wifi的连接状态变化来判断wifi的开关状态,通过监听wifi的供电状态变化来判断wifi是否可用,通过监听wifi连接的名称变化来判断当前连接的是哪一个wifi网络。

通过对这三个事件的监听,我们可以实时获取wifi的开关状态,供电状态,连接名称,借此可以实现以下功能:

1.自动根据wifi开关状态设置不同图标

2.自动展示连接的wifi名称

源码地址

https://gitee.com/openharmony/applications_systemui/tree/master/features/wificomponent

导入模块

import WifiInfo from '@ohos.wifi_native_js';
import Subscriber from '@ohos.commonEvent';

申明变量与初始化

var mCommonEventSubscribeInfo = {
  events: [Constants.EVENT_CONN_STATE,
  Constants.EVENT_POWER_STATE, Constants.Event_CONN_NAME]
};

var mCommonEventSubscriber = null;
var mWifiInfo;
var mWifiStatus;
var mWifiOpenStatus;

 export class WifiModel {
 	/**
 	* 自定义页面初始化函数,由此函数开始一层一层调用下一个函数,将当前类导出后,只需调用此初始化函数即可完成对Wifi模块的使用
 	* 页面初始化,这里使用AppStorage.SetAndLink('wifiInfo', 0)来跨页面关联数据,只需要在另一个页面中导入当前自定义组件, 	
 	* 并使用@StorageLink('wifiInfo')wifiInfo: number = 1,即可关联变量mWifiInfo与wifiInfo,然后再本页面修改mWifiInfo的值,
 	* 另一个页面的变量wifiInfo值也会跟着变动。
 	* 
 	* 页面初始化 即注册订阅事件,监听wifi事件变化,并获取wifi当前状态信息
 	*
 	*/
    initWifiModel() {
        Log.showInfo(TAG, `initWifiModel`)
        mWifiInfo = AppStorage.SetAndLink("wifiInfo", 0);
        mWifiStatus = AppStorage.SetAndLink("wifiStatus", false);
        mWifiOpenStatus = AppStorage.SetAndLink("wifiOpenStatus", false);
        if(mCommonEventSubscriber == null){
          this.registerWiFiStatusListener();
        }
        this.getWifiMessage();
      }

    /**
     * 取消初始化时取消订阅
     *
     */
     uninitWifiModel() {
       Log.showInfo(TAG, `uninitWifiModel`)
       this.unregisterWiFiStatusListener()
     }
}

订阅与回调

通过创建对wifi事件的订阅,来监听mCommonEventSubscribeInfo中的三个事件,‘usual.event.wifi.CONN_STATE’,‘usual.event.wifi.POWER_STATE’,‘WIFI_CONNECT_NAME’,若事件发生,则触发回调,

/**
 * Subscribe wifi events  订阅wifi事件,无返回值,创建订阅,监听mCommonEventSubscribeInfo中的事件
 *
 */
registerWiFiStatusListener() : void {
  Log.showInfo(TAG, `register Wifi status listener ===========`);
  Subscriber.createSubscriber(
    mCommonEventSubscribeInfo,
    this.createWifiStatusSubscriberCallBack.bind(this)
  );
}

/**
 * Callback of the subscriber    订阅回调
 *
 * @param {Object} err - error returns from the caller
 * @param {Object} data - data returns from the caller
 */
createWifiStatusSubscriberCallBack(err, data) {
  Log.showInfo(TAG, `createWifiStatusSubscriberCallBack start err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`);
  mCommonEventSubscriber = data;
  Subscriber.subscribe(mCommonEventSubscriber, this.wifiStatusSubscriberCallBack.bind(this));
}

/**
 * Callback of the events     事件回调
 *
 * @param {Object} err - error returns from the caller
 * @param {Object} data - data returns from the caller
 */
private wifiStatusSubscriberCallBack(err, data) {
  Log.showInfo(TAG, `wifiStatusSubscriberCallBack start err:${ JSON.stringify(err)} data: ${ JSON.stringify(data) }`);
  // 默认枚举值 DEFAULT_ERR_CODE: number = 0,代表函数正常运行
  if (err.code == Constants.DEFAULT_ERR_CODE) {
    Log.showInfo(TAG, `wifi data == ${JSON.stringify(data)}`);
    // 枚举值 EVENT_CONN_STATE: string = 'usual.event.wifi.CONN_STATE',表示wifi连接状态变化
    if (data.event == Constants.EVENT_CONN_STATE) {
    /**
     * 枚举值 
     * WIFI_STATE_AP_CONNECTING: number = 1;     正在建立WLAN连接
     * WIFI_STATE_NETWORK_ENABLED: number = 3;	 网络可用
     * WIFI_STATE_NO_NETWORK: number = 4;		 无网络连接
     * 如果正在建立WLAN连接||网络可用||无网络连接,则调用changeWifiStatus()方法,设置mWifiStatus为true,表示当前wifi已激活,否则即设置为false,表	  * 示当前wifi未打开
     */
      if(data.code == Constants.WIFI_STATE_AP_CONNECTING ||
      data.code == Constants.WIFI_STATE_NETWORK_ENABLED ||
      data.code == Constants.WIFI_STATE_NO_NETWORK){
        this.updateWifiInfo();
        this.changeWifiStatus(true);
      }else {
        this.updateWifiInfo();
        this.changeWifiStatus(false);
        mWifiName.set('WLAN');
      }
    }
    // WIFI_POWER_OFF: number = 0;  WIFI_POWER_ON: number = 4;
    // data.code == 0,wifi不可用,mWifiOpenStatus.set(false),
    // data.code == 4,wifi可用,mWifiOpenStatus.set(true)

    // 枚举值 EVENT_POWER_STATE: string = 'usual.event.wifi.POWER_STATE',表示wifi供电状态变化(常用于路由器等设备)
    if (data.event == Constants.EVENT_POWER_STATE) {
      if( data.code == Constants.WIFI_POWER_OFF){
        this.updateWifiInfo();
        this.changeWifiStatus(false);
        mWifiOpenStatus.set(false);
        mWifiName.set('WLAN');
      }else if(data.code == Constants.WIFI_POWER_ON){
        mWifiOpenStatus.set(true);
      }
    }
    // 枚举值 Event_CONN_NAME: string = 'WIFI_CONNECT_NAME',表示连接名称变化,意味着连接到了wifi网络(或者切换到了其他的wifi网络),可以获取当前wifi的信号强度了,更新wifi名称,并设置wifiStatus为true,表示已连接
    if(data.event == 'WIFI_CONNECT_NAME'){
      this.updateWifiName(JSON.parse(data.data).name)
      this.changeWifiStatus(true)

      // rssi是热点的信号强度(dBm),类型为number,取值范围为[0, 4],rssi为4时wifi信号满格
      // band是WLAN接入点的频段,类型为number
      // 将rssi,band传入函数updateWifiInfo()
      let rssi = JSON.parse(data.data).rssi
      let band = JSON.parse(data.data).band
      Log.showInfo(TAG, `WIFI_CONNECT_NAME ================ ${rssi}`)
      this.updateWifiInfo(rssi,band);
    }
  } else {
    Log.showError(TAG, `error when subscribing ========`);
  }
}

/**
 * Unsubscribe wifi events    取消wifi事件订阅(退订)
 *
 */
private unregisterWiFiStatusListener() {
  Subscriber.unsubscribe(mCommonEventSubscriber, () => {
    Log.showInfo(TAG, `unregister Wifi Status Listener ===============`);
  });
}

获取Wifi状态

/**
 * Check the connection status of Wifi  检查wifi的连接状态
 *
 * @param {boolean} status - if display wifi icon
 */
private changeWifiStatus(status) {
  Log.showInfo(TAG, `enter changeWifiStatus ================ ${status}`);
  mWifiStatus.set(status)
}

// 更新wifi信息,传入参数rssi,band
private updateWifiInfo(rssi=Constants.UPDATE_WIFI_INFO_DEFAULT_PARAM,band=Constants.SIGN_LEVEL) {
  Log.showInfo(TAG, `enter changeWifiInfos ================ ${rssi}+${band}`);
  mWifiInfo.set(this.getWifiInfo(rssi,band))
  Log.showInfo(TAG, `mWifiInfo wifiInfo ${mWifiInfo.get()}`);
}
// 更新wifi名称
private updateWifiName(name) {
  Log.showInfo(TAG, `enter changeWifiNames ================ ${name}`);
  mWifiName.set(name);
}

/**
 * Update the image of wifi status   更新wifi状态的图标(根据level,即信号的强度,取值范围为[0, 4]),信号4代表信号满格
 *
 * @param {number} rssi - the rssi number of the connected wifi
 * @return {string} image used to show wifi status
 */
private getWifiInfo(rssi,band) {
  //The current version keeps return 0 as result, set the level as 4(full level) by hand.
  Log.showInfo(TAG, `getWifiImage enter =========`);
  //Fake number of band and rssi for wifi signal level temporarily
  let level = WifiInfo.getSignalLevel(rssi, band);
  Log.showInfo(TAG, `wifi level = ${level}`);
  return level;
}
// 启用wifi(暂不可用)
enableWifi() {
  Log.showInfo(TAG, 'enableWifi ing');
  WifiInfo.enableWifi();
}
// 关闭wifi(暂不可用)
disableWifi() {
  Log.showInfo(TAG, 'disableWifi ing');
  WifiInfo.disableWifi();
}

Clockcomponent

简介

对于系统时间的获取较为简单,只需在页面初始化时调用JS的内置函数来获取系统时间即可,需要注意的是因为要保持所展示的时间实时更新,需要使用以下函数来设置时间间隔,确保每隔一定的时间就调用一次函数,保证时间的实时更新。

setInterval(() => {
    函数名;
  }, 时间间隔);

本文中通过每隔3秒获取一次时间来展示系统时间,满足设备展示“xx:xx”即“小时-分钟“的需要,如果需要精度更高,就需要调整LOOP_TIME,使得调用函数的间隔更短。

源码地址

https://gitee.com/openharmony/applications_systemui/tree/master/features/clockcomponent

获取时间数据

const LOOP_TIME = 3000; 
var mTimeLink;
var mDayLink;
var mWeekDayLink;
var mMonthLink;
/**
  * 获取当前日期和时间 调用getDate()函数,实例化Date对象,获取系统当前时间,调用JS内置函数,每隔三秒将date对象传入
  *	this.updateTime(date);
  *	this.updateDay(date);
  *	this.updateWeekDay(date);
  *	this.updateMonth(date);
  *	函数,获取时间、日、周、月数据
  *
  */
private getCurrentDate() {
  Log.showInfo(TAG, 'getCurrentDate');
  this.getDate();
  timeInterval = setInterval(() => {
    this.getDate();
  }, LOOP_TIME);
}

// 实例化Date对象,获取系统当前时间,并作为参数传入JS内置函数获取想要的时分秒、日、周、月等值
private getDate(){
  Log.showInfo(TAG, 'getDate');
  let date = new Date();
  this.updateTime(date);
  this.updateDay(date);
  this.updateWeekDay(date);
  this.updateMonth(date);
}

/**
 * Update Time.
 * date.toTimeString()返回一个表示该Date对象时分秒部分的时间字符串
   substring(0, 5) 截取下标第0个到第5个字符,即 xx:xx:xx
 * @param {Object} date - Object of Date.
 */
private updateTime(date) {
  let time = date.toTimeString().substring(0, 5);
  mTimeLink.set(time);
}

/**
 * Update Day.
 * date.getDate() 获取每个月的第几号-number
 * @param {Object} date - Object of Date.
 */
private updateDay(date) {
  let day = date.getDate();
  mDayLink.set(day);
}

/**
 * Update WeekDay.
 * date.getDay() 返回每周中的第几天-number,想获得'星期一'这样的value,还需要定义数组来获取,例如:
 var weekdaylist=new Array(7)
	weekdaylist[0]="周日"
	weekdaylist[1]="周一"
	weekdaylist[2]="周二"
	weekdaylist[3]="周三"
	weekdaylist[4]="周四"
	weekdaylist[5]="周五"
	weekdaylist[6]="周六"
	weekdaylist[this.mWeekDay]
 * @param {Object} date - Object of Date.
 */
private updateWeekDay(date) {
  let weekDay = date.getDay();
  mWeekDayLink.set(weekDay);
}

/**
 * Update Month.
 * date.getMonth() 返回月份-number,月份取值范围【0,11】,这里需要加1
 * @param {Object} date - Object of Date.
 */
private updateMonth(date) {
  let month = (date.getMonth() + 1);
  mMonthLink.set(month);
}

结语

本文对源码的方法进行了细致的解读,目标是节省广大开发者分析源码的时间,希望大家阅读本文后,可以将源码中从订阅监听事件到调用方法获得枚举值的整个模块直接拿来使用,以此助力鸿蒙OS生态搭建!

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/487451.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024年3月26日 十二生肖 今日运势

小运播报&#xff1a;2024年3月26日&#xff0c;星期二&#xff0c;农历二月十七 &#xff08;甲辰年丁卯月己丑日&#xff09;&#xff0c;法定工作日。 红榜生肖&#xff1a;鸡、鼠、猴 需要注意&#xff1a;马、狗、羊 喜神方位&#xff1a;东北方 财神方位&#xff1a;…

[HGAME 2023 week2]Designer

[HGAME 2023 week2]Designer 考点&#xff1a;XSS跨站脚本攻击&#xff0c;模板注入 代码审计 function auth(req, res, next) {const token req.headers["authorization"]if (!token) {return res.redirect("/")}try {const decoded jwt.verify(token,…

登录注册界面

T1、编程设计理工超市功能菜单并完成注册和登录功能的实现。 显示完菜单后&#xff0c;提示用户输入菜单项序号。当用户输入<注册>和<登录>菜单序号时模拟完成注册和登录功能&#xff0c;最后提示注册/登录成功并显示注册信息/欢迎XXX登录。当用户输入其他菜…

【随笔】Git -- 基本概念和使用方式(五)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

相机标定 手眼标定 网页版

欢迎使用&#xff0c;请移步ipv6 site (jah10527.github.io)

下载网页上的在线视频 网络视频 视频插件下载

只需要在浏览器上安装一个插件&#xff0c;就可以下载大部分的视频文件&#xff0c;几秒到一两个小时的视频&#xff0c;基本都不是问题。详细解决如下&#xff1a; 0、因为工作需要&#xff0c;需要获取某网站上的宣传视频&#xff0c;我像往常一样&#xff0c;查看视频的url…

C语言回顾笔记

1.变量 2.运算符 3.if判断 4.接力break 5.最大公约数 6.水仙花数 #include<stdio.h> int main(){int n;scanf("%d",&n);//根据输入的位数计算&#xff0c;如最小三位数100 int first 1;int i 1;while(i<n){first *10;i; }printf("first%d\n"…

数据分析POWER BI之power query

1.导入数据 ctrla全选--数据--获取数据--其他来源--来自表格/区域 导入数据&#xff0c;进入编辑模式 2.整理与清除 清除&#xff1a;删除所选列的非打印字符 转换--格式--清除 修整&#xff1a;删除前面和后面的空格 转换---格式---修整&#xff08;修整后前面后面的空格没有了…

代码随想录算法训练营第三十四天|1005. K次取反后最大化的数组和,135,分发糖果

1005. K 次取反后最大化的数组和 题目 给你一个整数数组 nums 和一个整数 k &#xff0c;按以下方法修改该数组&#xff1a; 选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。 重复这个过程恰好 k 次。可以多次选择同一个下标 i 。 以这种方式修改数组后&#xff0c;返回数…

选项式API和组合式API的区别

选项式(options) API 和组合式(composition) API两种不同的风格书写&#xff0c;Vue3 的组件可以使用这两种api来编写。 选项式API和组合式API的区别 选项式API 选项式 API&#xff0c;具有相同功能的放在一起&#xff0c;可以用包含多个选项的对象来描述组件的逻辑&…

500元以内的运动耳机推荐有哪些?五大倍受欢迎的机型总汇

作为一个运动爱好者&#xff0c;我始终认为一款优秀的运动耳机不仅能够带来音乐的享受&#xff0c;更能为运动增添动力&#xff0c;但市面上的运动耳机种类繁多&#xff0c;价格不一&#xff0c;如何选择一款性价比高、功能实用的运动耳机成为了许多消费者的难题&#xff0c;今…

发布文章积分自动增加

controller ApiOperation(value "添加文章")PostMapping("/addwengzhang")public String addwengzhang(RequestBody WengDto wengDto) {if (wengDto.getContent() null || wengDto.getTitle() null) {return "参数不可为空";}User user user…

汽车ABS的bangbang控制和模糊PID控制

1、内容简介 略 82-可以交流、咨询、答疑 2、内容说明 摘要&#xff1a;本文旨在设计一种利用模糊控制理论优化的pid控制器&#xff0c;控制abs系统&#xff0c;达到对滑移率最佳控制范围的要求 &#xff0c;所提出的方案采用级联控制架构&#xff1a;设计用于外环中的车轮打…

[Java、Android面试]_12_java访问修饰符、抽象类和接口

文章目录 1. java访问修饰符2. 抽象类和接口2.1 抽象类2.2 接口2.3 抽象类和接口的区别 本人今年参加了很多面试&#xff0c;也有幸拿到了一些大厂的offer&#xff0c;整理了众多面试资料&#xff0c;后续还会分享众多面试资料。 整理成了面试系列&#xff0c;由于时间有限&…

(一)基于IDEA的JAVA基础8

使用多重if选择结构 多个if条件进行判断: 语法: if(条件1){ 执行语句1&#xff1b; }else if(条件2){ 执行语句2&#xff1b; }else if(条件3){ 执行语句3&#xff1b; }else if (条件4)…… 流程图: 我们来写个好玩的&#xff0c;对暗号: public class Test01 { …

【浅尝C++】类和对象第二弹=>类的6个默认成员函数/运算符重载详谈

&#x1f3e0;专栏介绍&#xff1a;浅尝C专栏是用于记录C语法基础、STL及内存剖析等。 &#x1f6a9;一些备注&#xff1a;之前的文章有点杂乱&#xff0c;这里将前面的知识点重新组织了&#xff0c;避免了过多冗余的废话。 &#x1f3af;每日努力一点点&#xff0c;技术变化看…

电阻器标记方法全解析:如何正确标注电阻器的阻值?

电阻器是一种用来限制电流流动的电子元件。它的主要作用是产生电阻&#xff0c;以控制电流的大小&#xff0c;从而保护其他电子元件不受过大的电流损害。电阻器通常由导电材料制成&#xff0c;电流在流过电阻器时会遇到阻力而产生电压降&#xff0c;使得电流被限制在一个较低的…

水牛社五大赚钱栏目概览:轻松了解项目核心与赚钱原理

很多新用户首次访问水牛社官网时&#xff0c;可能会感到有些迷茫。由于软件介绍相对较长&#xff0c;部分朋友可能缺乏耐心细读。然而&#xff0c;若您真心希望在网络上找到赚钱的机会&#xff0c;深入了解我们的发展历程将大有裨益。简而言之&#xff0c;本文旨在快速带您领略…

C++ assert()函数用法案例详解

参考:https://www.jb51.net/article/222176.htm assert宏的原型定义在<assert.h>中&#xff0c;其作用是如果它的条件返回错误&#xff0c;则终止程序执行。 原型定义&#xff1a; #include <assert.h> void assert( int expression );assert的作用是先计算表达…

【开发环境搭建篇】Redis服务器端安装和配置

作者介绍&#xff1a;本人笔名姑苏老陈&#xff0c;从事JAVA开发工作十多年了&#xff0c;带过大学刚毕业的实习生&#xff0c;也带过技术团队。最近有个朋友的表弟&#xff0c;马上要大学毕业了&#xff0c;想从事JAVA开发工作&#xff0c;但不知道从何处入手。于是&#xff0…