技术标签: 华为 Harmony OS 开发指南 harmonyos
移动应⽤开发:
2.1.1 系统的定位
HarmonyOS有三⼤特征:
2.1.2 系统架构
2.2.1 “鸿蒙”
盘古开天辟地——⼀⽚混沌(鸿蒙时代) ⽴志要在⼿机系统的国产化道路上开天辟地
2.2.2 发展史
2.3.1 内核
2.3.2 运⾏效率
安卓:应⽤的运⾏是基于虚拟机的 (Java---JDK编译器---字节码---虚拟机---操作系统)
鸿蒙:⽅⾈编译器 (Java----⽅⾈编译器---机器码---操作系统)
据说, 鸿蒙系统运⾏效率相较于安卓提升了50%+
2.4.1 技术特性
2.4.2 系统安全
3.1.1 开发环境搭建(Java)
下载地址
华为操作系统DevEco Studio和SDK下载与升级 | HarmonyOS开发者
安装
运行DevEco Studio
第一次启动开发环境会下载鸿蒙开发所需要的SDK
3.1.2 注册华为帐号
3.4.1 启动鸿蒙模拟器
3.5.1 config.json
config.json 是鸿蒙应⽤的主配置⽂件
mainAbility声明当前应用启动时默认加载的Ability
deviceType声明当前应用适配的设备类型
abilities 声明当前应⽤中每个ability的配置信息
3.5.2 应⽤启动流程
启动鸿蒙应⽤加载config.json⽂件,根据 mainAbility
配置加载启动应⽤的主界⾯
"mainAbility": "com.example.myapplication.demo01.MainAbility"
执⾏MainAbility的 onStart ⽅法
MainAbility是⼀个显示界⾯的容器,在onStart
⽅法中通过调⽤ setMainRoute ⽅法来指 定当前界⾯容器中显示的视图界⾯
// ability相当于一个容器(或者说是浏览器窗口), // 在容器里面通过填充一个视图slice(html中的body)来展示。 // MainAbilitySlice就是⼀个界⾯ super.setMainRoute(MainAbilitySlice.class.getName());
执⾏MainAbilitySlice中的 onStart
完成界⾯的渲染
slice是⼀个界⾯,界⾯中显示什么视图,就是通过onstart⽅法来加载渲染的
3.5.3 你好,世界哪里来的
$string : 表示引用的一sing,表示要去string文件中寻找键值对,如图寻找key为:mainability_HelloWorld 的值。
Ability是应⽤所具备能⼒的抽象,也是应⽤程序的重要组成部分。⼀个应⽤可以具备多种能⼒
(即可以包含多个Ability),HarmonyOS⽀持应⽤以Ability为单位进⾏部署。
Ability可以分为 FA(Feature Ability)
和PA (Particle Ability)
两种类型,每种类型为
开发者提供了不同的模板,以便实现不同的业务功能。
FA⽀持Page Ability:
Page模板是FA唯⼀⽀持的模板,⽤于提供与⽤户交互的能⼒。⼀个Page实例可以包含⼀
组相关⻚⾯,每个⻚⾯⽤⼀个AbilitySlice实例表示。
PA⽀持Service Ability和Data Ability:
4.2.1PageAbility简介
⼀个PageAbility相当于⼀个⻚⾯的容器(浏览器窗⼝),⼀个AbilitySlice相当于显示在容器
中的⼀个⻚⾯(HTML)
Page模板(以下简称“Page”)是FA唯⼀⽀持的模板,⽤于提供与⽤户交互的能⼒。⼀个Page可以由⼀个或多个AbilitySlice构成,AbilitySlice是指应⽤的单个⻚⾯及其控制逻辑的总和(相当于⼀个HTML⽂件)。在⼀个Abiliy种可以包含多个Slice
商品管理: ProductAbility(PageAbility): goods-list.html ProductListSlice goods-detail.html ProductDetailSlice
4.2.2 创建AbilitySlice
AbilitySlice创建slice包中
创建步骤:
创建⼀个类继承 ohos.aafwk.ability.AbilitySlice 类
public class MainAbilitySlice2 extends AbilitySlice { }
在 resources/base/layout
⽬录下创建布局⽂件
<?xml version="1.0" encoding="utf-8"?> <DirectionalLayout xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:height="match_parent" ohos:width="match_parent" ohos:orientation="vertical"> <Text ohos:height="match_content" ohos:width="match_content" ohos:text="这是测试⽂本" ohos:text_color="#ff0000" ohos:text_size="40vp"></Text> </DirectionalLayout>
在创建的 AbilitySlice 类中重写 onStart ⽅法,调⽤setUIContent⽅法加载布局⽂件
通过 ResourceTable 加载resouces⽬录下的资源
public class MainAbilitySlice2 extends AbilitySlice { @Override protected void onStart(Intent intent) { super.onStart(intent); //定义slice视图组件(Java,XML) //setUIContent(int); 加载应⽤的 布局⽂件(xml) 作为当前slice的视图 setUIContent(ResourceTable.Layout_ability_main_slice2); } }
4.2.3 PageAbility⽣命周期
⼀个Page中可以包含多个Slice,但是只能同时显示⼀个slice,如何设置PageAbility默认
显示的slice?
在⼀个Page Ability中提供了多个声明周期⽅法,这些⽅法在当前PageAbility加载的不同
阶段会⾃定调⽤
说明
INACTIVE状态是一种短暂存在的状态,可理解为“激活中”。
public class MainAbility extends Ability { /** * 当系统⾸次创建当前PageAbility实例时,⾃动调⽤onstart⽅法。也就是说对于⼀个Page⽽⾔,onStart⽅法只会执⾏⼀次 */ public void onStart(Intent intent) { super.onStart(intent); super.setMainRoute(MainAbilitySlice2.class.getName()); System.out.println("--------------onStart"); } /** * 当前Page进⼊active状态进⼊到⼿机前台获取焦点时,会触发onActive⽅法的执⾏ */ protected void onActive() { super.onActive(); System.out.println("--------------onActive"); } /** * 当前PageAbility失去焦点(⻚⾯切⼊到后台、切换到其他Page),触发onInactive⽅法的执⾏ */ protected void onInactive() { super.onInactive(); System.out.println("--------------onInactive"); } /** * 当前PageAbility切换到后台,不可⻅时,触发onBackground执⾏ */ protected void onBackground() { super.onBackground(); System.out.println("--------------onBackground"); } /** * 当PageAbility从后台不可⻅状态(⻚⾯在后台、但是没销毁)切换到前台可⻅状态时触发 onForeground执⾏ */ protected void onForeground(Intent intent) { super.onForeground(intent); System.out.println("--------------onForeground"); } /** * 当前Page销毁时,触发onStop的执⾏ */ protected void onStop() { super.onStop(); System.out.println("--------------onStop"); } }
4.2.4 Slice的两种渲染方式
Slice相当于一个网页,Slice中显示的视图是通过组件来声明的,Slice中的组件加载支持两种方式:
- Java代码
- xml布局文件
onStart
方法:在Slice实例创建时执行,用于载入当前Slice的视图组件,在onStart方法中通过调用setUIContext
来加载视图组件
setUIContext方法提供了2个重载:
setUIContext(int):通过布局⽂件的ID,加载resources/base/layout⽬录下的布局⽂件
完成⻚⾯的渲染
setUIContext(ComponentContainer) :通过加载⼀个使⽤Java代码创建的组件完成⻚⾯
的渲染
XML****⽅式渲染
创建布局⽂件:ability_main_slice2.xml
<?xml version="1.0" encoding="utf-8"?> <DirectionalLayout xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:height="match_parent" ohos:width="match_parent" ohos:orientation="vertical"> <Text ohos:height="match_content" ohos:width="match_content" ohos:text="这是测试文本" ohos:text_color="#ff0000" ohos:text_size="40vp"></Text> </DirectionalLayout>
在Slice的onStart⽅法中加载布局⽂件:
每创建一个布局文件(或者说每个资源都会创建一个ID)都会生成一个ID,所以布局文件调用的是setUIContext(int)方法
@Override protected void onStart(Intent intent) { super.onStart(intent); // 定义slice视图组件(java,xml) // setUIContent(int); 加载应用的 布局文件(xml)作为当前slice的试图 super.setUIContent(ResourceTable.Layout_ability_main_slice2); }
Java⽅式渲染
使⽤Java代码创建组件,渲染到slice中
public class MainAbilitySlice2 extends AbilitySlice { @Override protected void onStart(Intent intent) { super.onStart(intent); // 定义slice视图组件(java,xml) // setUIContent(int); 加载应用的 布局文件(xml)作为当前slice的试图 // super.setUIContent(ResourceTable.Layout_ability_main_slice2); // ComponentContainer(组件容器) DirectionalLayout directionalLayout = new DirectionalLayout(this); directionalLayout.setOrientation(Component.DRAG_VERTICAL); // Component(组件) Text text = new Text(this); text.setText("Hello Boys"); text.setHeight(40); text.setTextSize(40); // 将组件放到组件容器中 directionalLayout.addComponent(text); // 将组件容器渲染到slice中 setUIContent(directionalLayout); } }
4.2.5 AbilitySlice间导航
⼀个PageAbility可以包含多个Slice,同⼀时刻只能显示⼀个Slice,但是可以在不同的
Slice之间进⾏跳转——AbilitySlice间的导航
在MainAbilitySlice中添加按钮,并监听按钮的点击事件(略 参考4.3)
创建SecondAbilitySlice(略)
<?xml version="1.0" encoding="utf-8"?> <DirectionalLayout xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:height="match_parent" ohos:width="match_parent" ohos:orientation="vertical"> <!-- 将图片文件存到resource/base/media目录 PS:文件的名字不要用数字开头,因为名字会作为变量名 --> <Image ohos:height="match_content" ohos:width="match_parent" ohos:image_src="$media:cat"> </Image> </DirectionalLayout>
public class SecondAbilitySlice extends AbilitySlice { @Override protected void onStart(Intent intent) { super.onStart(intent); this.setUIContent(ResourceTable.Layout_ability_second); } }
在MainAbilitySlice中监听按钮的点击事件,导航到SecondAbilitySlice
public class MainAbilitySlice extends AbilitySlice { @Override public void onStart(Intent intent) { super.onStart(intent); // 在当前slice中渲染试图组件有2中方式: // 1. 基于Java代码的渲染 // 2. 基于xml标签渲染,例如: super.setUIContent(ResourceTable.Layout_ability_main); super.setUIContent(ResourceTable.Layout_ability_main); // 1. 获取id=btn1的按钮组件 Button btn1 = (Button) this.findComponentById(ResourceTable.Id_btn1); // 2.设置按钮事件监听 MainAbilitySlice _this = this; // a.创建事件监听器 Component.ClickedListener clickedListener = new Component.ClickedListener() { @Override public void onClick(Component component) { //挑转到SecondAbilitySlice // 从this指代的当前slice跳转到new的slice中 _this.present(new SecondAbilitySlice(), new Intent()); } }; // b.设置组件的事件监听 btn1.setClickedListener(clickedListener); } }
简化版本
public class MainAbilitySlice extends AbilitySlice { @Override public void onStart(Intent intent) { super.onStart(intent); // 在当前slice中渲染试图组件有2中方式: // 1. 基于Java代码的渲染 // 2. 基于xml标签渲染,例如: super.setUIContent(ResourceTable.Layout_ability_main); super.setUIContent(ResourceTable.Layout_ability_main); // 1. 获取id=btn1的按钮组件 Button btn1 = (Button) this.findComponentById(ResourceTable.Id_btn1); // //b.设置组件的事件监听 PS:简化成lambda表达示 // PS:简化成lambda表达式 因为listener要实现onclick方法 // btn1.setClickedListener(clickedListener->{ // present(new SecondAbilitySlice(), new Intent() ); // }); // b.设置组件的事件监听 因为只有一个方法,可以省略大括号 btn1.setClickedListener(clickedListener -> present(new SecondAbilitySlice(), new Intent())); } }
4.2.6 Slice之间的传值问题
使⽤Intent对象实现slice间的传值
MainAbilitySlice
public class MainAbilitySlice extends AbilitySlice { @Override public void onStart(Intent intent) { super.onStart(intent); super.setUIContent(ResourceTable.Layout_ability_main); // 1. 获取id=btn1的按钮组件 Button btn1 = (Button) this.findComponentById(ResourceTable.Id_btn1); // b.设置组件的事件监听 btn1.setClickedListener(clickedListener -> { // 在跳转之前的slice将需要传递的数据设置到Intent对象中 Intent intent1 = new Intent(); intent1.setParam("productId", "101"); present(new SecondAbilitySlice(), intent1); }); } }
SecondAbilitySlice
public class SecondAbilitySlice extends AbilitySlice { @Override protected void onStart(Intent intent) { super.onStart(intent); this.setUIContent(ResourceTable.Layout_ability_second); // 在跳转后的slice的onStart方法中,从intent对象中获取数据 if (intent != null) { // 因为intent.getParam()返回的是IntentParams, 所以先获取IntentParams然后再获取值 IntentParams params = intent.getParams(); String productId = (String) params.getParam("productId"); // 获取到id=text1的文本组件 Text text = (Text) findComponentById(ResourceTable.Id_text1); // 将获取到的商品ID设置到text文本组件 text.setText(productId); } } }
4.3.1 在MainAbilitySlice布局文件添加按钮
<?xml version="1.0" encoding="utf-8"?> <DirectionalLayout xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:height="match_parent" ohos:width="match_parent" ohos:alignment="center" ohos:orientation="vertical"> <Image ohos:height="match_content" ohos:width="match_content" ohos:image_src="$media:icon"> </Image> <Text ohos:id="$+id:text_helloworld" ohos:height="match_content" ohos:width="match_content" ohos:background_element="$graphic:background_ability_main" ohos:layout_alignment="horizontal_center" ohos:text="$string:mainability_HelloWorld" ohos:text_size="40vp"/> <Button ohos:id="$+id:btn1" ohos:height="match_content" ohos:width="match_parent" ohos:padding="5vp" ohos:text="点我试试!" ohos:text_size="40vp" ohos:background_element="#a0b0c0"></Button> </DirectionalLayout>
当我们在Button使用$+id:btn1
时,这个组件就会在ResourceTable中产生一个唯一标识
4.3.2 监听按钮的点击事件
在加载布局文件的Slice类中,获取按钮组件,设置点击事件的监听器
package com.example.myapplicationdemo01.slice; import com.example.myapplicationdemo01.ResourceTable; import ohos.aafwk.ability.AbilitySlice; import ohos.aafwk.content.Intent; import ohos.agp.components.Button; import ohos.agp.components.Component; public class MainAbilitySlice extends AbilitySlice { @Override public void onStart(Intent intent) { super.onStart(intent); // 在当前slice中渲染试图组件有2中方式: // 1. 基于Java代码的渲染 // 2. 基于xml标签渲染,例如: super.setUIContent(ResourceTable.Layout_ability_main); super.setUIContent(ResourceTable.Layout_ability_main); // 1. 获取id=btn1的按钮组件 Button btn = (Button) this.findComponentById(ResourceTable.Id_btn1); // 2.设置按钮事件监听 // a.创建事件监听器 Component.ClickedListener clickedListener = new Component.ClickedListener(){ @Override public void onClick(Component component) { System.out.println("--------触发了点击事件"); } }; // b.设置组件的事件监听 btn.setClickedListener(clickedListener); } }
可以使用同一个监听器监听多个组件的事件,如果点击不同的组件执行的业务不同,则可以通过组件判断来执行不同的业务
// 1. 获取id=btn1的按钮组件 Button btn1 = (Button) this.findComponentById(ResourceTable.Id_btn1); Button btn2 = (Button) this.findComponentById(ResourceTable.Id_btn2); // 2.设置按钮事件监听 // a.创建事件监听器 Component.ClickedListener clickedListener = new Component.ClickedListener(){ @Override public void onClick(Component component) { // Component参数 表示监听的组件 if (component == btn1) { System.out.println("--------aaa"); } else if (component == btn2) { System.out.println("~~~~~~~~bbb"); } } }; // b.设置组件的事件监听 btn1.setClickedListener(clickedListener);// 输出aaa btn2.setClickedListener(clickedListener);// 输出bbb
文章浏览阅读1.3k次。# -*- coding: utf-8 -*-"""@File : 200113_等比例调整图像分辨率大小.py@Time : 2020/1/13 13:38@Author : Dontla@Email : [email protected]@Software: PyCharm"""import cv2def img_resize(image):height, width = image...._opencv小图等比例缩放
文章浏览阅读42次。对于这些调制技术的误码率(BER)研究是非常重要的,因为它们可以帮助我们了解在不同信道条件下系统的性能表现。通过以上步骤,您可以进行OFDM、OOK、PPM和QAM的误码率仿真研究,并绘制它们的误码率曲线,以便更好地了解它们在不同信道条件下的性能特点。针对这些调制技术的BER研究是非常重要的,可以帮助我们更好地了解这些技术在不同信道条件下的性能表现,从而指导系统设计和优化。6. 分析结果:根据误码率曲线的比较,分析每种调制方案在不同信噪比条件下的性能,包括其容忍的信道条件和适用的应用场景。_ber仿真
文章浏览阅读2.5w次,点赞3次,收藏3次。1、场景照抄官方的实例,绑定了 myData.Age 这个值。实际选择某个日期后,从 vuetool(开发工具)看,值已经更新了,但视图未更新。2、尝试绑定另一个值: myData,可以正常的触发 @change 方法。可能是:值绑定到子对象时,组件没有侦测到。3、解决使用 @blur 代替 @change 方法。再判断下 “值有没有更新” 即可。如有更好的方法,欢迎评论!..._el-date-picker @change不触发
文章浏览阅读1.5k次,点赞2次,收藏8次。Projectlnliersclass pcl: : Projectlnliers< PointT >类 Projectlnliers 使用一个模型和一组的内点的索引,将内点投影到模型形成新的一个独立点云。关键成员函数 void setModelType(int model) 通过用户给定的参数设置使用的模型类型 ,参数 Model 为模型类型(见 mo..._projectinliers
文章浏览阅读2.4k次。“System.BadImageFormatException”类型的未经处理的异常在 xxxx.exe 中发生其他信息: 未能加载文件或程序集“xxxxxxx, Version=xxxxxx,xxxxxxx”或它的某一个依赖项。试图加载格式不正确的程序。此原因是由于 ” 目标程序的目标平台与 依赖项的目标编译平台不一致导致,把所有的项目都修改到同一目标平台下(X86、X64或AnyCPU)进行编译,一般即可解决问题“。若果以上方式不能解决,可采用如下方式:右键选择配置管理器,在这里修改平台。_“system.badimageformatexception”类型的未经处理的异常在 未知模块。 中发生
文章浏览阅读2.4k次。记录一下碰到的问题:1.Assetbundle加载问题: 原PC打包后的AssetBundle导入安卓工程后,加载会出问题。同时工程打包APK时,StreamingAssets中不能有中文。解决方案: (1).加入PinYinConvert类,用于将中文转换为拼音(多音字可能会出错,例如空调转换为KongDiao||阿拉伯数字不支持,如Ⅰ、Ⅱ、Ⅲ、Ⅳ(IIII)、Ⅴ、Ⅵ、Ⅶ、Ⅷ、Ⅸ、Ⅹ..._电脑软件移植安卓
文章浏览阅读2.4k次。话不多说参考书籍 汪文君补充知识:start是异步,run是同步,start的执行会经过JNI方法然后被任务执行调度器告知给系统内核分配时间片进行创建线程并执行,而直接调用run不经过本地方法就是普通对象执行实例方法。什么是线程?1.现在几乎百分之百的操作系统都支持多任务的执行,对计算机来说每一个人物就是一个进程(Process),在每一个进程内部至少要有一个线程实在运行中,有时线..._start 是同步还是异步
文章浏览阅读5.3k次,点赞9次,收藏34次。我主要用了层次选择器和属性选择器可以随意选择,方便简单为主大体CSS格式 大家自行构造网页主体<body> <div class='main' > <div class='left'> <img src="images/pic.gif" /> <br/><br/> <img src="images/col.gif" alt="收藏本片"/&_单击标题“非缘勿扰”,元素中有id属性的的文本(主演、导演、标签、剧情
文章浏览阅读2.2k次。完整的解决思路_no module named 'win32com
文章浏览阅读901次,点赞20次,收藏23次。浏览器是每台电脑的必装软件,去浏览器搜索资源和信息已经成为我们的日常,我媳妇儿原本也以为浏览器就是上网冲浪而已,哪有那么强大,但经过我的演示之后她惊呆了,直接给我竖起大拇指道:“原来浏览器还能这么用?大开眼界!今天来给大家介绍几款实用的浏览器插件,学会之后让你的浏览器“活过来”!_浏览器插件助手
文章浏览阅读101次。NumPy是Python中最常用的科学数学计算库之一,它提供了高效的多维数组对象以及对这些数组进行操作的函数NumPy的核心是ndarray(N-dimensional array)对象,它是一个用于存储同类型数据的多维数组Numpy通常与SciPy(Scientific Python)和 Matplotlib(绘图库)一起使用,用于替代MatLabSciPy是一个开源的Python算法库和数学工具包;Matplotlib是Python语言及其Numpy的可视化操作界面'''_数学中常用的环境有numpy
文章浏览阅读1.1w次。docker in docker说白了,就是在docker容器内启动一个docker daemon,对外提供服务。优点在于:镜像和容器都在一个隔离的环境,保持操作者的干净环境。想到了再补充 :)一:低版本启动及访问启动1.12.6-dinddocker run --privileged -d --name mydocker docker:1.12.6-dind在其他容器访问d..._dind