鸿蒙应用服务开发【自定义通知角标】

news2025/1/10 20:37:28

自定义通知角标

介绍

本示例主要展示了设定应用的桌面图标角标的功能,使用@ohos.notificationManager接口,进行桌面角标的设置,通知的发送,获取等。

效果预览

1

使用说明

  1. 在主界面,可以看到当前应用的所有消息通知;
  2. 点击右下角Tab页签进入通知发送页面,点击对应的通知即可发送相应类型的通知,点击几次发送几条;
  3. 点击左下角Tab页签进入消息列表,可以查看刚才发送的消息,消息右边会显示消息数量,点击相应的消息可进行消息读取,取消相应通知;
  4. 下拉通知栏,可以看到角标数量,对应消息数量。

具体实现

  • 允许发送通知,发送通知的功能接口封装在NotificationUtil,源码参考:[NotificationUtil.ets]
/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { notificationManager } from '@kit.NotificationKit';
import { logger } from '../util/Logger';
import { notificationManagement } from '../notification/NotificationManagementUtil';
import { BusinessError } from '@kit.BasicServicesKit';

const TAG: string = 'NotificationUtilModel';

class NotificationUtil {
  /**
   * enable notification
   */
  private id: number = 0

  async enableNotification() {
    try {
      notificationManager.requestEnableNotification(AppStorage.get('context'), (err: BusinessError): void => {
        if (err) {
          logger.error(TAG, `requestEnableNotification failed, code is ${err.code}, message is ${err.message}`);
        } else {
          logger.info(TAG, 'requestEnableNotification success');
        }
      });
      logger.info(TAG, `enableNotification success`);
    } catch (err) {
      logger.info(TAG, `enableNotification err ${JSON.stringify(err)}`);
    }
  }

  /**
   *
   * @param notificationRequest
   * @param id, Support specifying notification id when publishing notifications
   */
  async publishNotification(notificationRequest: notificationManager.NotificationRequest, group?: string) {
    notificationRequest.id = this.id;
    this.id++;
    if (group) {
      notificationRequest.groupName = group;
    }

    try {
      await notificationManager.publish(notificationRequest);
      logger.info(TAG, `publish notification success`);
      // 通知管理器添加新通知
      await notificationManagement.addNotification(notificationRequest);
    } catch (err) {
      if (err) {
        logger.info(TAG, `publishNotification err ${JSON.stringify(err)}`);
      }
    }
  }

  /**
   * cancel notification by id
   */
  async cancelNotificationById(id: number) {
    try {
      await notificationManager.cancel(id);
      logger.info(TAG, `cancel success`);
    } catch (err) {
      if (err) {
        logger.info(TAG, `cancel err ${JSON.stringify(err)}`);
      }
    }
  }

  /**
   * cancel all notification
   */
  async cancelAllNotifications() {
    try {
      await notificationManager.cancelAll();
      logger.info(TAG, `cancel all success`);
    } catch (err) {
      if (err) {
        logger.info(TAG, `cancel all err ${JSON.stringify(err)}`);
      }
    }
  }
}

export let notificationUtil = new NotificationUtil();

  • 允许发送通知:在进入[Index.ets] 前通过notificationUtil.enableNotification()调用notification.requestEnableNotification()接口向用户请求发送通知;
/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { NotificationList } from '../components/NotificationList';
import { NoticePublish } from '../components/NotificationPublish';

export interface TabImage {
  selectedImage: Resource,
  unselectedImage: Resource,
}

const MESSAGE_TAB: TabImage = {
  selectedImage: $r('app.media.ic_messages_filled'),
  unselectedImage: $r('app.media.ic_messages'),
}
const NOTIFICATION_TAB: TabImage = {
  selectedImage: $r('app.media.ic_public_send_filled'),
  unselectedImage: $r('app.media.ic_public_send'),
}

interface TAB_INDEX_TYPE {
  MESSAGE_TAB: number
  NOTIFICATION_TAB: number
}

const TAB_INDEX: TAB_INDEX_TYPE = {
  MESSAGE_TAB: 0,
  NOTIFICATION_TAB: 1
}

@Entry
@Component
struct Index {
  @State tabsIndex: number = 0

  @Builder TabBarBuilder(index: number, item: TabImage, tabBarName: Resource) {

    Column() {
      Image(this.tabsIndex === index ? item.selectedImage : item.unselectedImage)
        .width(24)
        .height(24)
        .margin({ bottom: 10 })
      Text(tabBarName)
        .fontSize(10)

    }
    .width('100%')
    .padding({ top: 0, bottom: 0 })
    .alignItems(HorizontalAlign.Center)
    .id(`tabBar${index}`)
  }

  build() {
    Column() {
      Tabs({ barPosition: BarPosition.End }) {
        TabContent() {
          Column() {
            if (this.tabsIndex === TAB_INDEX.MESSAGE_TAB) {
              NotificationList()
            }
            Blank()
          }
          .height('100%')
        }
        .tabBar(this.TabBarBuilder(TAB_INDEX.MESSAGE_TAB, MESSAGE_TAB, $r('app.string.messages_list_title')))

        TabContent() {
          Column() {
            NoticePublish()
            Blank()
          }
          .height('100%')
        }
        .tabBar(this.TabBarBuilder(TAB_INDEX.NOTIFICATION_TAB, NOTIFICATION_TAB, $r('app.string.notification_publish_title')),)
      }
      .barHeight(74)
      .barWidth('100%')
      .vertical(false)
      .onChange((index: number) => {
        this.tabsIndex = index
      })

    }.width('100%').height('100%')
    .backgroundColor($r('app.color.background_light_gray'))
  }
}

  • 发送通知:通过publishNotification()封装发布通知的接口;

  • 获取应用所有消息通知、取消相关类型通知,角标管理接口封装在NotificationManagementUtil,源码参考:[NotificationManagementUtil.ets]

/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { notificationManager } from '@kit.NotificationKit';
import { logger } from '../util/Logger';

const NOTIFICATION_TYPE_SIZE = 5;

export interface getAllNotificationsResultType {
  groupNotifications: Array<Array<notificationManager.NotificationRequest>>
  countsByType: Array<number>
}

// 通知管理
class NotificationManagementUtil {
  typeNotifications: Array<Array<notificationManager.NotificationRequest>> = new Array(NOTIFICATION_TYPE_SIZE + 1);
  countsByType: Array<number> = new Array(NOTIFICATION_TYPE_SIZE + 1);
  badgeNum: number = 0;

  constructor() {
    this.countsByType.fill(0);
    for (let i = 0; i < NOTIFICATION_TYPE_SIZE + 1; i++) {
      this.typeNotifications[i] = new Array();
    }
    // 获取当前应用所有通知
    notificationManager.getActiveNotifications().then((notifications) => {
      for (let i = 0; i < notifications.length; i++) {
        let typeId = notifications[i].content.notificationContentType;
        this.countsByType[typeId as number] += 1;
        this.typeNotifications[typeId as number].push(notifications[i]);
      }
      logger.info(`getAllActiveNotifications success, data: ${JSON.stringify(notifications)}`)
      // 计算角标数量
      this.countsByType.forEach((num: number) => {
        this.badgeNum += num;
      })
    })
  }

  // 取消属于该类型的通知
  cancelNotificationType(typeId: number) {
    this.typeNotifications[typeId].forEach(item => {
      notificationManager.cancel(item.id);
    })
  }

  // 设置角标
  async setBadgeNumber(num: number) {
    await notificationManager.setBadgeNumber(num).then(() => {
      this.badgeNum = num;
      logger.info("displayBadge success");
    });
  }

  // 获取角标数量
  getBadgeNumber(): number {
    return this.badgeNum;
  }

  // 添加一条消息
  async addNotification(notification: notificationManager.NotificationRequest) {
    const typeId: notificationManager.ContentType = notification.content.notificationContentType as notificationManager.ContentType;
    this.typeNotifications[typeId].push(notification);
    this.countsByType[typeId] += 1;
    this.badgeNum += 1;
    await notificationManagement.setBadgeNumber(this.badgeNum);
    logger.info("add Message success");
  }

  // 获取当前所有消息及数量
  async getAllNotifications() {
    let result: getAllNotificationsResultType = {
      groupNotifications: this.typeNotifications,
      countsByType: this.countsByType
    }
    return result;
  }
}

export let notificationManagement = new NotificationManagementUtil();
  • 获取应用所有消息通知:在constructor()构造函数中调用@ohos.notificationManager中的getActiveNotifications接口获取所有通知及相应类型通知数量,通过封装getAllNotifications()对外提供接口获取当前消息及消息数量。

  • 取消相关类型通知:通过cancelNotificationType()封装取消相关通知类型的接口;

  • 角标管理接口:通过setBadgeNumber()封装设置应用角标数量的接口,通过getBadgeNumber()封装获取当前应用角标数量的接口。

    • 添加一条通知:通过addNotification()封装接口添加一条通知到消息管理器,当发送通知的时候进行调用。
  • NotificationOperations向外提供接口,在页面中调用它们来实现功能,源码参考:[NotificationOperations.ets]

/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { image } from '@kit.ImageKit';
import { notificationManager } from '@kit.NotificationKit';
import { logger, notificationUtil, notificationContentUtil, notificationRequestUtil } from '@ohos/notification';

const TAG: string = 'Sample_Notification';
const MULTI_LINE_CONTENT: Array<string> = ['line0', 'line1', 'line2', 'line3']; // 多行文本通知的多行文本内容

interface NOTIFICATION_GROUP_TYPE {
  BASIC: string
  LONG_TEXT: string
  MULTI_LINE: string
  PICTURE: string
  CONVERSATION: string
}

const NOTIFICATION_GROUP: NOTIFICATION_GROUP_TYPE = { // 定义不同类型通知的通知组
  BASIC: 'BASIC',
  LONG_TEXT: 'LONG_TEXT',
  MULTI_LINE: 'MULTI_LINE',
  PICTURE: 'PICTURE',
  CONVERSATION: 'CONVERSATION'
}

export default class NotificationOperations {
  private context: Context;
  private basicContent: notificationManager.NotificationBasicContent;

  // 在初始化函数初始化基本通知类型的参数
  constructor(context: Context) {
    this.context = context;
    let notificationTitle = '';
    let notificationText = this.context.resourceManager.getStringSync($r('app.string.notification_content'));
    let notificationAdditional = this.context.resourceManager.getStringSync($r('app.string.notification_additional'));
    this.basicContent = {
      title: notificationTitle,
      text: notificationText,
      additionalText: notificationAdditional
    }
  }

  // 发布基本类型通知
  publishBasicNotification = () => {
    try {
      logger.info(TAG, 'publishBasicNotification');
      this.basicContent.title = this.context.resourceManager.getStringSync($r('app.string.basic_notification'));
      let notificationContent = notificationContentUtil.initBasicNotificationContent(this.basicContent);
      notificationUtil.publishNotification(notificationRequestUtil.initBasicNotificationRequest(notificationContent as notificationManager.NotificationContent) as notificationManager.NotificationRequest);
    } catch (error) {
      logger.info(TAG, `publishBasicNotification error, error = ${JSON.stringify(error)}`);
    }
  }
  // 发布长文本类型通知
  publishLongTextNotification = () => {
    try {
      logger.info(TAG, 'publishLongTextNotification');
      this.basicContent.title = this.context.resourceManager.getStringSync($r('app.string.long_text_notification'));
      let notificationLongText = this.context.resourceManager.getStringSync($r('app.string.notification_long_text'));
      let notificationBriefText = this.context.resourceManager.getStringSync($r('app.string.notification_brief_text'));
      let notificationExpandedText = this.context.resourceManager.getStringSync($r('app.string.notification_expanded_title'));
      let notificationContent = notificationContentUtil.initNotificationLongTextContent(this.basicContent, notificationLongText, notificationBriefText, notificationExpandedText);
      notificationUtil.publishNotification(notificationRequestUtil.initBasicNotificationRequest(notificationContent as notificationManager.NotificationContent) as notificationManager.NotificationRequest);
    } catch (error) {
      logger.info(TAG, `publishLongTextNotification error, error = ${JSON.stringify(error)}`);
    }
  }
  // 发布多行文本类型通知
  publishMultiLineNotification = () => {
    try {
      logger.info(TAG, 'publishMultiLineNotification');
      this.basicContent.title = this.context.resourceManager.getStringSync($r('app.string.multiline_notification'));
      let notificationBriefText = this.context.resourceManager.getStringSync($r('app.string.notification_brief_text'));
      let notificationLongTitle = this.context.resourceManager.getStringSync($r('app.string.notification_expanded_title'));
      let notificationContent = notificationContentUtil.initNotificationMultiLineContent(this.basicContent, notificationBriefText, notificationLongTitle, MULTI_LINE_CONTENT);
      notificationUtil.publishNotification(notificationRequestUtil.initBasicNotificationRequest(notificationContent as notificationManager.NotificationContent) as notificationManager.NotificationRequest);
    } catch (error) {
      logger.info(TAG, `publishMultiLineNotification error, error = ${JSON.stringify(error)}`);
    }
  }
  // 发布图片类型通知
  publishPictureNotification = async () => {
    try {
      logger.info(TAG, 'publishPictureNotification');
      this.basicContent.title = this.context.resourceManager.getStringSync($r('app.string.picture_notification'));
      let notificationBriefText = this.context.resourceManager.getStringSync($r('app.string.notification_brief_text'));
      let notificationExpandedText = this.context.resourceManager.getStringSync($r('app.string.notification_expanded_title'));
      let imageArray = await this.context.resourceManager.getMediaContent($r('app.media.notification_icon').id);
      let imageResource = image.createImageSource(imageArray.buffer as ArrayBuffer);
      let picture = await imageResource.createPixelMap();
      let notificationContent = notificationContentUtil.initNotificationPictureContent(this.basicContent, notificationBriefText, notificationExpandedText, picture);
      notificationUtil.publishNotification(notificationRequestUtil.initBasicNotificationRequest(notificationContent as notificationManager.NotificationContent) as notificationManager.NotificationRequest);
    } catch (error) {
      logger.info(TAG, `publishPictureNotification error, error = ${JSON.stringify(error)}`);
    }
  }
  // 发布社交类型的通知
  publishConversationNotification = async () => {
    try {
      logger.info(TAG, 'publishConversationNotification');
      this.basicContent.title = this.context.resourceManager.getStringSync($r('app.string.conversation_notification'));
      let notificationContent = notificationContentUtil.initNotificationConversationContent(this.basicContent);
      notificationUtil.publishNotification(notificationRequestUtil.initBasicNotificationRequest(notificationContent as notificationManager.NotificationContent) as notificationManager.NotificationRequest, NOTIFICATION_GROUP.CONVERSATION);
    } catch (error) {
      logger.info(TAG, `publishNotificationWithWantAgent error, error = ${JSON.stringify(error)}`);
    }
  }
}
  • 发布通知:在[Index.ets]页面中进入发送通知Tab页签,通过点击事件调用NotificationOperations中封装的对应的方法,然后从NotificationContentUtil中获取对应的主体内容content,将 content传递给NotificationRequestUtil得到完整的发布信息,最后调用NotificationUtil.publishNotification()发布内容,并调用NotificationManagementUtil的addNotification()添加一条消息;
/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { NotificationList } from '../components/NotificationList';
import { NoticePublish } from '../components/NotificationPublish';

export interface TabImage {
  selectedImage: Resource,
  unselectedImage: Resource,
}

const MESSAGE_TAB: TabImage = {
  selectedImage: $r('app.media.ic_messages_filled'),
  unselectedImage: $r('app.media.ic_messages'),
}
const NOTIFICATION_TAB: TabImage = {
  selectedImage: $r('app.media.ic_public_send_filled'),
  unselectedImage: $r('app.media.ic_public_send'),
}

interface TAB_INDEX_TYPE {
  MESSAGE_TAB: number
  NOTIFICATION_TAB: number
}

const TAB_INDEX: TAB_INDEX_TYPE = {
  MESSAGE_TAB: 0,
  NOTIFICATION_TAB: 1
}

@Entry
@Component
struct Index {
  @State tabsIndex: number = 0

  @Builder TabBarBuilder(index: number, item: TabImage, tabBarName: Resource) {

    Column() {
      Image(this.tabsIndex === index ? item.selectedImage : item.unselectedImage)
        .width(24)
        .height(24)
        .margin({ bottom: 10 })
      Text(tabBarName)
        .fontSize(10)

    }
    .width('100%')
    .padding({ top: 0, bottom: 0 })
    .alignItems(HorizontalAlign.Center)
    .id(`tabBar${index}`)
  }

  build() {
    Column() {
      Tabs({ barPosition: BarPosition.End }) {
        TabContent() {
          Column() {
            if (this.tabsIndex === TAB_INDEX.MESSAGE_TAB) {
              NotificationList()
            }
            Blank()
          }
          .height('100%')
        }
        .tabBar(this.TabBarBuilder(TAB_INDEX.MESSAGE_TAB, MESSAGE_TAB, $r('app.string.messages_list_title')))

        TabContent() {
          Column() {
            NoticePublish()
            Blank()
          }
          .height('100%')
        }
        .tabBar(this.TabBarBuilder(TAB_INDEX.NOTIFICATION_TAB, NOTIFICATION_TAB, $r('app.string.notification_publish_title')),)
      }
      .barHeight(74)
      .barWidth('100%')
      .vertical(false)
      .onChange((index: number) => {
        this.tabsIndex = index
      })

    }.width('100%').height('100%')
    .backgroundColor($r('app.color.background_light_gray'))
  }
}

以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!
下面是鸿蒙的完整学习路线,展示如下:
1

除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下

内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!

鸿蒙【北向应用开发+南向系统层开发】文档

鸿蒙【基础+实战项目】视频

鸿蒙面经

在这里插入图片描述

为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!

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

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

相关文章

ts-node 报错 ERR_UNKNOWN_FILE_EXTENSION

问题 有个monorepo项目&#xff0c;在最外层一次性打包 3 个项目的脚本已经成功实现&#xff0c;如下&#xff1a; "build:test": "cross-env NODE_ENVtest vite build --mode test && esno ./build/script/postBuild.ts", "build:prod"…

一款基于RBAC模型的开源快速开发平台,支持权限粒度达到列级别,前后端分离,可免费用于商业

前言 在企业级应用开发中&#xff0c;权限管理和系统配置是两个核心问题。传统的开发模式往往面临权限控制不够灵活、系统配置难以管理等挑战。为了解-决这些问题&#xff0c;需要一款能够提供细致权限控制和灵活系统配置的软件。 现有的一些软件虽然提供了基本的权限管理功能…

索尼相机SD卡找不到视频怎么办?提供全面解决方案

在使用索尼相机拍摄美好瞬间时&#xff0c;SD卡作为存储介质&#xff0c;承载着珍贵的视频和照片。然而&#xff0c;有时我们可能会遇到SD卡中视频文件无法找到的问题&#xff0c;这无疑让人倍感焦虑。本文旨在为大家提供一套全面的解决方案&#xff0c;希望帮助大家快速找回丢…

Istio 金丝雀发布

转载&#xff1a;备考ICA-Istio 金丝雀实验4 环境清理 kubectl delete gw/helloworld-gateway vs/helloworld dr/helloworld-destination #测试 kubectl get svc,pods for i in {1..10};do curl $(kubectl get svc helloworld|grep helloworld|awk {print $3":"$5}|a…

谷粒商城实战笔记-138-商城业务-首页-渲染二级三级分类数据

本节的主要内容是在前一节的基础上&#xff0c;提供结构查询出所有的二级、三级分类数据。 一&#xff0c;构造响应体数据结构 后端返回给前端的数据结构是在开发详细设计中应该确定的内容。 分析前端需要的数据结构&#xff0c;后端要将所有一级分类包含的二级和三级分类信…

嵌入式学习之路 14(C语言基础学习——指针)

一、指针基础 指针的概念 地址表示内存单元的编号&#xff0c;也被称为指针。指针既是地址&#xff0c;也是一种专门用于处理地址数据的数据类型。 例如&#xff0c;变量a的地址或者十六进制表示的0x1000都可以视作指针。 指针变量的定义 语法&#xff1a;基类型 * 指针变…

Python面试宝典第28题:合并区间

题目 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为intervals[i] [starti, endi]&#xff0c;且endi大于starti。请合并所有重叠的区间&#xff0c;并返回一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间。 示例 1&#xff1a; 输入&…

Linux 利用 iostat 和 iotop 进行 IO 分析

目录 一、概述二、iostat1、下载2、常用选项3、/proc/diskstats 文件3、一般使用 三、iostop1、下载2、常用选项3、一般使用 一、概述 在Linux 系统上&#xff0c;iostat 和 iotop 这两个 IO 数据工具非常常用。它们都是性能分析领域中不可缺少的工具性软件。 如果 Linux 系统…

关于Redis的集群面试题

问题一&#xff1a;Redis的多数据库机制&#xff0c;了解多少&#xff1f; Redis支持多个数据库&#xff0c;并且每个数据库是隔离的不能共享&#xff0c;单机下的redis可以支持16个数据库&#xff08;db0~db15&#xff09;;若在Redis Cluster集群架构下&#xff0c;则只有一个…

基于STM32F103的FreeRTOS系列(七)·任务创建·列表的使用超详细解析

目录 1. 列表和列表项 1.1 列表和列表项简介 1.1.1 列表 1.1.2 列表项 1.1.3 迷你列表项 1.1.4 列表与列表项关系图 1.2 列表初始化 1.3 列表项的初始化 1.4 列表项的插入函数 1.5 列表项的末尾插入 1.6 列表项的删除 1.7 列表的遍历 1. 列表和列表项…

Open3D 三维重建-Marching Cubes (行进立方体)

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1步骤 2.1.2函数代码 2.2完整代码 三、实现效果 3.1原始点云 3.2重建后点云 Open3D点云算法汇总及实战案例汇总的目录地址&#xff1a; Open3D点云算法与点云深度学习案例汇总&#…

基于Flask框架的豆瓣电影实时数据分析可视化系统【自动爬虫、数据库、Pyecharts】

文章目录 有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主项目介绍数据抓取数据存储可视化前后端交互登陆界面注册界面数据更新后展示每文一语 有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主 项目介绍 本项目基于Py…

JavaEE: 线程安全问题的解决方案(synchronized)

发生原因 要想解决线程安全问题,那么我们首先得知道线程安全问题为什么会发生. 发生原因: 线程在操作系统中是"随机调度,抢占式执行的"[根本原因].多个线程,同时修改同一个变量修改操作不是"原子"的内存可见性问题指令重排序 解决方案 原因1和2,我们很…

基于YOLOv8的茶叶病变检测系统

基于YOLOv8的茶叶病变检测系统 (价格85) 包含 [Algal Leaf Spot, Brown Blight, Gray Blight, Healthy, Helopeltis, Red Leaf Spot] 6个类 翻译&#xff1a; [藻类叶斑病&#xff0c;褐疫病&#xff0c;灰疫病&#xff0c;健康&#xff0c;茶角盲蝽&#xff0c; 红叶斑…

08.SQL注入-下(超详细!!!)

1、Access注入 1.1 判断是否存在注入漏洞 ?id10 and 11 //不报错 ?id10 and 12 //报错1.2 判断字段数 ?id10 order by 1 ... ?id10 order by 7 //不报错 ?id10 order by 8 //报错 说明有7个字段1.3 猜表名 ?id10 and exists(select * from administrator) …

IP协议解析

我最近开了几个专栏&#xff0c;诚信互三&#xff01; > |||《算法专栏》&#xff1a;&#xff1a;刷题教程来自网站《代码随想录》。||| > |||《C专栏》&#xff1a;&#xff1a;记录我学习C的经历&#xff0c;看完你一定会有收获。||| > |||《Linux专栏》&#xff1…

C语言宏定义的使用

文章目录 &#x1f34a;自我介绍&#x1f34a;宏定义&#x1f34a;宏函数&#x1f34a;嵌入式开发常用do...while(0)&#x1f34a;字符串化运算符 ‘ # ’&#x1f34a;不定参数宏 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以&#xff1a;点赞关注评论收藏&#xf…

SQL报错注入之floor

目录 1.简述 2.关键函数说明 1.rand函数 2.floor&#xff08;rand&#xff08;0&#xff09;*2&#xff09;函数 3.group by 函数 4.count&#xff08;*&#xff09;函数 3.报错分析 4.报错流程 4.1寻找注入点 4.2爆数据库名 4.3爆表名 4.4爆字段名 4.5查询数据 1.…

32、Python之面向对象:对象的表示,再论Python是dict包括语法糖

引言 在前面介绍Python容器的时候&#xff0c;我们曾经用过这种夸张的表述&#xff0c;“Python就是包裹在一堆语法糖中的字典”。虽然夸张&#xff0c;其实更多的是为了突出Python中dict的强大之处。今天这篇文章&#xff0c;打算看下Python中类对象、实例对象的表示及内存管理…

甄选范文“论负载均衡技术在Web系统中的应用”软考高级论文系统架构设计师论文

论文真题 负载均衡技术是提升Web系统性能的重要方法。利用负载均衡技术, 可将负载(工作任务) 进行平衡、分摊到多个操作单元上执行, 从而协同完成工作任务, 达到提升Web系统性能的目的。 请围绕“负载均衡技术在Web系统中的应用”论题, 依次从以下三个方面进行论述。 1.…