IssueNo: I8KNJB:【高阶开发范例】【性能】状态变量组件定位工具实践

Description:  【高阶开发范例】【性能】状态变量组件定位工具实践
Sig: SIG_applications_app_samples
Feature or Bugfix: Feature
Binary Source: No
Signed-off-by: MoistenT <wangtiansheng2@huawei.com>
This commit is contained in:
MoistenT 2024-01-17 17:21:13 +08:00
parent c3c7f15cb8
commit 774e431ea3
7 changed files with 297 additions and 279 deletions

View File

@ -13,208 +13,189 @@
* limitations under the License.
*/
@Observed
class NeedRenderImage {
const animationDuration: number = 500; // move动画时长
const opacityChangeValue: number = 0.1; // opacity每次变化的值
const opacityChangeRange: number = 1; // opacity变化的范围
const translateYChangeValue: number = 180; // translateY每次变化的值
const translateYChangeRange: number = 250; // translateY变化的范围
const scaleXChangeValue: number = 0.6; // scaleX每次变化的值
const scaleXChangeRange: number = 0.8; // scaleX每次变化的值
const imageWidthChangeValue: number = 30; // imageWidth每次变化的值
const imageWidthChangeRange: number = 160; // imageWidth每次变化的值
const imageHeightChangeValue: number = 30; // imageHeight每次变化的值
const imageHeightChangeRange: number = 160; // imageHeight每次变化的值
// 图片样式类
class ImageStyle {
public translateImageX: number = 0;
public translateImageY: number = 0;
public imageWidth: number = 78;
public imageHeight: number = 78;
}
// 缩放属性类
@Observed
class NeedRenderScale {
class ScaleStyle {
public scaleX: number = 0.3;
public scaleY: number = 0.3;
}
// 位移属性类
@Observed
class NeedRenderAlpha {
public alpha: number = 0.5;
}
@Observed
class NeedRenderSize {
public width: number = 336;
public height: number = 178;
}
@Observed
class NeedRenderPos {
public posX: number = 10;
public posY: number = 50;
}
@Observed
class NeedRenderBorderRadius {
public borderRadius: number = 24;
}
@Observed
class NeedRenderFontSize {
public fontSize: number = 20;
}
@Observed
class NeedRenderTranslate {
class TranslateStyle {
public translateX: number = 0;
public translateY: number = 0;
}
// 样式属性类嵌套ImageStyle, ScaleStyle, TranslateStyle
@Observed
class UIStyle {
needRenderTranslate: NeedRenderTranslate = new NeedRenderTranslate();
needRenderFontSize: NeedRenderFontSize = new NeedRenderFontSize();
needRenderBorderRadius: NeedRenderBorderRadius = new NeedRenderBorderRadius();
needRenderPos: NeedRenderPos = new NeedRenderPos();
needRenderSize: NeedRenderSize = new NeedRenderSize();
needRenderAlpha: NeedRenderAlpha = new NeedRenderAlpha();
needRenderScale: NeedRenderScale = new NeedRenderScale();
needRenderImage: NeedRenderImage = new NeedRenderImage();
translateStyle: TranslateStyle = new TranslateStyle();
scaleStyle: ScaleStyle = new ScaleStyle();
imageStyle: ImageStyle = new ImageStyle();
}
@Component
struct SpecialImage {
@Consume uiStyle: UIStyle;
@Prop needRenderImage: NeedRenderImage
struct SpecialImageA {
@Link specialImageAScaleStyle: ScaleStyle;
private opacityNum: number = 1; // 默认透明度
private isRenderSpecialImage(): number {
console.log("SpecialImage is rendered");
return 1;
// Image每次渲染时透明度增加0.1, 在0-1之间循环
this.opacityNum = (this.opacityNum + opacityChangeValue) % opacityChangeRange;
return this.opacityNum;
}
build() {
Image($r('app.media.icon'))
.width(this.needRenderImage.imageWidth)
.height(this.needRenderImage.imageHeight)
.margin({ top: 20 })
.translate({
x: this.needRenderImage.translateImageX,
y: this.needRenderImage.translateImageY
.width($r('app.integer.special_image_width'))
.height($r('app.integer.special_image_width'))
.margin({ top: $r('app.integer.image_margin_top') })
.scale({
x: this.specialImageAScaleStyle.scaleX,
y: this.specialImageAScaleStyle.scaleY
})
.opacity(this.isRenderSpecialImage())
}
}
@Component
struct CompA {
@Provide uiStyle: UIStyle = new UIStyle();
@ObjectLink needRenderTranslate: NeedRenderTranslate;
@ObjectLink needRenderFontSize: NeedRenderFontSize;
@ObjectLink needRenderBorderRadius: NeedRenderBorderRadius;
@ObjectLink needRenderPos: NeedRenderPos;
@ObjectLink needRenderSize: NeedRenderSize;
@ObjectLink needRenderAlpha: NeedRenderAlpha;
@Prop needRenderScale: NeedRenderScale;
struct SpecialImageB {
@Link specialImageBStyle: ImageStyle;
private opacityNum: number = 1; // 默认透明度
private isRenderColumn(): number {
console.log("Column is rendered");
return 1;
}
private isRenderStack(): number {
console.log("Stack is rendered");
return 1;
}
private isRenderImage(): number {
console.log("Image is rendered");
return 1;
}
private isRenderText(): number {
console.log("Text is rendered");
return 1;
private isRenderSpecialImage(): number {
// Image每次渲染时透明度增加0.1, 在0-1之间循环
this.opacityNum = (this.opacityNum + opacityChangeValue) % opacityChangeRange;
return this.opacityNum;
}
build() {
Column() {
SpecialImage({
needRenderImage: this.uiStyle.needRenderImage
Image($r('app.media.icon'))
.width(this.specialImageBStyle.imageWidth)
.height(this.specialImageBStyle.imageHeight)
.margin({ top: $r('app.integer.image_margin_top') })
.translate({
x: this.specialImageBStyle.translateImageX,
y: this.specialImageBStyle.translateImageY
})
SpecialImage({
needRenderImage: this.uiStyle.needRenderImage
.opacity(this.isRenderSpecialImage())
}
}
@Component
struct ComponentA {
@Prop uiStyle: UIStyle; // 样式属性类,实例属性被多个组件使用
@State scaleStyle: ScaleStyle = this.uiStyle.scaleStyle;
@State translateStyle: TranslateStyle = this.uiStyle.translateStyle;
@State imageStyle: ImageStyle = this.uiStyle.imageStyle;
build() {
Column() {
// 受状态变量影响的组件
SpecialImageA({
specialImageAScaleStyle: this.scaleStyle
})
SpecialImageB({
specialImageBStyle: this.imageStyle
})
Stack() {
Column() {
Image($r('app.media.icon'))
.opacity(this.needRenderAlpha.alpha)
.opacity($r('app.float.icon_opacity'))
.scale({
x: this.needRenderScale.scaleX,
y: this.needRenderScale.scaleY
x: this.scaleStyle.scaleX,
y: this.scaleStyle.scaleY
})
.padding(this.isRenderImage())
.width(300)
.height(300)
.width($r('app.integer.stack_icon_width'))
.height($r('app.integer.stack_icon_height'))
}
.width('100%')
.position({ y: -80 })
.position({ y: $r('app.integer.stack_column_position_y') })
Stack() {
Text("Hello World")
.fontColor($r('app.color.text_color'))
.fontWeight(FontWeight.Medium)
.fontSize(this.needRenderFontSize.fontSize)
.opacity(this.isRenderText())
.margin({ top: 12 })
.fontSize($r('app.integer.button_font_size'))
.margin({ top: $r('app.integer.text_margin_top') })
}
.opacity(this.isRenderStack())
.position({
x: this.needRenderPos.posX,
y: this.needRenderPos.posY
x: $r('app.integer.text_position_x'),
y: $r('app.integer.text_position_y')
})
.width('100%')
.height('100%')
}
.margin({ top: 50 })
.borderRadius(this.needRenderBorderRadius.borderRadius)
.opacity(this.isRenderStack())
.margin({ top: $r('app.integer.stack_margin_top') })
.borderRadius($r('app.integer.stack_border_radius'))
.backgroundColor($r('app.color.stack_color'))
.width(this.needRenderSize.width)
.height(this.needRenderSize.height)
.width($r('app.integer.stack_width'))
.height($r('app.integer.stack_height'))
.translate({
x: this.needRenderTranslate.translateX,
y: this.needRenderTranslate.translateY
x: this.translateStyle.translateX,
y: this.translateStyle.translateY
})
// 通过按钮点击回调修改状态变量的值,引起相应的组件刷新
Column() {
Button("Move")
.width(312)
.fontSize(20)
.width($r('app.integer.button_width'))
.fontSize($r('app.integer.button_font_size'))
.backgroundColor($r('app.color.button_color'))
.margin({ bottom: 10 })
.margin({ bottom: $r('app.integer.button_margin_bottom') })
.onClick(() => {
animateTo({
duration: 500
duration: animationDuration
}, () => {
this.needRenderTranslate.translateY = (this.needRenderTranslate.translateY + 180) % 250;
this.translateStyle.translateY = (this.translateStyle.translateY + translateYChangeValue) % translateYChangeRange;
})
})
Button("Scale")
.borderRadius(20)
.backgroundColor($r('app.color.button_color'))
.fontSize(20)
.width(312)
.margin({ bottom: 10 })
.fontSize($r('app.integer.button_font_size'))
.width($r('app.integer.button_width'))
.margin({ bottom: $r('app.integer.button_margin_bottom') })
.onClick(() => {
this.needRenderScale.scaleX = (this.needRenderScale.scaleX + 0.6) % 0.8;
this.scaleStyle.scaleX = (this.scaleStyle.scaleX + scaleXChangeValue) % scaleXChangeRange;
})
Button("Change Image")
.borderRadius(20)
.backgroundColor($r('app.color.button_color'))
.fontSize(20)
.width(312)
.fontSize($r('app.integer.button_font_size'))
.width($r('app.integer.button_width'))
.onClick(() => {
this.uiStyle.needRenderImage.imageWidth = (this.uiStyle.needRenderImage.imageWidth + 30) % 160;
this.uiStyle.needRenderImage.imageHeight = (this.uiStyle.needRenderImage.imageHeight + 30) % 160;
this.imageStyle.imageWidth =
(this.imageStyle.imageWidth + imageWidthChangeValue) % imageWidthChangeRange;
this.imageStyle.imageHeight =
(this.imageStyle.imageHeight + imageHeightChangeValue) % imageHeightChangeRange;
})
}
.position({
y: 616
y: $r('app.integer.button_column_position_y')
})
.height('100%')
.width('100%')
}
.opacity(this.isRenderColumn())
.width('100%')
.height('100%')
}
@ -226,17 +207,10 @@ export struct DFXStateAfterOptimization {
build() {
Stack() {
CompA({
uiStyle: this.uiStyle,
needRenderTranslate: this.uiStyle.needRenderTranslate,
needRenderFontSize: this.uiStyle.needRenderFontSize,
needRenderBorderRadius: this.uiStyle.needRenderBorderRadius,
needRenderPos: this.uiStyle.needRenderPos,
needRenderSize: this.uiStyle.needRenderSize,
needRenderAlpha: this.uiStyle.needRenderAlpha,
needRenderScale: this.uiStyle.needRenderScale
ComponentA({
uiStyle: this.uiStyle
})
}
.backgroundColor($r('app.color.stack_background'))
}
}
}

View File

@ -13,198 +13,179 @@
* limitations under the License.
*/
class NeedRenderImage {
const animationDuration: number = 500; // move动画时长
const opacityChangeValue: number = 0.1; // opacity每次变化的值
const opacityChangeRange: number = 1; // opacity变化的范围
const translateYChangeValue: number = 180; // translateY每次变化的值
const translateYChangeRange: number = 250; // translateY变化的范围
const scaleXChangeValue: number = 0.6; // scaleX每次变化的值
const scaleXChangeRange: number = 0.8; // scaleX每次变化的值
const imageWidthChangeValue: number = 30; // imageWidth每次变化的值
const imageWidthChangeRange: number = 160; // imageWidth每次变化的值
const imageHeightChangeValue: number = 30; // imageHeight每次变化的值
const imageHeightChangeRange: number = 160; // imageHeight每次变化的值
// 图片样式类
class ImageStyle {
public translateImageX: number = 0;
public translateImageY: number = 0;
public imageWidth: number = 78;
public imageHeight: number = 78;
}
class NeedRenderScale {
// 嵌套ImageStyle类
class ImageStyleContainer {
imageStyle: ImageStyle = new ImageStyle();
}
// 样式属性类
class UIStyle {
imageStyle: ImageStyle = new ImageStyle();
public translateX: number = 0;
public translateY: number = 0;
public scaleX: number = 0.3;
public scaleY: number = 0.3;
}
class NeedRenderAlpha {
public alpha: number = 0.5;
}
class NeedRenderSize {
public width: number = 336;
public height: number = 178;
}
class NeedRenderPos {
public posX: number = 10;
public posY: number = 50;
}
class NeedRenderBorderRadius {
public borderRadius: number = 24;
}
class NeedRenderFontSize {
public fontSize: number = 20;
}
class NeedRenderTranslate {
public translateX: number = 0;
public translateY: number = 0;
}
class UIStyle {
needRenderTranslate: NeedRenderTranslate = new NeedRenderTranslate();
needRenderFontSize: NeedRenderFontSize = new NeedRenderFontSize();
needRenderBorderRadius: NeedRenderBorderRadius = new NeedRenderBorderRadius();
needRenderPos: NeedRenderPos = new NeedRenderPos();
needRenderSize: NeedRenderSize = new NeedRenderSize();
needRenderAlpha: NeedRenderAlpha = new NeedRenderAlpha();
needRenderScale: NeedRenderScale = new NeedRenderScale();
needRenderImage: NeedRenderImage = new NeedRenderImage();
constructor() {
}
}
@Component
struct SpecialImage {
@Link uiStyle: UIStyle;
struct SpecialImageA {
@Link specialImageAUiStyle: UIStyle;
private opacityNum: number = 1; // 默认透明度
private isRenderSpecialImage(): number {
console.log("SpecialImage is rendered");
return 1;
// Image每次渲染时透明度增加0.1, 在0-1之间循环
this.opacityNum = (this.opacityNum + opacityChangeValue) % opacityChangeRange;
return this.opacityNum;
}
build() {
Image($r('app.media.icon'))
.width(this.uiStyle.needRenderImage.imageWidth)
.height(this.uiStyle.needRenderImage.imageHeight)
.margin({ top: 20 })
.translate({
x: this.uiStyle.needRenderImage.translateImageX,
y: this.uiStyle.needRenderImage.translateImageY
.width($r('app.integer.special_image_width'))
.height($r('app.integer.special_image_width'))
.margin({ top: $r('app.integer.image_margin_top') })
.scale({
x: this.specialImageAUiStyle.scaleX,
y: this.specialImageAUiStyle.scaleY
})
.opacity(this.isRenderSpecialImage())
}
}
@Component
struct CompA {
@Prop uiStyle: UIStyle;
@Prop needRenderTranslate: NeedRenderTranslate;
@Prop needRenderFontSize: NeedRenderFontSize;
@Prop needRenderBorderRadius: NeedRenderBorderRadius;
@Prop needRenderPos: NeedRenderPos;
@Prop needRenderSize: NeedRenderSize;
@Prop needRenderAlpha: NeedRenderAlpha;
@Prop needRenderScale: NeedRenderScale;
struct SpecialImageB {
@Link specialImageBStyleContainer: ImageStyleContainer;
private opacityNum: number = 1; // 默认透明度
private isRenderColumn(): number {
console.log("Column is rendered");
return 1;
}
private isRenderStack(): number {
console.log("Stack is rendered");
return 1;
}
private isRenderImage(): number {
console.log("Image is rendered");
return 1;
}
private isRenderText(): number {
console.log("Text is rendered");
return 1;
private isRenderSpecialImage(): number {
// Image每次渲染时透明度增加0.1, 在0-1之间循环
this.opacityNum = (this.opacityNum + opacityChangeValue) % opacityChangeRange;
return this.opacityNum;
}
build() {
Image($r('app.media.icon'))
.width(this.specialImageBStyleContainer.imageStyle.imageWidth)
.height(this.specialImageBStyleContainer.imageStyle.imageHeight)
.margin({ top: $r('app.integer.image_margin_top') })
.translate({
x: this.specialImageBStyleContainer.imageStyle.translateImageX,
y: this.specialImageBStyleContainer.imageStyle.translateImageY
})
.opacity(this.isRenderSpecialImage())
}
}
@Component
struct ComponentA {
@Prop uiStyle: UIStyle; // uiStyle的属性被多个组件使用
@State imageStyleContainer: ImageStyleContainer = new ImageStyleContainer(); // 传递给SpecialImageB中的Image使用
build() {
Column() {
SpecialImage({
uiStyle: this.uiStyle
// 使用状态变量的组件
SpecialImageA({
specialImageAUiStyle: this.uiStyle
})
SpecialImageB({
specialImageBStyleContainer: this.imageStyleContainer
})
Stack() {
Column() {
Image($r('app.media.icon'))
.opacity(this.needRenderAlpha.alpha)
.opacity($r('app.float.icon_opacity'))
.scale({
x: this.needRenderScale.scaleX,
y: this.needRenderScale.scaleY
x: this.uiStyle.scaleX,
y: this.uiStyle.scaleY
})
.padding(this.isRenderImage())
.width(300)
.height(300)
.width($r('app.integer.stack_icon_width'))
.height($r('app.integer.stack_icon_height'))
}
.width('100%')
.position({ y: -80 })
.position({ y: $r('app.integer.stack_column_position_y') })
Stack() {
Text("Hello World")
.fontColor($r('app.color.text_color'))
.fontWeight(FontWeight.Medium)
.fontSize(this.needRenderFontSize.fontSize)
.opacity(this.isRenderText())
.margin({ top: 12 })
.fontSize($r('app.integer.button_font_size'))
.margin({ top: $r('app.integer.text_margin_top') })
}
.opacity(this.isRenderStack())
.position({
x: this.needRenderPos.posX,
y: this.needRenderPos.posY
x: $r('app.integer.text_position_x'),
y: $r('app.integer.text_position_y')
})
.width('100%')
.height('100%')
}
.margin({ top: 50 })
.borderRadius(this.needRenderBorderRadius.borderRadius)
.opacity(this.isRenderStack())
.margin({ top: $r('app.integer.stack_margin_top') })
.borderRadius($r('app.integer.stack_border_radius'))
.backgroundColor($r('app.color.stack_color'))
.width(this.needRenderSize.width)
.height(this.needRenderSize.height)
.width($r('app.integer.stack_width'))
.height($r('app.integer.stack_height'))
.translate({
x: this.needRenderTranslate.translateX,
y: this.needRenderTranslate.translateY
x: this.uiStyle.translateX,
y: this.uiStyle.translateY
})
// 通过按钮点击回调修改状态变量的值,引起相应的组件刷新
Column() {
Button("Move")
.width(312)
.fontSize(20)
Button('Move')
.width($r('app.integer.button_width'))
.fontSize($r('app.integer.button_font_size'))
.backgroundColor($r('app.color.button_color'))
.margin({ bottom: 10 })
.margin({ bottom: $r('app.integer.button_margin_bottom') })
.onClick(() => {
animateTo({
duration: 500
duration: animationDuration
}, () => {
this.needRenderTranslate.translateY = (this.needRenderTranslate.translateY + 180) % 250;
this.uiStyle.translateY = (this.uiStyle.translateY + translateYChangeValue) % translateYChangeRange;
})
})
Button("Scale")
.borderRadius(20)
Button('Scale')
.backgroundColor($r('app.color.button_color'))
.fontSize(20)
.width(312)
.margin({ bottom: 10 })
.fontSize($r('app.integer.button_font_size'))
.width($r('app.integer.button_width'))
.margin({ bottom: $r('app.integer.button_margin_bottom') })
.onClick(() => {
this.needRenderScale.scaleX = (this.needRenderScale.scaleX + 0.6) % 0.8;
this.uiStyle.scaleX = (this.uiStyle.scaleX + scaleXChangeValue) % scaleXChangeRange;
})
Button("Change Image")
.borderRadius(20)
Button('Change Image')
.backgroundColor($r('app.color.button_color'))
.fontSize(20)
.width(312)
.fontSize($r('app.integer.button_font_size'))
.width($r('app.integer.button_width'))
.onClick(() => {
this.uiStyle.needRenderImage.imageWidth = (this.uiStyle.needRenderImage.imageWidth + 30) % 160;
this.uiStyle.needRenderImage.imageHeight = (this.uiStyle.needRenderImage.imageHeight + 30) % 160;
this.imageStyleContainer.imageStyle.imageWidth =
(this.imageStyleContainer.imageStyle.imageWidth + imageWidthChangeValue) % imageWidthChangeRange;
this.imageStyleContainer.imageStyle.imageHeight =
(this.imageStyleContainer.imageStyle.imageHeight + imageHeightChangeValue) % imageHeightChangeRange;
})
}
.position({
y: 616
y: $r('app.integer.button_column_position_y')
})
.height('100%')
.width('100%')
}
.opacity(this.isRenderColumn())
.width('100%')
.height('100%')
}
@ -216,19 +197,10 @@ export struct DFXStateBeforeOptimization {
build() {
Stack() {
CompA({
uiStyle: this.uiStyle,
needRenderTranslate: this.uiStyle.needRenderTranslate,
needRenderFontSize: this.uiStyle.needRenderFontSize,
needRenderBorderRadius: this.uiStyle.needRenderBorderRadius,
needRenderPos: this.uiStyle.needRenderPos,
needRenderSize: this.uiStyle.needRenderSize,
needRenderAlpha: this.uiStyle.needRenderAlpha,
needRenderScale: this.uiStyle.needRenderScale
ComponentA({
uiStyle: this.uiStyle
})
}
.backgroundColor($r('app.color.stack_background'))
}
}
}

View File

@ -0,0 +1,8 @@
{
"float": [
{
"name": "icon_opacity",
"value": "0.5"
}
]
}

View File

@ -0,0 +1,76 @@
{
"integer": [
{
"name": "special_image_width",
"value": 78
},
{
"name": "special_image_height",
"value": 78
},
{
"name": "image_margin_top",
"value": 20
},
{
"name": "stack_icon_width",
"value": 300
},
{
"name": "stack_icon_height",
"value": 300
},
{
"name": "stack_column_position_y",
"value": -80
},
{
"name": "text_position_x",
"value": 10
},
{
"name": "text_position_y",
"value": 50
},
{
"name": "text_margin_top",
"value": 12
},
{
"name": "stack_margin_top",
"value": 50
},
{
"name": "stack_border_radius",
"value": 24
},
{
"name": "stack_width",
"value": 336
},
{
"name": "stack_height",
"value": 178
},
{
"name": "button_width",
"value": 312
},
{
"name": "button_font_size",
"value": 20
},
{
"name": "button_margin_bottom",
"value": 10
},
{
"name": "button_column_position_y",
"value": 616
},
{
"name": "button_move_animation_duration",
"value": 500
}
]
}

View File

@ -1,8 +0,0 @@
{
"string": [
{
"name": "page_show",
"value": "page from npm package"
}
]
}

View File

@ -1,8 +0,0 @@
{
"string": [
{
"name": "page_show",
"value": "page from npm package"
}
]
}

View File

@ -12,6 +12,10 @@
"name": "TestAbility_label",
"value": "test label"
},
{
"name": "permission_while_use",
"value": "仅使用期间允许"
},
{
"name": "MemoryShared",
"value": "MemoryShared"