鸿蒙开发入门day16-拖拽事件和手势事件

(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,还请三连支持一波哇ヾ(@^∇^@)ノ)

目录

拖拽事件

概述

拖拽流程

​手势拖拽

​鼠标拖拽

拖拽背板图

开发步骤

通用拖拽适配

多选拖拽适配

手势事件

gesture(常规手势绑定方法)

priorityGesture(带优先级的手势绑定方法)

parallelGesture(并行手势绑定方法)

单一手势

点击手势(TapGesture)

长按手势(LongPressGesture)

拖动手势(PanGesture)


拖拽事件

概述

拖拽框架提供了一种通过鼠标或手势触屏的方式传递数据,即从一个组件位置拖出数据,并拖入到另一个组件位置上进行响应,拖出一方提供数据,拖入一方接收和处理数据。该操作可以让用户方便地移动、复制或删除指定内容。

  • 拖拽操作:在某个能够响应拖出的组件上长按并滑动触发的拖拽行为,当用户释放时,拖拽操作结束;
  • 拖拽背景(背板):用户所拖动数据的形象化表示,开发者可通过onDragStart的CustomerBuilder或DragItemInfo设置,也可以通过dragPreview通用属性设置;
  • 拖拽内容:拖动的数据,使用UDMF统一API UnifiedData 进行封装;
  • 拖出对象:触发拖拽操作并提供数据的组件;
  • 拖入目标:可接收并处理拖动数据的组件;
  • 拖拽点:鼠标或手指等与屏幕的接触位置,是否进入组件范围的判定是以接触点是否进入范围进行判断。

拖拽流程

​手势拖拽

​对于手势长按触发拖拽的场景,发起拖拽前框架侧会对当前组件是否可拖拽进行校验,针对默认可拖出的组件(Search、TextInput、TextArea、RichEditor、Text、Image、Hyperlink)需要判断是否设置了draggable属性为true(若系统使能分层参数,则draggable默认为true),其他组件需要额外判断是否设置了onDragStart回调函数,在满足上述可拖拽条件下,长按大于等于500ms可触发拖拽,长按800ms开始做预览图的浮起动效。

手势拖拽(手指/手写笔)触发拖拽流程:

​鼠标拖拽

鼠标拖拽属于即拖即走,只要鼠标左键在可拖拽的组件上按下并移动大于1vp就可触发拖拽。

当前支持应用内和跨应用拖拽,提供了多个回调事件供开发者感知拖拽状态并干预系统默认拖拽行为,具体如下:

回调事件说明
onDragStart

支持拖出的组件产生拖出动作时触发。

该回调可以感知拖拽行为的发起,开发者可通过在 onDragStart 方法中设置拖拽所传递的数据以及自定义拖拽背板图。推荐开发者使用pixelmap的方式返回背板图,不推荐使用customBuilder的方式,会有额外的性能开销。

onDragEnter当拖拽活动的拖拽点进入组件范围内时触发,只有该组件监听了onDrop事件时,此回调才会被触发。
onDragMove

拖拽点在组件范围内移动时触发;只有该组件监听了onDrop事件时,此回调才会被触发。

在此过程中可通过DragEvent中的setResult方法影响系统部分场景下的外观

1. 设置DragResult.DROP_ENABLED;

2. 设置DragResult.DROP_DISABLED。

onDragLeave

拖拽点离开组件范围时触发;只有该组件监听了onDrop事件时,此回调才会被触发。

针对以下两种情况默认不会发送onDragLeave事件:

1. 父组件移动到子组件;

2. 目标组件与当前组件布局有重叠;

API version 12开始可通过UIContext中的setDragEventStrictReportingEnabled方法严格触发onDragLeave事件。

onDrop

当用户在组件范围内释放时触发,需在此回调中通过DragEvent中的setResult方法设置拖拽结果,否则在拖出方组件的onDragEnd方法中通过getResult方法只能拿到默认的处理结果DragResult.DRAG_FAILED。

该回调也是开发者干预系统默认拖入处理行为的地方,系统会优先执行开发者的onDrop回调,通过在回调中执行setResult方法来告知系统该如何处理所拖拽的数据;

1. 设置 DragResult.DRAG_SUCCESSFUL,数据完全由开发者自己处理,系统不进行处理;

2. 设置DragResult.DRAG_FAILED,数据不再由系统继续处理;

3. 设置DragResult.DRAG_CANCELED,系统也不需要进行数据处理;

4. 设置DragResult.DROP_ENABLED或DragResult.DROP_DISABLED会被忽略,同设置DragResult.DRAG_FAILED;

onDragEnd当用户释放拖拽时,拖拽活动结束,发起拖出动作的组件会触发该回调。
onPreDrag

绑定此事件的组件,当触发拖拽发起前的不同阶段时,触发回调。

开发者可以使用该方法监听PreDragStatus中的枚举在发起拖拽前的不同阶段准备数据。

1. ACTION_DETECTING_STATUS:拖拽手势启动阶段。(按下50ms时触发);

2. READY_TO_TRIGGER_DRAG_ACTION:拖拽准备完成,可发起拖拽阶段。(按下500ms时触发);

3. PREVIEW_LIFT_STARTED:拖拽浮起动效发起阶段。(按下800ms时触发);

4. PREVIEW_LIFT_FINISHED:拖拽浮起动效结束阶段。(浮起动效完全结束时触发);

5. PREVIEW_LANDING_STARTED:拖拽落回动效发起阶段。(落回动效发起时触发);

6. PREVIEW_LANDING_FINISHED:拖拽落回动效结束阶段。(落回动效结束时触发);

7. ACTION_CANCELED_BEFORE_DRAG:拖拽浮起落位动效中断。(已满足READY_TO_TRIGGER_DRAG_ACTION状态后,未达到动效阶段,手指抬手时触发)。

拖拽背板图

拖拽移动过程中显示的拖拽背板图,并非是组件本身,其是用户拖动数据的表示,开发者可以将其设置为任意可显示的图像。其中onDragStart 回调返回的customBuilder或pixelmap可以设置拖拽移动过程中的背板图,浮起图默认使用组件本身的截图;dragpreview属性设置的customBuilder或pixelmap可以设置浮起和拖拽过程的背板图;如果开发者没有配置背板图,则系统会默认取组件本身的截图作为浮起及拖拽过程中的背板图。

拖拽背板图当前支持设置透明度、圆角、阴影和模糊,具体用法见:拖拽控制

约束:

  • 对于容器组件,如果内部内容通过position,offset等手段使得绘制区域超出了容器组件范围,则系统截图无法截取到范围之外的内容,此种情况下,如果一定要浮起及拖拽背板能够包含范围之外的内容,则可考虑通过扩大容器范围或自定义方式进行;
  • 不管是使用自定义builder或是系统默认截图方式,截图都暂时无法应用scale、rotate等图形变换效果。

开发步骤

通用拖拽适配

如下以Image组件为例,介绍组件拖拽开发的基本步骤,以及开发中需要注意的事项。

组件使能拖拽

设置draggable属性为true,并设置onDragStart回调,回调中可以通过UDMF设置拖拽的数据,并返回自定义拖拽背板图;

import { unifiedDataChannel, uniformTypeDescriptor } from '@kit.ArkData';

Image($r('app.media.app_icon'))
    .width(100)
    .height(100)
    .draggable(true)
    .onDragStart((event) => {
        let data: unifiedDataChannel.Image = new unifiedDataChannel.Image();
        data.imageUri = 'common/pic/img.png';
        let unifiedData = new unifiedDataChannel.UnifiedData(data);
        event.setData(unifiedData);

        let dragItemInfo: DragItemInfo = {
        pixelMap: this.pixmap,
        extraInfo: "this is extraInfo",
        };
        // onDragStart回调函数中返回自定义拖拽背板图
        return dragItemInfo;
    })

手势场景触发拖拽抵赖底层绑定的长按手势,若开发者在被拖拽组件上也绑定长按手势,则会与底层的长按手势发生竞争,导致拖拽失败。可以用并行手势解决解决此类问题,如下:

.parallelGesture(LongPressGesture().onAction(() => {
   promptAction.showToast({ duration: 100, message: 'Long press gesture trigger' });
}))

自定义拖拽背板图

自定义拖拽背板图的pixmap可以通过设置onPreDrag函数在长按50ms时触发的回调中前提准备;

.onPreDrag((status: PreDragStatus) => {
    if (preDragStatus == PreDragStatus.ACTION_DETECTING_STATUS) {
        this.getComponentSnapshot();
    }
})

具体pixmap的生成可以调用componentSnapshot.createFromBuilder函数;

@Builder
pixelMapBuilder() {
    Column() {
      Image($r('app.media.startIcon'))
        .width(120)
        .height(120)
        .backgroundColor(Color.Yellow)
    }
  }
  private getComponentSnapshot(): void {
  componentSnapshot.createFromBuilder(()=>{this.pixelMapBuilder()},
  (error: Error, pixmap: image.PixelMap) => {
      if(error){
        console.log("error: " + JSON.stringify(error))
        return;
      }
      this.pixmap = pixmap;
  })
}

多选拖拽适配

API version 12开始Grid组件和List组件中的GridItem和ListItem组件支持多选拖拽,当前只支持onDragStart的方式。如下以Grid为例,介绍多选拖拽的基本步骤,以及开发中的注意事项。

组件多选拖拽使能

创建GridItem子组件并绑定onDragStart函数。同时设置GridItem组件的状态是可选中的;

Grid() {
  ForEach(this.numbers, (idx: number) => {
    GridItem() {
      Column()
        .backgroundColor(this.colors[idx % 9])
        .width(50)
        .height(50)
        .opacity(1.0)
        .id('grid'+idx)
    }
    .onDragStart(()=>{})
    .selectable(true)
  }, (idx: string) => idx)
}

多选拖拽功能默认为关闭状态,使用多选拖拽需要在dragPreviewOptions接口中的DragInteractionOptions参数中设置isMultiSelectionEnabled为true,表示当前组件是否多选。DragInteractionOptions也有支持组件浮起前默认效果的参数defaultAnimationBeforeLifting,设置该参数为true后组件在浮起前会有一个默认缩小动效。

.dragPreviewOptions({isMultiSelectionEnabled:true,defaultAnimationBeforeLifting:true})

为了保证选中状态,需要设置GridItem子组件selected状态为true。例如,可以通过onClick的调用去设置特定的组件为选中的状态。

.selected(this.isSelectedGrid[idx])
.onClick(()=>{
    this.isSelectedGrid[idx] = !this.isSelectedGrid[idx]
})

多选拖拽性能优化

多选拖拽情况下,多选会有聚拢的动画效果,聚拢效果触发时,会给当前屏幕内显示的选中组件截图,当选中组件过多,会导致很高的性能开销。多选拖拽支持从dragPreview中获取截图来作为聚拢动效的截图,以节省性能。

.dragPreview({
    pixelMap:this.pixmap
})

截图的获取可以在选中组件时通过调用componentSnapshot中的get方法获取。如下通过获取组件对应id的方法进行截图。

@State previewData: DragItemInfo[] = []
@State isSelectedGrid: boolean[] = []
.onClick(()=>{
    this.isSelectedGrid[idx] = !this.isSelectedGrid[idx]
    if (this.isSelectedGrid[idx]) {
        let gridItemName = 'grid' + idx
        componentSnapshot.get(gridItemName, (error: Error, pixmap: image.PixelMap)=>{
            this.pixmap = pixmap
            this.previewData[idx] = {
                pixelMap:this.pixmap
            }
        })
    }
})

数量角标适配

多选拖拽的数量角标当前需要应用使用dragPreviewOptions中的numberBadge参数设置,开发者需要根据当前选中的节点数量来设置数量角标。

@State numberBadge: number = 0;

.onClick(()=>{
    this.isSelectedGrid[idx] = !this.isSelectedGrid[idx]
    if (this.isSelectedGrid[idx]) {
      this.numberBadge++;
    } else {
      this.numberBadge--;
  }
})
// 多选场景右上角数量角标需要应用设置numberBadge参数
.dragPreviewOptions({numberBadge: this.numberBadge})

手势事件

通过给各个组件绑定不同的手势事件,并设计事件的响应方式,当手势识别成功时,ArkUI框架将通过事件回调通知组件手势识别的结果。

gesture(常规手势绑定方法)

.gesture(gesture: GestureType, mask?: GestureMask)

gesture为通用的一种手势绑定方法,可以将手势绑定到对应的组件上。

例如,可以将点击手势TapGesture通过gesture手势将方法绑定到Text组件上。

// xxx.ets
@Entry
@Component
struct Index {
  build() {
    Column() {
      Text('Gesture').fontSize(28)
        // 采用gesture手势绑定方法绑定TapGesture
        .gesture(
          TapGesture()
            .onAction(() => {
              console.info('TapGesture is onAction');
            }))
    }
    .height(200)
    .width(250)
  }
}

priorityGesture(带优先级的手势绑定方法)

.priorityGesture(gesture: GestureType, mask?: GestureMask)

priorityGesture是带优先级的手势绑定方法,可以在组件上绑定优先识别的手势。

在默认情况下,当父组件和子组件使用gesture绑定同类型的手势时,子组件优先识别通过gesture绑定的手势。当父组件使用priorityGesture绑定与子组件同类型的手势时,父组件优先识别通过priorityGesture绑定的手势。

长按手势时,设置触发长按的最短时间小的组件会优先响应,会忽略priorityGesture设置。

例如,当父组件Column和子组件Text同时绑定TapGesture手势时,父组件以带优先级手势priorityGesture的形式进行绑定时,优先响应父组件绑定的TapGesture。

// xxx.ets
@Entry
@Component
struct Index {
  build() {
    Column() {
      Text('Gesture').fontSize(28)
        .gesture(
          TapGesture()
            .onAction(() => {
              console.info('Text TapGesture is onAction');
            }))
    }
    .height(200)
    .width(250)
    // 设置为priorityGesture时,点击文本区域会忽略Text组件的TapGesture手势事件,优先响应父组件Column的TapGesture手势事件
    .priorityGesture(
      TapGesture()
        .onAction(() => {
          console.info('Column TapGesture is onAction');
        }), GestureMask.IgnoreInternal)
  }
}

parallelGesture(并行手势绑定方法)

.parallelGesture(gesture: GestureType, mask?: GestureMask)

parallelGesture是并行的手势绑定方法,可以在父子组件上绑定可以同时响应的相同手势。

在默认情况下,手势事件为非冒泡事件,当父子组件绑定相同的手势时,父子组件绑定的手势事件会发生竞争,最多只有一个组件的手势事件能够获得响应。而当父组件绑定了并行手势parallelGesture时,父子组件相同的手势事件都可以触发,实现类似冒泡效果。

// xxx.ets
@Entry
@Component
struct Index {
  build() {
    Column() {
      Text('Gesture').fontSize(28)
        .gesture(
          TapGesture()
            .onAction(() => {
              console.info('Text TapGesture is onAction');
            }))
    }
    .height(200)
    .width(250)
    // 设置为parallelGesture时,点击文本区域会同时响应父组件Column和子组件Text的TapGesture手势事件
    .parallelGesture(
      TapGesture()
        .onAction(() => {
          console.info('Column TapGesture is onAction');
        }), GestureMask.Normal)
  }
}

单一手势

点击手势(TapGesture)

TapGesture(value?:{count?:number, fingers?:number})

点击手势支持单次点击和多次点击,拥有两个可选参数:

  • count:声明该点击手势识别的连续点击次数。默认值为1,若设置小于1的非法值会被转化为默认值。如果配置多次点击,上一次抬起和下一次按下的超时时间为300毫秒。

  • fingers:用于声明触发点击的手指数量,最小值为1,最大值为10,默认值为1。当配置多指时,若第一根手指按下300毫秒内未有足够的手指数按下则手势识别失败。

    以在Text组件上绑定双击手势(count值为2的点击手势)为例:

// xxx.ets
@Entry
@Component
struct Index {
  @State value: string = "";
  
  build() {
    Column() {
      Text('Click twice').fontSize(28)
        .gesture(
          // 绑定count为2的TapGesture
          TapGesture({ count: 2 })
            .onAction((event: GestureEvent|undefined) => {
            if(event){
              this.value = JSON.stringify(event.fingerList[0]);
            }
            }))
      Text(this.value)
    }
    .height(200)
    .width(250)
    .padding(20)
    .border({ width: 3 })
    .margin(30)
  }
}

长按手势(LongPressGesture)

LongPressGesture(value?:{fingers?:number, repeat?:boolean, duration?:number})

长按手势用于触发长按手势事件,拥有三个可选参数:

  • fingers:用于声明触发长按手势所需要的最少手指数量,最小值为1,最大值为10,默认值为1。

  • repeat:用于声明是否连续触发事件回调,默认值为false。

  • duration:用于声明触发长按所需的最短时间,单位为毫秒,默认值为500。

以在Text组件上绑定可以重复触发的长按手势为例:

// xxx.ets
@Entry
@Component
struct Index {
  @State count: number = 0;

  build() {
    Column() {
      Text('LongPress OnAction:' + this.count).fontSize(28)
        .gesture(
          // 绑定可以重复触发的LongPressGesture
          LongPressGesture({ repeat: true })
           .onAction((event: GestureEvent|undefined) => {
              if(event){
                if (event.repeat) {
                  this.count++;
                }
              }
            })
            .onActionEnd(() => {
              this.count = 0;
            })
        )
    }
    .height(200)
    .width(250)
    .padding(20)
    .border({ width: 3 })
    .margin(30)
  }
}

拖动手势(PanGesture)

PanGesture(value?:{ fingers?:number, direction?:PanDirection, distance?:number})

拖动手势用于触发拖动手势事件,滑动达到最小滑动距离(默认值为5vp)时拖动手势识别成功,拥有三个可选参数:

  • fingers:用于声明触发拖动手势所需要的最少手指数量,最小值为1,最大值为10,默认值为1。

  • direction:用于声明触发拖动的手势方向,此枚举值支持逻辑与(&)和逻辑或(|)运算。默认值为Pandirection.All。

  • distance:用于声明触发拖动的最小拖动识别距离,单位为vp,默认值为5。

以在Text组件上绑定拖动手势为例,可以通过在拖动手势的回调函数中修改组件的布局位置信息来实现组件的拖动

// xxx.ets
@Entry
@Component
struct Index {
  @State offsetX: number = 0;
  @State offsetY: number = 0;
  @State positionX: number = 0;
  @State positionY: number = 0;

  build() {
    Column() {
      Text('PanGesture Offset:\nX: ' + this.offsetX + '\n' + 'Y: ' + this.offsetY)
        .fontSize(28)
        .height(200)
        .width(300)
        .padding(20)
        .border({ width: 3 })
          // 在组件上绑定布局位置信息
        .translate({ x: this.offsetX, y: this.offsetY, z: 0 })
        .gesture(
          // 绑定拖动手势
          PanGesture()
           .onActionStart((event: GestureEvent|undefined) => {
              console.info('Pan start');
            })
              // 当触发拖动手势时,根据回调函数修改组件的布局位置信息
            .onActionUpdate((event: GestureEvent|undefined) => {
              if(event){
                this.offsetX = this.positionX + event.offsetX;
                this.offsetY = this.positionY + event.offsetY;
              }
            })
            .onActionEnd(() => {
              this.positionX = this.offsetX;
              this.positionY = this.offsetY;
            })
        )
    }
    .height(200)
    .width(250)
  }
}

说明

大部分可滑动组件,如List、Grid、Scroll、Tab等组件是通过PanGesture实现滑动,在组件内部的子组件绑定拖动手势(PanGesture)或者滑动手势(SwipeGesture)会导致手势竞争。

当在子组件绑定PanGesture时,在子组件区域进行滑动仅触发子组件的PanGesture。如果需要父组件响应,需要通过修改手势绑定方法或者子组件向父组件传递消息进行实现,或者通过修改父子组件的PanGesture参数distance使得拖动更灵敏。当子组件绑定SwipeGesture时,由于PanGesture和SwipeGesture触发条件不同,需要修改PanGesture和SwipeGesture的参数以达到所需效果。

不合理的阈值设置会导致滑动不跟手(响应时延慢)的问题。

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

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

相关文章

企业架构的概念及发展历程简述(附TOGAF架构理论学习资料下载链接)

企业架构在数字化转型中发挥着至关重要的作用。它不仅确保了战略一致性、提高了运营效率、强化了信息安全,还指导了数字化转型路径、推动了技术与业务的深度融合以及促进了生态系统的连接。因此,在数字化转型过程中,企业应高度重视企业架构的…

《OpenCV计算机视觉》—— 图像边缘检测

文章目录 一、图像边缘检测概述二、常见的图像边缘检测算法(简单介绍)1.sobel算子2.Scharr算子3.Laplacian算子4.Canny算子 三、代码实现 一、图像边缘检测概述 图像边缘检测是一种重要的图像处理技术,用于定位二维或三维图像中对象的边缘。…

计算氨基酸残基之间的键角和二面角

在蛋白质结构中,不同的角度由特定的原子位置决定。常见的原子类型包括氨基酸主链中的 Cα(α 碳)、C(羰基碳)、N(氮原子)和 O(氧原子)。为了更加清晰,下面给出几种常见角度的定义及其对应的原子类型: 使用具体原子的坐标计算键角和二面角 1. 计算 N−Cα−C 的键角…

初次使用住宅代理有哪些常见误区?

随着网络技术的发展,住宅代理因其高匿名性和稳定性成为许多用户进行网络活动的首选工具。然而,对于新手而言,使用住宅代理时往往容易陷入一些误区,这不仅可能影响使用效果,还可能带来安全风险。本文将探讨新手在使用住…

前缀列表(ip-prefix)配置

一. 实验简介 本来前缀列表是要和访问控制列表放在一起讲的,但是这里单拎出来是为了更详细的讲解两者的区别 1.前缀列表针对IP比访问控制更加灵活。 2.前缀列表在后面被引用时是无法对数据包进行过滤的 实验拓扑 二. 实验目的 R4路由器中只引入子网LoopBack的…

oracle数据库安装和配置

​ 大家好,我是程序员小羊! 前言: Oracle 数据库的安装和配置是一个较为复杂的过程,涉及多个步骤和配置项。以下将详细介绍如何在 Linux 和 Windows 系统中安装 Oracle 数据库并进行基础配置。 一、Oracle 数据库安装前的准备 …

提升效率!ArcGIS中创建脚本工具

在我们日常使用的ArcGIS中已经自带了很多功能强大的工具,但有时候遇到个人的特殊情况还是无法满足,这时就可以试着创建自定义脚本工具。 一、编写代码 此处的代码就是一个很简单的给图层更改别名的代码。 1. import arcpy 2. input_fc arcpy.GetParam…

Oracle同义词

默认只能访问自己用户下面的对象,所以可以创建同义词。 同义词(Synonym) 是数据库对象的一个别名,Oracle 可以为表、视图、序列、过程、函数、程序包等指定一个别名 https://blog.csdn.net/ChineseSoftware/article/details/121750937

【springboot】使用缓存

目录 1. 添加依赖 2. 配置缓存 3. 使用EnableCaching注解开启缓存 4. 使用注解 1. 配置缓存名称 2. 配置缓存的键 3. 移除缓存 5. 运行结果 1. 添加依赖 <!-- springboot缓存--><dependency><groupId>org.springframework.boot</groupId>…

ngrok | 内网穿透,支持 HTTPS、国内访问、静态域名

前言 当我们需要把本地开发的应用展示给外部用户时&#xff0c;常常会因为无法直接访问而陷入困境。 就为了展示一下&#xff0c;买服务、域名&#xff0c;搭环境&#xff0c;费钱又费事。 那有没有办法&#xff0c;让客户直接访问自己本机开发的应用呢&#xff1f; 这种需…

分享MSSQL、MySql、Oracle的大数据批量导入方法及编程手法细节

1&#xff1a;MSSQL SQL语法篇&#xff1a; BULK INSERT [ database_name . [ schema_name ] . | schema_name . ] [ table_name | view_name ] FROM data_file [ WITH ( [ [ , ] BATCHSIZE batch_size ] [ [ , ] CHECK_CONSTRAINTS …

基于OMS构建OceanBase容灾双活架构的实践

在实际生产环境中&#xff0c;对于关键业务&#xff0c;往往会有容灾双活的需求。除了OceanBase提供的主备库能力&#xff0c;通过官方工具OMS也可以实现容灾双活架构。目前&#xff0c;通过OMS实现的双活架构仅支持OceanBase数据库之间的数据同步。 要通过OMS实现双活架构&am…

Spring之Bean的生命周期 2024-9-6 19:47

目录 什么是Bean的生命周期为什么要知道Bean的生命周期Bean的生命周期之5步Bean生命周期之7步Bean生命周期之10步 声明&#xff1a;本章博客内容采自老杜2022spring6 语雀文档 什么是Bean的生命周期 Spring其实就是一个管理Bean对象的工厂。它负责对象的创建&#xff0c;对象的…

关于鸿蒙开发中Stage应用模型的相关介绍

应用模型 是系统为开发者提供的应用程序所需能力的抽象提炼&#xff0c;它提供了应用程序必备的组件和运行机制。 简言之&#xff1a;应用模型就是 应用的施工图纸&#xff0c;他规范了&#xff1a;程序运行流程、项目结构、文件功能等…… 了解应用模型之后&#xff0c;就可…

ELK学习笔记(二)——使用K8S部署Kibana8.15.0

上篇文章我们完成了&#xff0c;ES的集群部署&#xff0c;如果还没有看过上篇文章的兄弟&#xff0c;可以去看看。 ELK学习笔记&#xff08;一&#xff09;——使用K8S部署ElasticSearch8.15.0集群 话不多说&#xff0c;接下来直接进入kibana的搭建 一、下载镜像 #1、下载官方…

JS 封装方式

引言&#xff1a;本人是后台服务端开发的&#xff0c;前端的 js 都是在 html 中的 script 标签中写的&#xff0c;处理下数据啥&#xff0c;如果要有需要公共使用的方法啥的都是把方法直接丢在一个 js 文件里&#xff0c;然后 html 引入使用&#xff0c;没有关注过 js 的封装。…

【JavaEE初阶】多线程(2)

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 线程的核心操作 创建线程start 线程的状态 线程的终止 定义一个变量实现 利用标志位实现 加上break/return 结束线程 线程等待 join 无参数版本 两个线程等待 多个线…

如何从 Bak 文件中恢复 SQL数据库?(3种方法)

如何从 .bak 文件恢复 SQL数据库&#xff1f; 在数据库管理和维护过程中&#xff0c;数据的安全性和完整性至关重要。备份文件&#xff08;.bak 文件&#xff09;是 SQL Server 中常用的数据库备份格式&#xff0c;它包含了数据库的完整副本&#xff0c;用于在数据丢失、系统故…

iLogtail 开源两周年:社区使用调查报告

作者&#xff1a;玄飏 iLogtail 作为阿里云开源的可观测数据采集器&#xff0c;以其高效、灵活和可扩展的特性&#xff0c;在可观测采集、处理与分析领域受到了广泛的关注与应用。在 iLogtail 两周年之际&#xff0c;我们对 iLogtail 开源社区进行了一次使用调研&#xff0c;旨…

Java入门:07.Java中的面向对象02

5 对象的使用 对象有两种使用情况 情况一&#xff1a; 对象本身&#xff0c;是一个引用类型的数据 所以他也可以像其他的所有数据一样&#xff0c;进行操作 如&#xff1a;存储&#xff0c;打印等。 int i 10 ; print(10) ; ​ //最终存储在变量中的是对象的地址。 Perso…