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是truemBatteryCharging.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).rssilet band = JSON.parse(data.data).bandLog.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 temporarilylet 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.鸿蒙南向开发方向

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Windows常用软件] word 复制粘贴报错修复

背景 在word 内 ctrlv 会报这个错。 microsoft visual basic MathPage.Wll 运行时错误 网上查了一下是 mathtype 导致的&#xff0c;应该是我之前卸载 mathtype 没有卸载干净导致的。 解决方案 参考知乎里面的一个回答解决的&#xff1a;https://www.zhihu.com/question/37…

高防服务器、高防IP、高防CDN的工作原理是什么

高防IP高防CDN我们先科普一下是什么是高防。“高防”&#xff0c;顾名思义&#xff0c;就犹如网络上加了类似像盾牌一样很高的防御&#xff0c;主要是指IDC领域的IDC机房或者线路有防御DDOS能力。 高防服务器主要是比普通服务器多了防御服务&#xff0c;一般都是在机房出口架设…

网络七层模型之网络层:理解网络通信的架构(三)

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

centos 7安装pgsql14

参考 yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm终端直接运行&#xff1a;yum install -y postgresql14-server 1. 初始化数据库 使用yum安装后&#xff0c;会在系统中创建一个postgres的无密码…

【快速解决】谷歌浏览器驱动的安装及selenium的安装

目录 快速安装Selenium 快速下载对应谷歌驱动 找不到对应版本号的解决方法 快速安装Selenium 安装 Selenium 环境就用下面的代码进行安装&#x1f447;&#x1f447;&#x1f447;&#x1f447;&#x1f447; pip install selenium3.141.0 快速下载对应谷歌驱动 点击这个链接…

关于RPC

初识RPC RPC VS REST HTTP Dubbo Dubbo 特性&#xff1a; 基于接口动态代理的远程方法调用 Dubbo对开发者屏蔽了底层的调用细节&#xff0c;在实际代码中调用远程服务就像调用一个本地接口类一样方便。这个功能和Fegin很类似&#xff0c;但是Dubbo用起来比Fegin还要简单很多&a…

pe启动盘破解windows密码wins电脑登录密码修改重置

目录 1.进入电脑BIOS&#xff0c;设置电脑第一启动项为U盘启动2.进入微pe系统3.然后点击界面最左下方的Windows图标4.点击windows密码选择对应用户名称修改&#xff1b; 1.进入电脑BIOS&#xff0c;设置电脑第一启动项为U盘启动 把u盘插到要清除密码的电脑&#xff0c;然后开机…

Java语法学习 正则表达式

Java语法学习 正则表达式 大纲 具体案例 需求&#xff1a;使用正则表达式完成对文本的查询&#xff0c;regular expression&#xff08;正则表达式&#xff09; 源码解析group package com.wantian.regular;import java.util.regex.Matcher; import java.util.regex.Patt…

日新增百万数据clickhouse大数据解决方案记录分享

公司广告业务需求&#xff0c;需要多个维度统计每个应用的设备数&#xff0c;点击率&#xff0c;展示率&#xff0c;等相关数据&#xff0c;而且数据需要进行去重&#xff0c;我第一时间想到的是利用clickhouse来做统计&#xff0c;因为我们平台访问量比较大&#xff0c;用mysq…

浅谈WPF之MVVM工具包

在之前的WPF示例中&#xff0c;都会用到一个MVVM框&#xff0c;也是一个比较常的MVVM框架&#xff0c;就是MVVM工具包【CommunityToolkit.Mvvm】&#xff0c;今天专门以一个简单的小例子&#xff0c;简述一下MVVM工具包的常见用法&#xff0c;仅供学习分享使用&#xff0c;如有…

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

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

WPF---1.入门学习

学习来源 布局 wpf布局原则 一个窗口中只能包含一个元素 不应显示设置元素尺寸 不应使用坐标设置元素的位置 可以嵌套布局容器 StackPanel-->表单条件查找布局 DataGrid wpf布局容器 StackPanel: 水平或垂直排列元素&#xff0c;Orientation属性分别: Horizontal / Vertic…

Java数据结构-ArrayList

目录 1. 初识集合框架2. ArrayList的介绍3. ArrayList的使用3.1 构造方法3.2 add3.3 addAll3.4 remove3.5 get3.6 set3.7 contains3.8 IndexOf3.9 lastIndexOf3.10 subList 4. ArrayList的遍历4.1 简单粗暴法4.2 循环遍历法4.3 迭代器 1. 初识集合框架 Java集合框架是Java编程…

基于OneAPI+ChatGLM3-6B+FastGPT搭建LLM大语言模型知识库问答系统

搭建大语言模型知识库问答系统 部署OneAPI部署一个LLM模型部署嵌入模型部署FastGPT新建FastGPT对话应用新建 FastGPT 知识库应用 部署OneAPI 拉取镜像 docker pull justsong/one-api创建挂载目录 mkdir -p /usr/local/docker/oneapi启动容器 docker run --name one-api -d …

粘包/半包及解决方案

一、粘包/半包介绍 1&#xff1a;粘包 粘包&#xff08;Packet Concatenation&#xff09;通常发生在基于流式传输协议&#xff08;如 TCP&#xff09;的通信中&#xff0c;因为 TCP 是面向流的传输协议&#xff0c;它不保证数据包的边界&#xff0c;而是将数据视为连续的字节…

密码学及其应用1 —— 密码学概述

1 密码学的基本概念 1.1 网络安全的定义 网络安全是网络领域的一个专业领域&#xff0c;它涵盖了在基础计算机网络基础设施中所采取的措施、网络管理员为保护网络及网络可访问资源免受未授权访问而采纳的政策&#xff0c;以及对其有效性&#xff08;或无效性&#xff09;的持续…

2024年2月线上助听器综合电商(京东天猫淘宝)热销排行榜

鲸参谋监测的综合电商平台&#xff08;京东天猫淘宝&#xff09;2月份助听器品牌销量销额排行榜已揭晓&#xff01; 根据鲸参谋电商大数据显示&#xff0c;2月助听器在综合电商平台销量约为19万&#xff0c;环比上个月下滑了2%&#xff0c;同比去年下滑了25%&#xff1b;销售额…

基于nodejs+vue发艺美发店管理系统python-flask-django-php

系统根据现有的管理模块进行开发和扩展&#xff0c;采用面向对象的开发的思想和结构化的开发方法对发艺美发店管理的现状进行系统调查。采用结构化的分析设计&#xff0c;该方法要求结合一定的图表&#xff0c;在模块化的基础上进行系统的开发工作。在设计中采用“自下而上”的…

javaSwing愤怒的小鸟游戏

一、简介 游戏名称是“愤怒的小鸟”&#xff0c;英文称为“AngryBird”。 “愤怒的小鸟”是著名游戏公司Rovio偶然间开发出来的益智游戏&#xff0c;从2009年12月上市到iOS。&#xff0c;讲述了鸟类和猪因为猪偷鸟蛋反生的一系列故事。游戏的类型版本是横向版本的水平视角&…

6、运行时数据区

Java虚拟机在运行Java程序过程中管理的内存区域&#xff0c;称之为运行时数据区。《Java虚拟机规范》中规定了每一部分的作用。 3.1 程序计数器 程序计数器&#xff08;Program Counter Register&#xff09;也叫PC寄存器&#xff0c;每个线程会通过程序计数器记录当前要执行的…