浅谈ArkTS/ArkUI组件开发

news2024/11/25 10:24:14

浅谈ArkTS/ArkUI组件开发

本篇文章将从一个移动开发思维的维度出发,浅谈ArkTS组件开发的基础问题,比如状态管理、装饰器、属性传递、自定义构建函数、插槽、条件渲染,模块引用和路由跳转等。


创建项目

这里使用截图简单过一下,不再赘述了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

页面和组件

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';

  build() {
    RelativeContainer() {
      Text(this.message)
        .id('HelloWorld')
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
        .alignRules({
          center: { anchor: '__container__', align: VerticalAlign.Center },
          middle: { anchor: '__container__', align: HorizontalAlign.Center }
        })
    }
    .height('100%')
    .width('100%')
  }
}

看页面入口Index组件,装饰器

  • @Entry装饰器修饰的组件,表示这是个入口组件。且表示是一个独立page页面,通过router进行跳转。
  • @Component使用该装饰器修饰的组件,表示自定义组件,可进行页面渲染。
  • build类似ReactNative中的render方法。生成节点树实例。

另外,鸿蒙ArkUI是一套构建分布式应用界面的声明式UI开发框架,使用声明式的写法。也就是只能使用表达式,与jsx语法对比来看

// 感受下ReactNative中的组件,响应式编程范式(特点:都有一个return,属性样式以插入标签方式实现)
// return 之后是如何写的~
 render() {
        const {errDisMsg, title='账**', backMsg='返回'} = this.state;
         //公共错误
         ...省略...
        return (
            <View style={{ flex: 1 }}>
                <View style={styles.container}>
                    <View>
                        <ICBCWAPHeader {...header} />
                        <View style={{ backgroundColor: '#F5F7F9' }} />
                        {bodytext}
                    </View>
                </View>
            </View>
        );
    }
 }
  // 与上面使用ReactNative组件响应式开发对比,该ArkUI声明式开发如下
  // 方式与响应式相近,无return返回,有属性样式的链式调用
  build() {
    Stack({ alignContent: Alignment.Top }) {
      Image($r('app.media.ic_app_logo'))
        .width(80)
        .height(80)
        .margin({ top: 160 })
        .borderRadius(30)
        .sharedTransition('imgAppLogo', {
          duration: 300,
          curve: Curve.Linear
        })
      Column() {
        Text("剧影新视界")
          .fontSize(SizeConstant.TEXT_XXL)
          .fontColor('#CC333333')
          .fontWeight(FontWeight.Medium)
      }
      .width("100%")
      .height(100)
      .margin(260)
      .padding({ top: SizeConstant.SPACE_XL, bottom: SizeConstant.SPACE_XL })
      .alignItems(HorizontalAlign.Center)
      .justifyContent(FlexAlign.SpaceEvenly)
     ... 省略...
    }.width("100%").height("100%").backgroundColor('#F5F5F5')
  }

可以发现声明式的开发中的一个小特点,组件中不需要renturn

自定义组件

上面组件的开发示例代码中,我们用到 @Entry装饰器。它装饰的组件,则通过路由可跳转进入的页面组件。其实对于自定义组件,不需要@Entry装饰器的修饰使用(@Entry修饰的组件,属于入口组件,可通过router进行跳转),且不是页面组件,不可路由进入。使用开发中的一段代码介绍下

/**
 * @auther y**
 * @description 登陆页面
 * @date 今天
 */
@Entry  // 通过该装饰器装饰,可路由页面组件
@Component
struct LoginPage {
  @StorageLink(THEME_TYPE) themeType: ThemeType = ThemeType.DEFAULT
  @State qrcodeValueBean?: Partial<QrcodeValueBean> = {}
  @State authStep: LoginAuthStep | undefined = undefined

  aboutToAppear() {
    this.authStep = LoginAuthStep.GENERATE_QRCODE_ING
  }

  build() {
    Stack({ alignContent: Alignment.Top }) {
      Image($r('app.media.ic_app_logo'))
	  ... 省略 ...
	  Stack() {
          this.QrcodeBuilder()
        }.layoutWeight(1)
	  ...省略...
      }
    }.width("100%").height("100%").backgroundColor(AppTheme.primary)
  }

  @Builder QrcodeBuilder() {
    ViewStateLayout({ onLoadData: async (viewState) => {
      this.qrcodeValueBean = (await loginViewModel.qrcodeAuth(viewState,
        (authStep: LoginAuthStep) => {
          this.authStep = authStep
        })).data
    } }) {
    // 这里引入自定义组件
      CpnQRCode({ qrcodeValueBean: this.qrcodeValueBean as QrcodeValueBean })
    }
  }
 ... 省略转场动画...
// 省略放在下方~
// 自定义组件

最基本的自定义组件,也就是下面这样写的了

 // 自定义组件,不可路由进入的组件,且非页面组件
@Component   /**自定义组件:第一步 */
struct/**自定义组件:第二步 */ CpnQRCode {
  @ObjectLink qrcodeValueBean: QrcodeValueBean

  build()/**自定义组件:第三步 */ {
   QRCode(this.qrcodeValueBean.qraurl).width(160).height(160)
  }
}

链式调用

链式调用,就是我们常用到的可以一直通过.方法调用执行方法的路子。如安卓火热的RxJava(Rxjava其基于事件流的链式调用、逻辑简洁)。另外,有Flutter开发经验的会发现,与Flutter声明式编码如出一辙。那相对于混合开发技术栈的ReactNative和React、Vue响应式UI编程范式就大不一样啦。但是只要有以上任何一种技术栈的丰富开发经验,ArkUI样式写法就很容易理解和上手。
在这里插入图片描述
而且上面很多样式并不常用,只要有UI样式编码经验,心底成竹在胸的知道,该如何定义和使其展现,开发则不成问题。样式开发中类似上图提示的功能,同样可以通过@Extend和@Styles这俩装饰器来集中实现。@Styles或@Extend目前不支持export导出,后续这两个装饰器不会继续演进

  • @Extend装饰器 定义扩展组件样式。
  • @Styles装饰器 定义组件重用样式,支持通用属性和通用事件。

@Styles装饰器

在这里插入图片描述
@Styles装饰器,用来定义一些公共基础的样式能力。如颜色背景,透明度、内边距、外边距等。可以定义在组件内或全局,在全局定义时需在方法名前面添加function关键字,组件内定义时则不需要添加function关键字。定义在组件内部,该方法被认为是该组件的私有、特殊类型的成员函数,有助于提升组件内聚;定义在外部,可构建作为基础样式库提供支持。

@Extend

@Styles不能携带参数,恰好@Extend补充了这一缺点。(和@Styles不同,@Extend装饰的方法支持参数,开发者可以在调用时传递参数,调用遵循TS方法传值调用。)

和@Styles不同,@Extend仅支持在全局定义,不支持在组件内部定义

在这里插入图片描述

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  build() {
    RelativeContainer() {
      Text(this.message)
        .TextStyle()
        .TextStyleExtend()
    }
    .height('100%')
    .width('100%')
  }
}

@Extend(Text) function TextStyleExtend (fontSize: number = 20, id: string = 'hello-world') {
  .fontSize(fontSize)
  .fontWeight(FontWeight.Bolder)
  .id(id)
  .alignRules({
    center: { anchor: '__container__', align: VerticalAlign.Center },
    middle: { anchor: '__container__', align: HorizontalAlign.Center }
  })
}
@Styles
function TextStyle () {
  .backgroundColor(Color.Blue)
  .border({width: {top:2}, color: Color.Gray})
  .margin({left: '15vp'})
}

属性和状态

声明式UI编程范式中,UI是应用程序状态的函数,应用程序状态的修改会更新相应的UI界面。ArkUI采用了MVVM模式,其中ViewModel将数据与视图绑定在一起,数据更新的时候直接更新视图。如下图所示:
在这里插入图片描述

属性prop,通过外部传入,由父到子的单向数据流传递;使用者(子组件)无法修改。
状态state,组件私有状态,参于组件内部交互处理逻辑。

@State装饰器

上述截图及代码中有用到@State装饰器,修饰一个标量,在该变量被改变时,会触发UI重绘。

使用@State装饰器,表示定义状态与当前组件的一种绑定;即需要用到状态的变化引发组件的重绘渲染。否则,不要使用绑定。

在这里插入图片描述

@Prop装饰器

被@Prop装饰器修饰的成员标量。引用从外部传入,在内部使用。相比ReactNative自定义组件,可认为是自定义组件对外开放的接口。以方便自定义组件接收参数并灵活的设计出可预期的组件样式和功能。
在这里插入图片描述

源码中,同时支持状态和属性的改变
@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  build() {
    RelativeContainer() {
      // 在父级组件中轻松调用,并传入子组件@Prop修饰的属性'text_color'赋值
      // `若`text_color传入值使用@State装饰的message,即ZidingyiComponent({text_color: this.message}) 
      // 且在当前组件(父级)生命周期方法中对该状态message做修改变化,
      // 那么在父组件状态值的变化同时会触发子组件(ZidingyiComponent)属性的变化。达到数据流的单向传递效果。
      ZidingyiComponent({text_color: 'red'}) 
    }
    .height('100%')
    .width('100%')
  }
}

/**自定义子组件,子组件中定义了@State和@Prop*/
@Component
struct ZidingyiComponent {
  @Prop text_color: string = '#FFFFFF'
  @State text_size: number = 18

  aboutToAppear(): void {
    this.text_size = 66 // 自定义组件生命周期中改变状态,触发渲染
  }

  build() {
    Text('自定义组件,prop由外部传入,默认是白色')
      .TextStyleExtend(this.text_size, this.text_color, 'id')
      .TextStyle()
  }
}
@Extend(Text) function TextStyleExtend (fontSize: number = 20, fontColor:string = 'black', id: string = 'hello-world') {
  .fontSize(fontSize)
  .fontColor(fontColor)
  .fontWeight(FontWeight.Bolder)
  .id(id)
  .alignRules({
    center: { anchor: '__container__', align: VerticalAlign.Center },
    middle: { anchor: '__container__', align: HorizontalAlign.Center }
  })
}
@Styles
function TextStyle () {
  .backgroundColor(Color.Blue)
  .border({width: {top:2}, color: Color.Gray})
  .margin({left: '15vp'})
}

属性监听

@Watch属性监听装饰器,可以监听@Prop和@State装饰对象的变化。所监听的装饰对象发生变化,触发@Watch的回调方法。且,一个对象只能被监听一次。

@State @Watch('onMessageChange') message: string = 'Hello World';
onMessageChange() {
  hilog.info(0x88, 'onMessageChange', '@Watch装饰器监听变量message发生变化后,触发该方法执行')
}
// 页面每次显示时触发一次
onPageShow(): void {
  this.message = '修改message,为了触发@Watch'
}

构建函数组件和插槽实现

从官网定义看@Builder称作UI元素复用机制,@Builder所装饰的函数遵循build()函数语法规则,开发者可以将重复使用的UI元素抽象成一个方法,在build方法里调用自定义构建函数,也可作为一种自定义组件使用与看待。

@Builder 和 @BuilderParam

值得注意的是,@BuilderParam装饰的方法只能被自定义构建函数(@Builder装饰的方法)初始化。@BuilderParam可实现插槽
在这里插入图片描述

ArkUI引入了@BuilderParam装饰器,该装饰器用于声明任意UI描述的一个元素,类似slot占位符。

简单的举例,(定义需求)在父级组件中定义了一个@Builder函数构件(一个完整的函数组件,且具备通用性);然后在子组件中定义并初始化了@BuilderParam。父组件在使用子组件的同时,将父级组件中的通用函数组件传递到子组件中使用,以实现类似的slot占位符效果
提示:@BuilderParam出现的同时,必然会有@Builder的出现。反之不同。
在这里插入图片描述

@Entry
@Component
struct Index {
  @Builder BuilderComponent() {
    Button('Builder自定义构建函数')
      .type(ButtonType.Capsule)
      .fontColor('#333333')
      .fontSize('16fp')
  }
  
  build() {
    RelativeContainer() {
      // 父组件中使用自定义子组件,并传入子组件(父组件的函数组件)
      // 传递组件哦
      ZidingyiComponent({BuilderParamsComponent: this.BuilderComponent})
    }
    .height('100%')
    .width('100%')
  }
}

@Component
struct ZidingyiComponent {
  @Builder BuilderComponent() {
    // 空的,初始化@BuilderParam使用
  }
  @BuilderParam BuilderParamsComponent:()=>void = this.BuilderComponent

  build() {
    RelativeContainer() {
      Text('自定义子组件')
    }
    .height('100%')
    .width('100%')
  }
}

装饰器

单向同步

数据流单向同步的方式,在以上已描述带过。即在子孙组件中使用@Prop装饰器修饰定义的变量对象,可以引流父组件数据向子组件单向传递。
在这里插入图片描述

双相同步

数据流的双向同步,即父级组件中嵌入子组件。通过双向数据流装饰器@Link/@StorageLInk/@ObjectLink装饰的变量,任何一方的改变都会触发另外一方的数据变化,从而变化的数据驱动UI重绘。
在这里插入图片描述
上面截图来自实际项目工程,表达的不够明确。下面手写一段代码再次解释下使用装饰器如何实现数据的双向同步。

@Entry
@Component
struct Index {
  @State @Watch('showChangeCallback') isShow: boolean = false;
  showChangeCallback() {
    // 监听`isShow`的变化,并触发该回调方法。
    // 回调方法中,修改全局缓存的`isShow`的值。之后被装饰器@StorageLink、@StorageProp绑定`isShow`的变量对象。
    // 变量对象的值都将响应变化
    AppStorage.setOrCreate<Boolean>('isShow', !this.isShow);
  }

  aboutToAppear(): void {
    // 初始化isShow的全局缓存
    AppStorage.setOrCreate<Boolean>('isShow', this.isShow);
  }
  build() {
    RelativeContainer() {
      ZidingyiComponent()
      Button('改变isShow在AppStorage的缓存').onClick(()=>{this.isShow = true/**命中变化*/})
    }
    .height('100%')
    .width('100%')
  }
}

@Component
struct ZidingyiComponent {
  @StorageLink('isShow') _isShow: boolean = false; // 响应AppStorage中缓存的`isShow`,双向传递
  build() {
    RelativeContainer() {
      if (this._isShow) Text('自定义子组件文本'); else Button('自定义子组件按钮');
      Zidingyi2Component({_isShow_: this._isShow})
    }
    .height('45vp')
    .width('100%')
  }
}

@Component
struct Zidingyi2Component {
  // @Link 装饰器修饰的对象 _isShow_ 可实现双向传递
  // _isShow_的修改(变化)会同时修改到『ZidingyiComponent』中的`_isShow`值,同时修改到AppStorage中缓存的`isShow`。
  // 然后『ZidingyiComponent』中「@StorageLink('isShow') _isShow: boolean」的`_isShow`值同时响应变化。
  @Link _isShow_: boolean;
  build() {
    RelativeContainer() {
      if (this._isShow_) Text('自定义子组件文本2');
      else Button('自定义子组件按钮2').onClick(()=>this._isShow_ = true/**命中修改*/);
    }
    .height('45vp')
    .width('100%')
  }
}

模块引用

如果我要对我的工程开发进行模块化架构解耦处理,如下截图

其中common目录下,创建的module模块,使用的静态共享包;features目录下,创建的module模块,使用的是动态共享包

在这里插入图片描述
此时,在Index.ets主模块入口文件中使用common模块中的资源。那么需要做以下配置操作使用。

  • 引用配置,在主模块的oh-package.json5中配置
{
  "name": "visionofscript",
  "version": "1.0.0",
  "description": "Please describe the basic information.",
  "main": "",
  "author": "",
  "license": "",
  "dependencies": {
    "@ohos/DrawerLayoutLib": "file:../common/DrawerLayoutView",
    "@ohos/CommonAndViewLib": "file:../common/CommonAndViewLib"
  }
}

  • 引用使用,在主模块(其他模块)中的文件中import后,即可正常使用
import { DrawerLayout } from '@ohos/DrawerLayoutLib';

路由跳转

跳转使用系统os自带api,需要引入import router from '@ohos.router';

模块内跳转

entry主模块内部路由的跳转,由欢迎页跳转到应用首页

分解上面路由跳转参数,例如~ 注意:目的页面文件名后,不加后缀名 .ets
router.replaceUrl({url: 「页面地址」})

  • 页面地址 pages/home/HomeIndex
    router.replaceUrl({url: 'pages/home/HomeIndex'})

更值得注意的是:跳转的目的页面,类似安卓的Activity(每创建出一个Activity,都需要在AndroidManifest.xml中配置),需要在 main_pages.json中进行注册。否则,找不到跳转目的页面。

在这里插入图片描述

跨模块跳转

如上面模块引用下截图展示的架构介绍~
跨module的路由跳转的方式: entry主模块页面,点击跳转按钮,跳转至hsp模块指定页面。
router.pushUrl({ url: '@bundle:「包名」/「模块名」/「页面地址」'})

分解上面路由跳转参数,例如~ 注意:目的页面文件名后,不加后缀名 .ets

  • 包名 cn.com.cec.tiomovie
  • 模块名 mine
  • 页面地址 ets/pages/Index

router.pushUrl({url: '@bundle:cn.com.cec.tiomovie/mine/ets/pages/Index'})

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

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

相关文章

数据结构与算法 - 递归

一、递归 1. 概述 定义&#xff1a;在计算机科学中&#xff0c;递归是一种解决计算问题的方法&#xff0c;其中解决方案取决于同一类问题的更小子集。 比如单链表递归遍历的例子&#xff1a; void f(Node node) {if(node null) {return;}println("before:" node…

Java 字符串常量池

目录 一、池化概念 二、字符串常量池 1. 概述 2. String对象的创建过程 1&#xff09;直接使用字符串常量进行赋值 2&#xff09;通过new创建String类对象 3&#xff09;结论 4&#xff09;intern方法 一、池化概念 先看如下的一段代码&#xff1a; String s1 "…

LLM实战系列(1)—强强联合Langchain-Vicuna应用实战

背景 本文主要介绍一下&#xff0c;基于Langchain与Vicuna-13B的外挂OceanBase知识库项目实战以及QA使用&#xff0c;项目地址: github.com/csunny/DB-G… 在开始之前&#xff0c;我们还是先看看效果&#xff5e; 自Meta发布LLaMA大模型以来&#xff0c; 围绕LLaMA微调的模型…

为什么越来越多的IT青年转行网络安全?

目前&#xff0c;我国互联网已经从爆发增长期进入平稳发展阶段&#xff0c;同时每年大量计算机相关专业的毕业生涌入就业市场&#xff0c;导致IT行业逐渐趋于饱和状态&#xff0c;甚至出现裁员现象&#xff0c;去年很多大厂都有裁员&#xff0c;不少程序员再就业成了难题。 面…

大彩触摸屏与单片机通讯

目录&#xff1a; 一、概述 1、触摸屏简介 2、安装软件 1&#xff09;设置VSPD软件 2&#xff09;设置VisualTFT软件 3&#xff09;设置串口软件 二、单片机发送指令给触摸屏 1、发送文本 2、显示与隐藏控件 1&#xff09;通过指令助手生成指令 2&#xff09;隐藏…

IDEA启动springBoot项目,显示构建和正在启动XxxApplication之后无反应

今天拉其他项目组的代码&#xff0c;然后发现IDEA启动不了项目&#xff0c;点击启动一闪而过&#xff0c;啥提示也没有&#xff0c;因为之前有过类似IDEA出错的经验&#xff0c;所以知道怎么排查。 首先打开IDEA日志输出&#xff0c;然后看具体是什么错 帮助>Tail Log in Co…

Linux用户无法访问Github怎么办?

进入Steam官网:Watt Toolkit 1.点击下载 2.在点击授权并下载 3.尽量选择Nas分流&#xff08;德国&#xff09; 4.然后选择最新版本 5.点击Linux版本它会自动文件夹 6.双击,他会自动下载 7.下载完成后进行解压,解压后进入目录 8.右键在此打开终端,在终端输入,运行此脚本 …

揭秘!焦虑症不只是心理战,这些躯体化症状你中招了吗?

引言 在这个快节奏、高压力的时代&#xff0c;焦虑症已成为许多人难以言说的秘密。它不仅悄无声息地侵蚀着我们的心理健康&#xff0c;还可能以一系列令人意想不到的躯体化症状显现&#xff0c;让人误以为自己只是“身体出了点小毛病”。今天&#xff0c;就让我们一起揭开焦虑…

[工具推荐]前端加解密之Burp插件Galaxy

如果觉得该文章有帮助的&#xff0c;麻烦师傅们可以搜索下微信公众号&#xff1a;良月安全。点个关注&#xff0c;感谢师傅们的支持。 免责声明 本号所发布的所有内容&#xff0c;包括但不限于信息、工具、项目以及文章&#xff0c;均旨在提供学习与研究之用。所有工具安全性…

肖扬率团队到北京军区干休所与离退休老干部座谈

在中国人民解放军建军97周年到来之际&#xff0c;为弘扬拥军优属光荣传统&#xff0c;营造尊崇关爱军人的浓厚氛围&#xff0c;世界中医药联合会骨伤科专业委员会副会长肖扬教授率团队遵从上级部门安排于7月31日上午到北京军区干休所看望离退休的老干部和多位老将军的后代&…

【DRF性能优化】

一、背景 项目中有一个查询脚本的接口&#xff0c;查询20条数据需要5min&#xff0c;性能很差,需要优化 二、问题排查 查看代码发现&#xff0c;serializers中&#xff0c;发现了一个奇怪的查询 查询脚本时&#xff0c;关联的脚本版本的一些字段也需要查询出来&#xff0c;…

安卓单机游戏:世界盒子手机游戏,最新版,春秋MOD整合 下载

《世界盒子》&#xff08;WorldBox&#xff09;是一款由Maxim Karpenko制作的沙盒模拟类游戏。这款游戏允许玩家在游戏中扮演上帝的角色&#xff0c;使用神力来创造和改变像素世界。玩家可以利用水、沙子、土壤、森林、人类、种子、动物等元素&#xff0c;以及温度、降雨等环境…

【数据结构】了解哈希表,解决哈希冲突,用Java模拟实现哈希桶

哈希表的概念 哈希表&#xff08;Hash Table&#xff09;是一种高效的数据结构&#xff0c;用于实现快速的数据存储和检索。它通过将数据映射到一个数组的索引位置&#xff0c;从而能够在平均情况下实现O(1)的时间复杂度进行查找、插入和删除操作。 哈希表的基本概念包括以下…

LLM应用-prompt提示:让大模型总结生成PPT

参考&#xff1a; https://mp.weixin.qq.com/s/frKOjf4hb6yec8LzSmvQ7A 思路&#xff1a;通过大模型生成markdown内容&#xff0c;通过markdown去生成PPT 技术&#xff1a;Marp&#xff08;https://marp.app/&#xff09;这里用的这个工具进行markdown转PPT 1、让大模型生成Ma…

川土微电子|高性能模拟芯片供应商

上海川土微电子有限公司&#xff0c;成立于2016年&#xff0c;总部位在上海&#xff0c;并于深圳、北京、杭州设有分支机构&#xff0c;产品涵盖隔离与接口、驱动与电源、高性能模拟三大产品线以及μMiC战略产品&#xff08; micro-Module in Chip&#xff09;。目前产品已广泛…

玩转大模型之五(测试FastGPT高级编排)

一、高级编排 FastGPT 从 V4 版本开始采用新的交互方式来构建 AI 应用。使用了 Flow 节点编排&#xff08;工作流&#xff09;的方式来实现复杂工作流&#xff0c;提高可玩性和扩展性。但同时也提高了上手的门槛&#xff0c;有一定开发背景的用户使用起来会比较容易。 编排方…

局域网内远程控制桌面软件推荐

在现代办公环境中&#xff0c;局域网&#xff08;LAN&#xff09;内的远程桌面连接已成为提升工作效率和促进团队协作的关键技术之一。无论是需要访问办公室内部服务器&#xff0c;还是在家工作时远程操作公司电脑&#xff0c;局域网内的远程桌面都能满足这一需求。本文将探讨在…

互联网家政小程序,为大众带来高效、便捷的服务

随着人口老龄化的严重和社会生活节奏的加快&#xff0c;大众对家政服务的需求日益增加&#xff0c;家政行业的市场规模逐渐扩大&#xff01; 在科技的推动下&#xff0c;家政行业开始向数字化发展&#xff0c;“互联网家政”的模式推动了市场的快速发展。互联网家政小程序借助…

安卓Intent

文章目录 Intent新建一个活动显示Intent隐式Intent同多隐式Intent用法向下一个活动传递数据向上一个活动返回数据 Intent Intent是Android程序中各组件之间进行交互的一种重要方式&#xff0c;它不仅可以指明当前组件想要执行的动作&#xff0c;还可以在不同组件之间传递数据。…

EPM 和 EPM-P 系列功率计

EPM 和 EPM-P 系列功率计 是德(KEYSIGHT)简述 EPM 功率计提供了 CW 和平均功率测量功能。EPM-P 功率计提供了峰值、均值、峰值均值比和时间选通功率测量功能。 EPM系列 功率计表 功能特点 EPM 和 EPM-P 系列提供高性能、可编程的功率计&#xff0c;以执行连续波、平均功率和…