一、基础知识
1.Image:图片显示组件
声明Image组件并设置图片源:Image(src:string|PixeMap|Resource)
string格式:通常用来加载网络图片,需要申请网络访问权限:ohos.permission.INTERNET。Image('https://xxx.png')
PixeMap格式:可以加载像素图,常用在图片编辑中。Image(pixeMapObject)
Resource格式:加载本地图片。图片存放目录有两个:
1.resources->base->madia:Image($r('app.media.mate60')) --- 常用
2.resources->rawfile:Image($rawfile(mate60.png))
修改图片清晰度属性(枚举类型):interpolation(ImageInterpolation.High)
使用网络图片运行在模拟机上需要在module.json5文件添加下面代码:
"module": {
// 添加以下代码
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
],
}
2.Text 文本显示组件
1.声明Text组件并设置文本内容
1)string格式,直接填写文本内容 :Text('图片宽度')
2)Resource格式,读取本地资源文件:Text($r('app.string.width_label'))
2.添加限定词目录
3.文本属性:字体粗细的参数是枚举类型:fontWeight(FontWeight.Bold)
3.TextInput :文本输入框
type类型:type(InputType:password)
Normal基本输入模式 ,支持数字、字母、下划线、空格、特殊字符。
password密码输入模式,支持数字、字母、下划线、空格、特殊字符。
Email邮箱地址输入模式。支持数字、字母、下划线以及@字符。
Number纯数字输入模式。
PhoneNumber电话号码输入模式。支持输入数字、=、-、*、#长度不限。
4.Button 按钮组件
声明Button组件,label是按钮文字:
1.文字类型按钮:Button('点我')
2.自定义按钮,在Button 内嵌套其他组件:
Button(){ Image($r('app.media.search')).width(20).marrgin(10) }
按钮类型的参数为枚举类型:
type(ButtonType.Normal) 普通按钮;
type(ButtonType.Capsule)胶囊型按钮(默认样式);
type(ButtonType.Circle)圆形按钮。
5.slider 滑动条组件
Slidder({
min:0, //最小值
max:100,//最大值
value:40, //当前值
step:10, //滑动步长
direction::Axis.Horizontal, //滑动条方向,默认水平。垂直是Vertical
style:SliderStyle.OutSet, //滑动圆圈是在里面还是外面,默认在里面。外面是InSet。
reverse:false,//是饭否反向滑动
})
.showTips(true) //是否展示value百分比提示
.blockColor(‘#36D') //圆圈的颜色
6.对齐方式
justifyContent:设置子元素在主轴方向的对齐格式,参数是FlexAlign枚举。
alignItems:设置子元素在交叉轴方向的对齐格式。Row容器使用VerticalAlign枚举,Column容器使用HoriaontalAlign枚举。
7.循环方式
1.forEach:循环遍历数组,根据数组内容渲染页面组件
forEach(
arr:Array,//要遍历的数据数组
(item:ary,index?:number)=>{
//页面组件生成函数
},
keyGenerator?:(item:any,index?:number):string => {
// 键生成函数,为数组每一项生成一个唯一标识,组件是否重新渲染的判断标准
}
)
2.if-else:条件判断,根据数据状态的不同,渲染不同的页面组件。
if(判断条件){内容} else{内容2}
8.List:列表是一种复杂容器,具备下列特点
1.列表项(ListItem)数量过多超出屏幕后,会自动提供滚动功能。
2.列表项既可以纵向排列,也可以横向排列。
// space表示列表项间距
List({space:10}){
ForEach(this.items,(item:Item)=>{
ListItem(){
// 列表项内容,智能包含一个跟组件
Row({space:10}){
Image(item.img)
.width(100)
Column({space:10}){
Text(item.name)
Text('原价:¥'+item.price)
.fontSize(20)
Text('现价:¥'+(item.price-item.count))
.fontColor('red')
}
}
.width('90%')
.listDirection(Axis.Vertical) //列表方向,moren纵向(垂直)
}
})
}
9.自定义组件
1.封装全局公共组件:
//封装全局公共组件
// 页面使用 Header({title:'百亿补贴'})
@Component
export struct Header{
private title:ResourceStr
build(){
Row(){
Image($r('app.media.back'))
.width(30)
Text(this.title)
.fontWeight(FontWeight.Bold)
Blank()
Image($r('app.media.reload'))
.height(30)
}
.width('100%')
.height(30)
.margin({top:15,bottom:15})
}
}
2.封装局部定义组件
class Item{
name:string
img:ResourceStr
price:number
count:number
constructor(name:string,img:ResourceStr,price:number,count:number=0) {
this.name = name
this.img = img
this.price = price
this.count = count
}
}
@Entry
@Component
struct Index {
private items:Array<Item> = [
new Item('华为P30',$r('app.media.img1'),6999,500),
new Item('华为P40',$r('app.media.img2'),13999),
new Item('华为P50',$r('app.media.img3'),12999),
new Item('华为P60',$r('app.media.img4'),11999),
new Item('华为P70',$r('app.media.img5'),9999),
new Item('华为P30',$r('app.media.img1'),6999),
new Item('华为P40',$r('app.media.img2'),13999),
new Item('华为P50',$r('app.media.img3'),12999),
new Item('华为P60',$r('app.media.img4'),11999),
new Item('华为P70',$r('app.media.img5'),9999),
]
build(){
Column(){
Header({title:'百亿补贴1'})
.width('100%')
List({space:8}){
ForEach(this.items,(item:Item)=>{
ListItem(){
this.ItemCard(item)
}
})
}
}
}
// 局部自定义构建函数 -- this.ItemCard(item)
@Builder ItemCard(item:Item){
Row({space:10}){
Image(item.img)
.width(100)
Column({space:4}){
Text(item.name)
.fontSize(20)
.fontWeight(FontWeight.Bold)
if(item.count){
Text('原价:¥'+item.price)
.fontSize(14)
.fontColor('#ccc')
.decoration({type:TextDecorationType.LineThrough})
Text('现价:¥'+(item.price-item.count))
.priceText()
}else {
Text('原价:¥'+item.price)
.fontSize(20)
}
}
.alignItems(HorizontalAlign.Start)
}
.width('95%')
.margin(5)
.backgroundColor('#fff')
.borderRadius(20)
.height(120)
}
}
3.封装公共样式
// 全局自定义公共样式
// 页面使用 .fillScreen()
@Styles function fillScreen(){
.width('100%')
.height('100%')
.backgroundColor('#ddd')
.padding(20)
}
4.封装局部公共样式
// 局部公共样式
// 页面使用 .fillScreen()
@Styles fillScreen(){
.width('100%')
.height('100%')
.backgroundColor('#ddd')
.padding(20)
}
5.封装非全局通用属性
// 全局引入单个属性的样式,继承模式只能用在全局模式
// 使用方法 .priceText()
@Extend(Text) function priceText(){
.fontSize(18)
.fontColor('#36d')
}
10.堆叠容器(Stack):将两个容器的样式堆叠到一起。
Stack(){
Progress({
value:this.finishTask,
total:this.totalTask,
type:ProgressType.Ring
})
Row(){
Text(this.finishTask.toString())
.fontSize(24)
.fontColor('#36D')
Text('/'+this.totalTask.toString())
.fontSize(24)
}
}Stack(){
Progress({
value:this.finishTask,
total:this.totalTask,
type:ProgressType.Ring
})
Row(){
Text(this.finishTask.toString())
.fontSize(24)
.fontColor('#36D')
Text('/'+this.totalTask.toString())
.fontSize(24)
}
}
11.状态管理
1.@State
状态(state):指驱动试图更新的数据(被装饰器标记的变量)
视图(View):基于UI描述渲染得到用户界面
说明:
1.@State装饰器标记的变量必须初始化,不能为空值。
2.@State支持object、class、string、number、Boolean、enum类型以及这些类型的数组。
3.嵌套类型以及数组中的对象属性无法触发试图更新。
class的状态管理:
class Item{ name:string age:number gf:Person //嵌套无法触发更新事件 constructor(name:string,age:number,gf?:Person) { this.name = name this.age= age this.gf = gf } }
@state p:Item = new Person('Jack',21)
@state p:Item = new Person('Jack',21,new Person('Ros',18))
页面使用:${this.p.name}
数组的状态管理:数组可以进行增删操作,但不能对数组中的对象属性操作。
数组定义:gfs:Person[] = [new Person('柔丝',18),new Person('路西',18)]
@State状态案例:
// 任务类
class Tack {
static id:number = 1
// 任务名称
name:string = `任务${Tack.id++}`
finished:boolean = false
}
//统一的卡片样式
@Styles function card(){
.width('95%')
.padding(20)
.backgroundColor(Color.White)
.borderRadius(15)
.shadow({radius:6,color:'#1f0000',offsetX:2,offsetY:4})
}
// @任务完成样式
@Extend(Text) function finishedTask(){
.decoration({type:TextDecorationType.LineThrough})
.fontColor('##B1B2B1')
}
@Entry
@Component
struct PropPage {
@State totalTask :number = 0
@State finishTask :number = 0
@State tasks: Tack[] = []
handleTaskChange(){
this.totalTask = this.tasks.length
this.finishTask = this.tasks.filter(item=>item.finished).length
}
build(){
Column({space:10}){
// 1.任务进度卡片
Row(){
Text('任务进度:')
.fontSize(30)
.fontWeight(FontWeight.Bold)
// 堆叠容器
Stack(){
Progress({
value:this.finishTask,
total:this.totalTask,
type:ProgressType.Ring
})
Row(){
Text(this.finishTask.toString())
.fontSize(24)
.fontColor('#36D')
Text('/'+this.totalTask.toString())
.fontSize(24)
}
}
}
.card()
.margin({top:20,bottom:10})
.justifyContent(FlexAlign.SpaceEvenly)
// 2.新增任务按钮
Button('新增任务')
.width(200)
.onClick(()=>{
this.tasks.push(new Tack())
this.handleTaskChange()
})
// 3.任务列表
List({space:10}){
ForEach(this.tasks,(item:Tack,index)=>{
ListItem(){
Row(){
Text(item.name)
.fontSize(20)
Checkbox()
.select(item.finished)
// @ts-ignore
.finishedTask()
.onChange(val => {
item.finished = val
})
}
.card()
.justifyContent(FlexAlign.SpaceBetween)
}
.swipeAction({end:this.DeleteButton(index)})
})
}
.width('100%')
.layoutWeight(1)
.alignListItem(ListItemAlign.Center)
}
.width('100%')
.height('100%')
.backgroundColor('#f1f2f3')
}
@Builder DeleteButton(index:number){
Button(){
Image($r('app.media.back'))
.fillColor(Color.White)
.width(20)
}
.width(40)
.height(40)
.type(ButtonType.Circle)
.backgroundColor(Color.Red)
.margin(5)
.onClick(()=>{
this.tasks.splice(index,1)
this.handleTaskChange()
})
}
}
2.单向同步 @Prop
数据传输命令:
TaskStatistics({finishTask:this.finishTask,totalTask:this.totalTask})
注意:
1.prop不能赋初始值,只能通过父亲传递过来的值进行渲染。
2.@Prop只支持string、number、boolean、enum类型;父组件对象类型,子组件可以是对象属性;不可以是数组、any。
3.双向数据同步 @Link
数据传输命令:
TaskList({finishTask:$finishTask,totalTask:$totalTask})
注意:
1.Link不能自己赋初始值,只能通过父亲传递过来的值进行渲染。
2.允许装饰的变量类型:
父子类型一致:string、number、boolean、enum、object、class以及他们的数组。
数组中元素增、删、替换会引起刷新。
嵌套类型以及数组中的对象属性无法触发视图更新 。
如果儿子只是获取数据进行渲染,则采用@prop;如果儿子需要对数据进行修改,则采用@Link。
4.跨组件的传递数据:@Provide和Consume可以跨组件提供类似于@State和@Link的双向同步。
5.@ObjectLink和@Observed装饰器用于在涉及嵌套对象或数组元素为对象的场景中进行双向数据绑定。
12.页面路由
页面路由是指在应用程序中实现不同页面之间的跳转和数据传递。
页面栈的最大容量上限为32个页面,使用过router.clear()方法可以清空页面栈,释放内存(不建议使用)。
Router有两种页面跳转模式,分别是:
router.pushUrl():目标不会替换当前页,而是压入页面栈,因此可以用router.back
()返回当前页。
router.replaceUrl():目标页替换当前页,当前页会被销毁并释放资源,无法返回当前页。一般用于登录页面。
Router有两种页面实例模式,分别是:
Standard:标准实例模式,每次跳转都会建立一个目标页并压入栈顶。默认就是这种模式。
Single:单实例模式,如果目标页已经在栈中,则离栈最近的同Url页面会被移动到栈顶并重新加载。这个适用于频繁切换的页面。
使用方法 :
1.导入Router模块 :import router from '@ohos.router'
2.利用router实现跳转、返回等操作。
// 跳转到指定路径并传递参数
router.pushUrl(
{
url:'pages/ImagePage',
params:{id:1}
},
router.RouterMode.Single, //页面模式
err => {
if(err){
//异常响应回调函数错误码:
//100001:内部错误,可能渲染失败
//100002:路由地址错误
//100003:路由栈中页面超过32个
console.log('路由失败')
}
}
)
// 获取传递过来的参数
params:any = router.getParams()
// 返回上一页
router.back()
//返回到指定页,并携带参数
router.back(
{
url:'pages/Index',
params:{id:10}
}
)
13.页面动画
1.属性动画是通过设置组件的animation属性来给组件添加动画,当组件的width、height、Opactity、backgroundColor、scale、rotate、translate等属性变更时,可以实现渐变过渡效果。
Text('😊')
.opsition({
x:10, //x轴
y:0, //y轴
})
.rotate({
angle:0, //旋转角度
centerX:'50%', //旋转中心横坐标
centerY:'50%', //旋转中心纵坐标
})
.animation({
duration:100,
curve:Curve.EaseInOut
})
2.显示动画是通过全局animateTo函数来修改组件属性,实现属性变化时的渐变过渡效果 。
Text('😊')
.opsition({
x:10, //x轴
y:0, //y轴
})
.rotate({
angle:0, //旋转角度
centerX:'50%', //旋转中心横坐标
centerY:'50%', //旋转中心纵坐标
})
// 显示调用animateTo函数触发动画
animateTo(
{ duration:100},
()=>{
//修改组件属性关联的状态变量
}
)
3.组件转场动画时在组件插入或移除时的过渡动画,通过组件的transition属性来配置。
Image(this.src)
.position({x:this.fishX-20,y:this.fishY-20})
.width(40)
.height(40)
.rotate({angle:this.angle,centerX:'50%',centerY:'50%'})
.transition({
type:TransitionType.Insert,
opacity:0,
translate:{x:-250}
})
14.Stage模型应用配置文件
全局配置:AppScope:应用的全局配置信息
15.UIAbility生命周期
16.页面及组件的生命周期
aboutToAppear:用于数据初始化功能,方便bind调用。
页面生命周期:用于页面功能的功能
onPageShow:页面展示
onBackPress:页面返回
onPageHide:页面隐藏
aboutToDisappear:用户数据保存或销毁功能。
16.UIAblility的启动模式
1.Singleton启动模式:每个UIAbility只存在唯一实例。是默认启动模式。任务列表中只会存在一个相同的UIAbility。
2.standard启动模式:(有人也叫multiton,但是这两个是不一样的。旧的实例会移除)
每次启动UIAbility都会创建一个新的实例。在任务列表中可能存在一个或多个相同的UIAbility。(多个实例并存)
3.specified启动模式:每个UIAbility实例可以设置Key标示。启动UIAbility时,需要指定key,存在key相同实例直接被拉起,不存在则创建新实例。
18.网络连接--Http数据请求
1.导入http模块:import http from '@ohos.net.http'
2.使用http模块发送请求,处理响应
// 创建一个http请求对象,不可复用
let httpRequest = http.createHttp()
// 发起网络请求
httpRequest.request(
'http://localhost:3000/users',
{
// 请求选项HttpRequestOpptions
method:http.RequestMethod.GET,
extraData:{'paraml':'value1'}
}
)
//处理相应结果
.then((resp:http.HttpResponse)=>{
if(resp:responseCode === 200){
//请求成功
}
})
.catch((err:Error)=>{
//请求失败
});
HttpRequestOptions:
名称 | 类型 | 描述 |
method | RequestMethod | 请求方式,GET,POST,PUT,DELETE等 |
extraData | string|Object | 请求参数 |
header | Object | 请求头字段 |
connectTimeout | number | 连接超时时间,单位毫秒,默认是60000ms |
readTimeout | number | 读取超时时间,单位毫秒,默认是60000ms |
HttpResponse:
名称 | 类型 | 描述 |
responseCode | ResponseCode | 响应状态码 |
header | Object | 响应头 |
cookies | string | 响应返回cookies |
result | string|Object | 响应体,默认是JSON字符串 |
resultType | HttpDataType | 返回值类型 |
不能打印json数据,需要将json数据转为字符串:JSON.stringify()
把json字符串转为对象JSON.parse()
封装案例:
import http from '@ohos.net.http'
class ShopModel{
baseURL:string = 'http://localhost:3000'
pageNo:number = 1
// @ts-ignore
getShopList():Promise<ShopInfo[]>{
return new Promise((resolve,reject)=>{
// 1.创建http请求对象
let httpRequest = http.createHttp()
// 2.发送请求
httpRequest.request(
'${this.baseURL}/users?pageNo=${this.pageNo}&pageSize=3',
{
// 请求选项HttpRequestOpptions
method:http.RequestMethod.GET,
}
)
.then(resp =>{
if(resp.responseCode === 200){
// 查询成功
console.log('查询成功')
resolve(JSON.parse((resp.result.toString())))
}else {
console.log('查询失败')
reject('查询失败')
}
})
.catch(err =>{
console.log('查询失败')
reject('查询失败')
})
})
}
}
const shopModel = new ShopModel()
export default shopModel as ShopModel;
//页面上获取数据
ShopModel.getShopList().then(shops => {
// 页面请求回来的数据要进行拼接操作才能看到之前查的数据
this.shop = this.shop.connect(shop)
})
触底事件:
// 1.全局定义一个boolean值,用于判断当前是否是加载状态
@State isLoading:boolean = false
// 定义判断数据是否全部加载完成
@State isMore:boolean = false
// 2.添加触底事件
.onReachEnd(()=>{
if(!this.isLoading && this.isMore){
this.isLoading = true
//翻页:在分页查询的时候当前页给了个初始值,现在把初始值进行++就可以加载下一页的数据了
ShopModel.pageNo++
// 调用请求接口的函数 此时当前页2
this.loadShopInfo()
}
})
// 3.在函数完成数据加载后,赋值完成后,修改加载状态
this.isLoading = false
//判断请求回来的数据是否为空
if(!shops || shops.length === 0){
this.isMore = false
}
19.网络连接--第三方库axios
使用第三方库需要先安装ohpm,安装链接:文档中心
安装完成后,先进行初始化,初始化完成之后进行全局的环境变量配置。配置完成后打开cmd,输入ohpm -v验证是否配置成功。
下载axios: 在项目的命令行中输入:ohpm install @ohos/axios
开放网络权限:
{
# 在模块的module.json5 文件中配置网络权限
"module": {
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
],
}
}
使用axios:
先导入axios:import axios from '@ohos/axios'
发送请求并处理响应:
status:number 响应状态码 headers:Object 响应头 data:any 服务端返回的响应体
axios.get(
'url',
{
params:{'param':'value'},//get请求传参
data:{'param':'value'}//post,put,delete传参
}
)
.then(response => {
if(response.status !== 200){
console.log('查询失败')
}
console.log('查询成功')
})
.caatch(error => {
console.log('查询失败')
})
20.数据持久化
1.用户首选项:为应用提供Key-Value键值型的数据处理能力,支持应用持久化轻量级数据。
2.使用方法
(1)导入首选项模块:import dataPreference from '@ohos.data.preferences'
(2)获取首选项实例,读取指定文件
dataPreference.getPreferences(this.context,'MyAppPreferences')
.then(preferences => {
//获取成功
})
.catch(reason => {
//获取失败
})
(3)数据操作
// 1.写入数据,如果已经存在则会覆盖,可利用.has()判断是否存在
preffeences.put('key',val)
.then(()=>preferences.flush()) //刷到磁盘
.catch(reason => {}) //处理异常
// 2.删除数据
preffeences.delete('key')
.then(()=>{})
.catch(reason => {}) //处理异常
// 3.查询数据
preffeences.get('key','defaultValue')
.then((value)=>{console.log('查询成功')})
.catch(reason => {console.log('查询失败')}) //处理异常
说明:
1.key为string类型,要求非空且长度不超过80字节。
2.Value可以是string、number、boolean及以上类型数组,大小不超过8192字节。
3.数据量建议不超过一万条。
3.代码案例:
import preferences from '@ohos.data.preferences'
class PreferenceUtil{
prefMap: Map<string,preferences.Preferences> = new Map()
// 加载
async loadPreference(context,name:string){
try {
let pref = await preferences.getPreferences(context,name)
this.prefMap.set(name,pref)
console.log('testTag',`加载getPreferences【${name}】成功`)
}catch (e){
console.log('testTag',`加载getPreferences【${name}】失败`,JSON.stringify(e))
}
}
// 添加
async putPreferenceValue(name:string,key:string,value:preferences.ValueType){
// 判断name是否存在
if (!this.prefMap.has(name)){
console.log('testTag',`getPreferences【${name}】尚未初始化!`)
return
}
try {
let pref = this.prefMap.get(name)
// 写入数据
await pref.put(key,value)
// 刷盘
await pref.flush()
console.log('testTag',`保存getPreferences【${name}.${key}=${value}】成功`)
}catch (e){
console.log('testTag',`保存getPreferences【${name}.${key}=${value}】失败`,JSON.stringify(e))
}
}
// 获取
async getPreferenceValue(name:string,key:string,defaultValue:preferences.ValueType){
// 判断name是否存在
if (!this.prefMap.has(name)){
console.log('testTag',`getPreferences【${name}】尚未初始化!`)
return
}
try {
let pref = this.prefMap.get(name)
// 读数据
let value = await pref.get(key,defaultValue)
console.log('testTag',`保存getPreferences【${name}.${key}=${value}】成功`)
}catch (e){
console.log('testTag',`保存getPreferences【${name}.${key}】失败`,JSON.stringify(e))
}
}
}
const preferencesUtil = new PreferenceUtil()
export default preferencesUtil as PreferenceUtil
4.页面使用:
import preferencesUtil from '../pages/component/PreferencesUtil'
async onCreate(want, launchParam) {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
// 加载preferences
await preferencesUtil.loadPreference(this.context,'MyPerferences')
}
21.关系型数据库
导入关系型数据库模块:import relationalStore from '@ohos.data.relationalStore'
初始化数据库表:
// 1.rdb 配置
const config = {
name:'MyApplication.db', //数据库文件名
securityLevel:relationalStore.SecurityLevel.S1 //数据库安全级别
}
// 2.初始化表的sql
const sql = `CREATE TABLE IF NOT EXISTS TASK (
ID INTEGER PRIMARY KEY,
NAME TEXT NOT NULL,
FINISHED bit
)`
// 3.获取rdb
relationalStore.getRdbStore(this.context,config,(err,rdbStore)=>{
// 4.执行sql,后续的所有增删改查都是使用rdbStore
rdbStore.executeSql(sql)
})
// 新增数据
let task = {id:1,name:'任务1',finished:false}
this.rdbStore.insert(this.tableName,task)
// 修改数据
let task = {'finished':true};
// 查询条件,RdbPredicates就是条件谓词
let predicates = new relationalStore.RdbPredicates(this.tableName)
predicates.equalTo('ID',id)
// 执行更新
this.rdbStore.update(task,predicates)
// 删除数据
let predicates = new relationalStore.RdbPredicates(this.tableName)
predicates.equalTo('ID',id)
//执行删除
this.rdbStore.delete(predicates)
//查询数据
//1.查询条件
let predicates = new relationalStore.RdbPredicates(this.tableName)
// 2.执行查询
let result = await this.rdbStore.query(predicates,['ID','NAME','FINISHED'])
//3.解析结果
let task:any[] = [] //准备数组保存结果
//循环遍历结果集,判断结果是否遍历到最后一行
while(!result.isAtLastRow){
//指针移动到下一行数据
result.goToNextRow()
//根据字段名获取字段index,从而获取字段值
let id = result.getLong(result.getColumnIndex('ID'));
let name = result.getLong(result.getColumnIndex('NAME'));
tasks.push({id,name})
}
结果集初始位置在-1,这行是没有数据的,要想取到数据,先将指针移到0位置。
实战代码总结:
import relationalStore from '@ohos.data.relationalStore';
class TaskModel{
private rdbStore:relationalStore.RdbStore
private tableName:string = 'TASK'
// 初始化任务表
initTaskDB(){
// rdb 配置
const config = {
name:'MyApplication.db', //数据库文件名
securityLevel:relationalStore.SecurityLevel.S1 //数据库安全级别
}
// 初始化SQL语句
const sql = `CREATE TABLE IF NOT EXISTS TASK (
ID INTEGER PRIMARY KEY,
NAME TEXT NOT NULL,
FINISHED bit
)`
// 获取rdb
// @ts-ignore
relationalStore.getRdbStore(context,config,(err,rdbStore)=>{
if(err){
console.log('textTag','获取rdbstore失败')
return
}
// 执行sql
rdbStore.executeSql(sql)
console.log('textTag','创建task表成功')
// 保存rdbStore
this.rdbStore = rdbStore
})
}
// 查询任务表
async getTaskList(){
// 构建查询条件
let predicates = new relationalStore.RdbPredicates(this.tableName)
// 查询
let result = await this.rdbStore.query(predicates,['ID','NAME','FINISHED'])
// 解析查询结果
// 定义一个数组,组装最终的查询结果
// @ts-ignore
let tasks:TaskInfo[] = []
// 遍历封装
while(!result.isAtLastRow){
//指针移动到下一行数据
result.goToNextRow()
//根据字段名获取字段index,从而获取字段值
let id = result.getLong(result.getColumnIndex('ID'));
let name = result.getLong(result.getColumnIndex('NAME'));
let finished = result.getLong(result.getColumnIndex('FINISHED'));
// 封装给到数组
tasks.push({id,name,finished:!!finished})
}
console.log('testTag','查询到数据:',JSON.stringify(tasks))
return tasks
}
// 添加新的任务 name:任务名称 returns 任务id
addTask(name:string):Promise<number>{
return this.rdbStore.insert(this.tableName,{ name,finished: false });
}
// 更新任务 id 任务id finished 任务是否完成
updateTaskStatus(id:number,finished:boolean){
// 要更新的数据
let data = {finished}
// 更新条件
let predicates = new relationalStore.RdbPredicates(this.tableName)
predicates.equalTo('ID',id)
// 更新操作
return this.rdbStore.update(data,predicates)
}
// 删除id任务
deleteTaskById(id:number){
// 删除条件
let predicates = new relationalStore.RdbPredicates(this.tableName)
predicates.equalTo('ID',id)
// 更新操作
return this.rdbStore.delete(predicates)
}
}
let taskModel = new TaskModel();
export default taskModel as TaskModel;
22.通知
1.普通通知:
应用可以通过通知接口发送通知消息,提醒用户关注应用中的变化。用户可以在通知栏查看和操作通知内容。
使用方法:
1)导入notification模块:import notificationManager from '@ohos.notificationManager '
2)发布通知
// 1.构建通知请求
let request: notificationManager.NotificationRequest = {
id:10,
content:{//通知内容:...}
}
// 2.发布通知
notificationManager.publish(request)
.then(()=>console.log('发送通知成功'))
.catxh(reson => console.log('发送通知失败'))
// 3.取消通知
notificationManager.cancel(10) //取消指定id的通知
notificationManager.cancelAll() //取消当前应用所有通知
//普通文本型
let request: notificationManager.NotificationRequest = {
id:10,
content:{//通知内容:...
contentType:notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
nomal:{
title:'通知标题',
text:'通知内容详情',
additionalText:'通知附加内容'
}
}
}
//长文本型
let request: notificationManager.NotificationRequest = {
id:10,
content:{//通知内容:...
contentType:notificationManager.ContentType.NOTIFICATION_CONTENT_LONG_TEXT,
longText:{
title:'通知标题',
text:'通知内容详情',
additionalText:'通知附加内容',
longText:'通知文本很长很长很长很长很长很长很长很长很长很长很长很长很长很长',
briefText:'通知概要和总结',
expandedTitle:'通知展开时的标题',
}
}
}
//多行文本型
let request: notificationManager.NotificationRequest = {
id:10,
content:{//通知内容:...
contentType:notificationManager.ContentType.NOTIFICATION_CONTENT_MULTILINE,
multline:{
title:'通知标题',
text:'通知内容详情',
additionalText:'通知附加内容',
briefText:'通知概要和总结',
longtitle:'通知文本很长很长很长很长很长很长很长很长很长很长很长很长很长很长',
lines:[
'第一行',
'第一行',
'第一行',
'第一行',
],
}
}
}
//图片型
let request: notificationManager.NotificationRequest = {
id:10,
content:{//通知内容:...
contentType:notificationManager.ContentType.NOTIFICATION_CONTENT_PICTURE,
picture:{
title:'通知标题',
text:'通知内容详情',
additionalText:'通知附加内容',
briefText:'通知概要和总结',
expandedTitle:'展开后标题',
picture:this.pixel
}
},
deliveryTime:new Date().getTime(), //获取时间
showDeliverytime:true,//展示时间
groupName:'wechat', //分组通知栏
slotType:notify。SlotType.SOCIAL_COMMUNICATION,//表示是社交类型的,状态栏图标、提示音、横幅都会有 服务类型只会有状态栏图标、提示音,SERVICE_INFORMATION. 内容类型只有状态栏图标,CONTENT_INFORMATION(默认).OTHER_TYPES什么提示也没有。
}
async aboutToAppear(){
//获取资源管理器
let rm = getContext(this).resouceManager;
// 读取图片
let file = await rm.getMediaContent($r('picture路径'))
// 创建PixelMap
image.createImageSource(file.buffer).createPixelMap()
.then(value => this.pixel = value)
.catch(reson => console.log('teestTag','加载图片异常',JSON.stringify(reason)))
}
2.进度条通知:
进度条通会展示一个动态的进度条,主要用于文件下载/长任务处理的进度显示。
1.判断当前系统是否支持进度条模板
// dowmloadTemplate 这个名字是固定的 必须叫这个
this.isSupport = await notificationManager.isSupportTemplate('dowmloadTemplate')
if(!this.isSupport){ return }
2.定义通知请求
// 通知模板
let template = {
name:'',
data:{
progressValue:this.progressValue, //进度条当前进度
progressMaxValue:100 //进度条最大值
}
}
// 通知请求
let request: notificationManager.NotificationRequest = {
id:10,
template:template,
content:{//通知内容:...
contentType:notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
nomal:{
title:this.filename + ':'+this.state,
text:'',
additionalText:`${this.progressValue}%`
}
}
}
3.发送通知
notificationManager.publish(request)
.then(()=>console.log('发送通知成功'))
.catxh(reson => console.log('发送通知失败')
3.通知意图:我们可以给通知或其中的按钮设置好的行为意图(Want),从而实现拉起应用组件或发布公共事件等能力。
wantAgentInstance : WantAgent
// 创建拉取当前应用的行为意图
// 1,创建wantInfo信息
let wantInfo:wantAgent.WantAgentInfo = {
wants:[
{
deviceId:'',
bundleName:'com.example.myapplication',
abilityName:'EntryAbility',
action:'',
entities:[]
}
],
requestCode:0,
operationType:wantAgent.OperationType.START_ABILITY,
wantAgentFlags:[wantAgent.WantAgentFlags.CONSTANT_FLAG]
}
// 2.创建wantAgent实例
this.wantAgentInstance = await wantAgent.getWantAgent(wantInfo)
// 3.通知请求
let request:notify.NotificationRequest = {
id:'',
template:template,
wantAgent:this.wantAgenttInstance, //设置通知意图
content:{...}
}