diff --git a/AvoidTimeComsume/AppScope/app.json5 b/AvoidTimeComsume/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5470c22e225cb61e721cda383f7074711b2b0911 --- /dev/null +++ b/AvoidTimeComsume/AppScope/app.json5 @@ -0,0 +1,10 @@ +{ + "app": { + "bundleName": "com.example.myapplication", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/AvoidTimeComsume/AppScope/resources/base/element/string.json b/AvoidTimeComsume/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..1080233f01384411ec684b58955cb8808746fdd3 --- /dev/null +++ b/AvoidTimeComsume/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "MyApplication" + } + ] +} diff --git a/AvoidTimeComsume/AppScope/resources/base/media/app_icon.png b/AvoidTimeComsume/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/AvoidTimeComsume/AppScope/resources/base/media/app_icon.png differ diff --git a/AvoidTimeComsume/REDAME.md b/AvoidTimeComsume/REDAME.md new file mode 100644 index 0000000000000000000000000000000000000000..454a1672429571f10324a4df9a851b7ee1a8f5de --- /dev/null +++ b/AvoidTimeComsume/REDAME.md @@ -0,0 +1,63 @@ +# **主线程耗时操作优化指导** +## 介绍 +在应用开发实践中,有效避免主线程执行冗余与易耗时操作是至关重要的策略。此举能有效降低主线程负载,提升UI的响应速度。面对高频回调接口在短时间内密集触发的场景,需要避免接口内的耗时操作,尽量保证主线程不被长时间占用,从而防止阻塞UI渲染,引发界面卡顿或掉帧现象。 +本实例结束开发过程中常见的冗余操作,常见的高频回调场景以及其他主线程优化思路。 + +## 预览效果 +![](screenshots/output-15_53_54.gif) +## 工程目录 +``` +├──entry/src/main/ets // 代码区 +│ ├──common +│ │ └──Item.ets // 公共区 +│ ├──entryability +│ │ └──EntryAbility.ets // 程序入口类 +│ ├──entrybackupability +│ │ └──EntryBackupAbility.ets +│ ├──pages +│ │ └──Index.ets // 首页 +│ └──views.ets +│ ├──ConditionalRendering.ets // 条件渲染页 +│ ├──GetStrOfId.ets // ID资源获取页 +│ ├──GetStrOfResource.ets // 资源获取页 +│ ├──NegativeOfGrid.ets // 组件复用反例 +│ ├──NegativeOfLazyForEach.ets // 循环渲染反例 +│ ├──NegativeOfOnScroll.ets // 高频事件回调执行耗时操作页 +│ ├──NegativeOfProperty.ets // 组件属性反例页 +│ ├──NoRedundantOperation.ets // 不含有冗余操作页 +│ ├──PositiveOfGrid.ets // 组件复用正例页 +│ ├──PositiveOfLazyForEach.ets // 循环渲染正例页 +│ ├──PositiveOfOnScroll.ets // 高频事件回调不执行耗时操作页 +│ ├──PositiveOfProperty.ets // 组件属性正例页 +│ ├──RedundantOperation.ets // 含有冗余操作页 +│ ├──UseAsync.ets // 使用异步页 +│ ├──UseTaskPool.ets // 使用多线程页 +│ └──WaterFlowDataSource.ets // 瀑布流懒加载数据源页 +└──entry/src/main/resources // 应用资源目录 +``` +## 使用说明 +“避免冗余操作”的正例和反例,反例中包含release版本中冗余日志打印、Trace打点以及无业务代码的空回调,降低了性能。 + +“高频回调场景中避免执行耗时操作”的正例和反例,以下常见高频回调场景中需要避免执行耗时操作: +* 高频事件回调 +* 组件复用回调 +* 组件生命周期回调 +* 循环渲染 +* 组件属性 + +反例中在高频事件中执行了上述耗时操作,降低了性能。 + +“避免使用耗时接口”的正例和反例,反例中使用了没有指定资源id的接口,导致耗时增加,从而影响了性能。 + +“使用多线程”是正例,开启多线程后,渲染页面速度加快,提升了性能。 +## 相关权限 +无 + +## 约束与限制 +* 本示例仅支持标准系统上运行,支持设备:华为手机。 + +* HarmonyOS系统:HarmonyOS NEXT Release及以上。 + +* DevEco Studio版本:DevEco Studio NEXT Release及以上。 + +* HarmonyOS SDK版本:HarmonyOS NEXT Release SDK及以上。 \ No newline at end of file diff --git a/AvoidTimeComsume/build-profile.json5 b/AvoidTimeComsume/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b2cc02977d74631a63703f33a1ae6c1f94d81219 --- /dev/null +++ b/AvoidTimeComsume/build-profile.json5 @@ -0,0 +1,36 @@ +{ + "app": { + "signingConfigs": [ + ], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compatibleSdkVersion": "5.0.0(12)", + "runtimeOS": "HarmonyOS", + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/AvoidTimeComsume/code-linter.json5 b/AvoidTimeComsume/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..77b31b517a3e5c2f34c3ae1bf44083c0c06cbd6d --- /dev/null +++ b/AvoidTimeComsume/code-linter.json5 @@ -0,0 +1,20 @@ +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + } +} \ No newline at end of file diff --git a/AvoidTimeComsume/entry/.gitignore b/AvoidTimeComsume/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/AvoidTimeComsume/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/AvoidTimeComsume/entry/build-profile.json5 b/AvoidTimeComsume/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..0311b505dbf43f0d22662c8d783c5f4464d15b15 --- /dev/null +++ b/AvoidTimeComsume/entry/build-profile.json5 @@ -0,0 +1,25 @@ +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + } + ] +} \ No newline at end of file diff --git a/AvoidTimeComsume/entry/hvigorfile.ts b/AvoidTimeComsume/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..c6edcd90486dd5a853cf7d34c8647f08414ca7a3 --- /dev/null +++ b/AvoidTimeComsume/entry/hvigorfile.ts @@ -0,0 +1,6 @@ +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/AvoidTimeComsume/entry/obfuscation-rules.txt b/AvoidTimeComsume/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/AvoidTimeComsume/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/AvoidTimeComsume/entry/oh-package.json5 b/AvoidTimeComsume/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..248c3b7541a589682a250f86a6d3ecf7414d2d6a --- /dev/null +++ b/AvoidTimeComsume/entry/oh-package.json5 @@ -0,0 +1,10 @@ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/AvoidTimeComsume/entry/src/main/ets/common/Item.ets b/AvoidTimeComsume/entry/src/main/ets/common/Item.ets new file mode 100644 index 0000000000000000000000000000000000000000..b973a781e339aa564fc3fc37c71793ceb844b1c2 --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/ets/common/Item.ets @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@Sendable +// DocsCode1 +export class Item { + url: string = ''; + id: number = 0; + name: string = ''; + + // DocsDot + constructor(url:string,id:number,name:string) { + this.url = url; + this.id = id; + this.name = name; + } + // DocsDot +} +// DocsCode1 + +export class ResponseData{ + public data: Item[] = []; +} + +export function dataToItem(data: object[]): Item[]{ + let arr: Item[] = []; + for(let dataElement of data){ + let temp = dataElement as Item; + arr.push(new Item(temp.url,temp.id,temp.name)); + } + return arr; +} \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/ets/entryability/EntryAbility.ets b/AvoidTimeComsume/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..567c1d90258a23974f05716ee7472a01584224e8 --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; +import { BusinessError } from '@kit.BasicServicesKit'; + +export default class EntryAbility extends UIAbility { + private color: string = '#F5F5F5'; + + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + hilog.info(0x0000, 'Sample', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(0x0000, 'Sample', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'Sample', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(0x0000, 'Sample', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'Sample', 'Succeeded in loading the content.'); + }); + + windowStage.getMainWindow().then((windowObj) => { + windowObj.setWindowPrivacyMode(true); + let windowClass: window.Window = windowObj; + windowClass.setWindowLayoutFullScreen(true); + let sysBarProps: window.SystemBarProperties = { + statusBarColor: this.color, + navigationBarColor: this.color, + statusBarContentColor: this.color, + navigationBarContentColor: this.color + }; + windowClass.setWindowSystemBarProperties(sysBarProps) + }).catch((err: BusinessError) => { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + }) + } + + onWindowStageDestroy(): + void { + // Main window is destroyed, release UI related resources + hilog + .info + ( + 0x0000, + 'Sample', + '%{public}s', + 'Ability onWindowStageDestroy' + ) + ; + } + + onForeground(): + void { + // Ability has brought to foreground + hilog + .info + ( + 0x0000, + 'Sample', + '%{public}s', + 'Ability onForeground' + ) + ; + } + + onBackground(): + void { + // Ability has back to background + hilog + .info + ( + 0x0000, + 'Sample', + '%{public}s', + 'Ability onBackground' + ) + ; + } +} diff --git a/AvoidTimeComsume/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/AvoidTimeComsume/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..dfa9341ece95bcb7d89387e31ead4128544b5a3b --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * 最佳实践 主线程耗时操作优化指导 + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(0x0000, 'Sample', 'onBackup ok'); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(0x0000, 'Sample', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + } +} \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/ets/pages/Index.ets b/AvoidTimeComsume/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..c76a4e4799dd3057e5132b2acdbfe55703a05fbc --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { router } from '@kit.ArkUI'; + +class DirectoryItem { + title: ResourceStr = ''; + uri: string = ''; + id: string = ''; +} + +@Entry +@Component +struct Index { + private directory: DirectoryItem[] = [ + { + title: $r('app.string.redundant_operation'), + uri: 'views/RedundantOperation', + id: 'RedundantOperation' + }, + { + title: $r('app.string.no_redundant_operation'), + uri: 'views/NoRedundantOperation', + id: 'NoRedundantOperation' + }, + { + title: $r('app.string.negative_of_grid'), + uri: 'views/NegativeOfGrid', + id: 'NegativeOfGrid' + }, + { + title: $r('app.string.positive_of_grid'), + uri: 'views/PositiveOfGrid', + id: 'PositiveOfGrid' + }, + { + title: $r('app.string.negative_of_lazy_forEach'), + uri: 'views/NegativeOfLazyForEach', + id: 'NegativeOfLazyForEach' + }, + { + title: $r('app.string.positive_of_lazy_forEach'), + uri: 'views/PositiveOfLazyForEach', + id: 'PositiveOfLazyForEach' + }, + { + title: $r('app.string.negative_of_property'), + uri: 'views/NegativeOfProperty', + id: 'NegativeOfProperty' + }, + { + title: $r('app.string.positive_of_property'), + uri: 'views/PositiveOfProperty', + id: 'PositiveOfProperty' + }, + { + title: $r('app.string.get_str_of_resource'), + uri: 'views/GetStrOfResource', + id: 'GetStrOfResource' + }, + { + title: $r('app.string.get_str_of_id'), + uri: 'views/GetStrOfId', + id: 'GetStrOfId' + }, + { + title: $r('app.string.use_async'), + uri: 'views/UseAsync', + id: 'UseAsync' + }, + { + title: $r('app.string.use_task_pool'), + uri: 'views/UseTaskPool', + id: 'UseTaskPool' + } + ] + + build() { + Column() { + Text($r('app.string.EntryAbility_label')) + .fontSize(30) + .fontWeight(700) + .width('100%') + .height(56) + .margin({ top: 92 }) + .padding({ left: 16 }) + Column() { + Grid() { + ForEach(this.directory, (item: DirectoryItem) => { + GridItem() { + Button(item.title) + .id(item.id) + .fontSize(16) + .width('100%') + .height(40) + .backgroundColor('#0A59F7') + .onClick(() => { + router.pushUrl({ + url: item.uri + }); + }) + } + }, (item: DirectoryItem) => JSON.stringify(item)) + } + .columnsGap(12) + .rowsGap(12) + .padding({ left: 16, right: 16 }) + .columnsTemplate('1fr 1fr') + .height(314) + + Column({ space: 12 }) { + Button($r('app.string.negative_of_onScroll')) + .id('NegativeOfOnScroll') + .fontSize(16) + .width('100%') + .height(40) + .backgroundColor('#0A59F7') + .onClick(() => { + router.pushUrl({ + url: 'views/NegativeOfOnScroll' + }); + }) + Button($r('app.string.positive_of_onScroll')) + .id('PositiveOfOnScroll') + .fontSize(16) + .width('100%') + .height(40) + .backgroundColor('#0A59F7') + .onClick(() => { + router.pushUrl({ + url: 'views/PositiveOfOnScroll' + }); + }) + Button($r('app.string.conditional_rendering')) + .id('ConditionalRendering') + .fontSize(16) + .width('100%') + .height(40) + .backgroundColor('#0A59F7') + .onClick(() => { + router.pushUrl({ + url: 'views/ConditionalRendering' + }); + }) + } + .padding({ left: 16, right: 16, bottom: 44 }) + } + } + .backgroundColor('#F5F5F5') + .height('100%') + .justifyContent(FlexAlign.SpaceBetween) + } +} \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/ets/views/ConditionalRendering.ets b/AvoidTimeComsume/entry/src/main/ets/views/ConditionalRendering.ets new file mode 100644 index 0000000000000000000000000000000000000000..cfbf980863165c7cfad292ca0736e730e266cbab --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/ets/views/ConditionalRendering.ets @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { router } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +// DocsCode 1 +@Entry +@Component +struct MyComponent { + // Toggles the custom component flag + @State flag: boolean = false; + + build() { + Column({ space: 10 }) { + Row({ space: 5 }) { + Column() { + Image($r('app.media.chevron_left')) + .width(16) + .height(16) + } + .width(40) + .height(40) + .justifyContent(FlexAlign.Center) + .backgroundColor('#E8E8E8') + .borderRadius(40) + .onClick(() => { + router.back({ + url: 'pages/Index' + }); + }) + + Text($r('app.string.conditional_rendering')) + .fontSize(20) + .fontWeight(700) + .height(26) + } + .width('100%') + .height(56) + .margin({ top: 36 }) + + // Use conditional rendering to simulate a scene where components are frequently created and destroyed with the click of a button + if (this.flag) { + // Custom component A + CustomComponentA() + } else { + // Custom component B + CustomComponentB() + } + Button('switch custom component') + .width('100%') + .backgroundColor('#0A59F7') + .onClick(() => { + // Click the button to switch to the custom component + this.flag = !this.flag; + }) + } + .width('100%') + .height('100%') + .justifyContent(FlexAlign.SpaceBetween) + .padding({ left: 16, right: 16, bottom: 44 }) + .backgroundColor('#F5F5F5') + } +} + +@Component +struct CustomComponentA { + aboutToAppear(): void { + let temp = 0; + for (let i = 0; i < 1000000; i++) { + temp += 1; + } + hilog.info(0x0001, 'Sample', `%{public}s', 'CustomComponentA aboutToAppear ${temp}`); + } + + aboutToDisappear(): void { + let temp = 0; + for (let i = 0; i < 1000000; i++) { + temp += 1; + } + hilog.info(0x0001, 'Sample', '%{public}s', `CustomComponentA aboutToDisappear ${temp}`); + } + + build() { + Column() + .backgroundColor(Color.Blue) + .width(200) + .height(200) + } +} + +@Component +struct CustomComponentB { + aboutToAppear(): void { + let temp = 0; + for (let i = 0; i < 1000000; i++) { + temp += 1; + } + hilog.info(0x0001, 'Sample', '%{public}s', `CustomComponentB aboutToAppear ${temp}`); + } + + aboutToDisappear(): void { + let temp = 0; + for (let i = 0; i < 1000000; i++) { + temp += 1; + } + hilog.info(0x0001, 'Sample', '%{public}s', `CustomComponentB aboutToDisappear ${temp}`); + } + + build() { + Column() + .backgroundColor(Color.Gray) + .width(200) + .height(200) + } +} + +// DocsCode 1 \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/ets/views/GetStrOfId.ets b/AvoidTimeComsume/entry/src/main/ets/views/GetStrOfId.ets new file mode 100644 index 0000000000000000000000000000000000000000..94a019ced609222d16d4b2cd3278e7a5e447912d --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/ets/views/GetStrOfId.ets @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// DocsCode 1 +import { hiTraceMeter } from '@kit.PerformanceAnalysisKit'; +import { router } from '@kit.ArkUI'; + +@Entry +@Component +struct GetStrOfId { + @State message: string = 'getStringSyncAfter'; + + aboutToAppear(): void { + hiTraceMeter.startTrace('getStringSyncAfter', 1); + // The input parameter of the getStringSync operation directly uses the resource and does use the resource ID + getContext().resourceManager.getStringSync($r('app.string.test').id) + hiTraceMeter.finishTrace('getStringSyncAfter', 1) + } + + build() { + Column() { + Row({ space: 5 }) { + Column() { + Image($r('app.media.chevron_left')) + .width(16) + .height(16) + } + .width(40) + .height(40) + .justifyContent(FlexAlign.Center) + .backgroundColor('#E8E8E8') + .borderRadius(40) + .onClick(() => { + router.back({ + url: 'pages/Index' + }); + }) + + Text($r('app.string.get_str_of_id')) + .fontSize(20) + .fontWeight(700) + .height(26) + } + .width('100%') + .height(56) + .margin({ top: 20 }) + + TextArea({ text: this.message }) + .height('40%') + } + .height('100%') + .width('100%') + .padding(16) + .backgroundColor('#F5F5F5') + } +} + +// DocsCode 1 \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/ets/views/GetStrOfResource.ets b/AvoidTimeComsume/entry/src/main/ets/views/GetStrOfResource.ets new file mode 100644 index 0000000000000000000000000000000000000000..79bbc1d82b6d9e8dcbcc1ef26b9a88b624444e74 --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/ets/views/GetStrOfResource.ets @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// DocsCode 1 +import { hiTraceMeter } from '@kit.PerformanceAnalysisKit'; +import { router } from '@kit.ArkUI'; + +@Entry +@Component +struct GetStrOfResource { + @State message: string = 'getStringSync'; + + aboutToAppear(): void { + hiTraceMeter.startTrace('getStringSync', 1); + // The input parameter of the getStringSync operation directly uses the resource and does not use the resource ID + getContext().resourceManager.getStringSync($r('app.string.test')) + hiTraceMeter.finishTrace('getStringSync', 1) + } + + build() { + Column() { + Row({ space: 5 }) { + Column() { + Image($r('app.media.chevron_left')) + .width(16) + .height(16) + } + .width(40) + .height(40) + .justifyContent(FlexAlign.Center) + .backgroundColor('#E8E8E8') + .borderRadius(40) + .onClick(() => { + router.back({ + url: 'pages/Index' + }); + }) + + Text($r('app.string.get_str_of_resource')) + .fontSize(20) + .fontWeight(700) + .height(26) + } + .width('100%') + .height(56) + .margin({ top: 20 }) + + TextArea({text: this.message}) + .height('40%') + } + .height('100%') + .width('100%') + .padding(16) + .backgroundColor('#F5F5F5') + } +} + +// DocsCode 1 \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/ets/views/NegativeOfGrid.ets b/AvoidTimeComsume/entry/src/main/ets/views/NegativeOfGrid.ets new file mode 100644 index 0000000000000000000000000000000000000000..2ea41c902a769417f5a275b1f61647a6fa776f45 --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/ets/views/NegativeOfGrid.ets @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hiTraceMeter } from '@kit.PerformanceAnalysisKit'; +import { router } from '@kit.ArkUI'; + +class MyDataSource implements IDataSource { + private dataArray: number[] = []; + + public pushData(data: number): void { + this.dataArray.push(data); + } + + // The total amount of data from the data source + public totalCount(): number { + return this.dataArray.length; + } + + // Returns data for the specified index location + public getData(index: number): number { + return this.dataArray[index]; + } + + registerDataChangeListener(): void { + } + + unregisterDataChangeListener(): void { + } +} + +@Entry +@Component +struct NegativeOfGrid { + // Data sources + private data: MyDataSource = new MyDataSource(); + + aboutToAppear(): void { + for (let i = 1; i < 1000; i++) { + this.data.pushData(i); + } + } + + build() { + Column() { + Row({ space: 5 }) { + Column() { + Image($r('app.media.chevron_left')) + .width(16) + .height(16) + } + .width(40) + .height(40) + .justifyContent(FlexAlign.Center) + .backgroundColor('#E8E8E8') + .borderRadius(40) + .onClick(() => { + router.back({ + url: 'pages/Index' + }); + }) + + Text($r('app.string.negative_of_grid')) + .fontSize(20) + .fontWeight(700) + .height(26) + } + .padding({ left: 16, right: 16 }) + .width('100%') + .height(56) + .margin({ top: 36 }) + + Column() { + Grid() { + LazyForEach(this.data, (item: number) => { + GridItem() { + // Use reusable custom components + ReusableChildComponent({ item: item }) + } + }, (item: number) => item.toString()) + } + .cachedCount(2) + .columnsTemplate('1fr 1fr 1fr 1fr') + .columnsGap(10) + .rowsGap(10) + } + .margin({ top: 12 }) + } + .backgroundColor('#F5F5F5') + } +} + +// Custom components are decorated @Reusable decorators, which signify their ability to be reused by components +@Reusable +@Component +struct ReusableChildComponent { + @State item: number = 0; + + // DocsCode 1 + // ... + // Simulate time-consuming operations with loop functions + count(): number { + let temp: number = 0; + for (let index = 0; index < 1000000; index++) { + temp += 1; + } + return temp; + } + + aboutToReuse(params: Record): void { + hiTraceMeter.startTrace('ReuseOfGrid', 1001); + this.item = params.item; + // Simulate time-consuming operations + this.count(); + hiTraceMeter.finishTrace('ReuseOfGrid', 1001); + } + + // ... + // DocsCode 1 + + build() { + Column() { + Image($r('app.media.app_icon')) + .width(48) + .height(48) + .margin({ bottom: 12 }) + Text(`image${this.item}`) + .fontSize(12) + .textAlign(TextAlign.Center) + } + .width('100%') + .height(82) + } +} \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/ets/views/NegativeOfLazyForEach.ets b/AvoidTimeComsume/entry/src/main/ets/views/NegativeOfLazyForEach.ets new file mode 100644 index 0000000000000000000000000000000000000000..e63b3c29f45d5a198a09494ed3466b46ff983e30 --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/ets/views/NegativeOfLazyForEach.ets @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog, hiTraceMeter } from '@kit.PerformanceAnalysisKit'; +import { router } from '@kit.ArkUI'; + +class MyDataSource implements IDataSource { + private dataArray: number[] = []; + + public pushData(data: number): void { + this.dataArray.push(data); + } + + // The total amount of data from the data source + public totalCount(): number { + return this.dataArray.length; + } + + // Returns data for the specified index location + public getData(index: number): number { + return this.dataArray[index]; + } + + registerDataChangeListener(): void { + } + + unregisterDataChangeListener(): void { + } +} + +@Entry +@Component +struct NegativeOfLazyForEach { + // Data sources + private data: MyDataSource = new MyDataSource(); + private item: number = 0; + + // DocsCode 1 + // ... + aboutToAppear(): void { + // DocsDot + for (let i = 1; i < 1000; i++) { + this.data.pushData(i); + } + this.item = this.itemGeneratorFunc(0); + hilog.info(0x0000, 'Sample', '%{public}s', `item: ${this.item}`); + // DocsDot + } + + // Simulate time-consuming operations + itemGeneratorFunc(item: number): number { + let temp: number = 0; + for (let index = 0; index < 1000000; index++) { + temp += 1; + } + item += temp; + return item; + } + + build() { + Column() { + Row({ space: 5 }) { + Column() { + Image($r('app.media.chevron_left')) + .width(16) + .height(16) + } + .width(40) + .height(40) + .justifyContent(FlexAlign.Center) + .backgroundColor('#E8E8E8') + .borderRadius(40) + .onClick(() => { + router.back({ + url: 'pages/Index' + }); + }) + + Text($r('app.string.negative_of_lazy_forEach')) + .fontSize(20) + .fontWeight(700) + .height(26) + } + .padding({ left: 16, right: 16 }) + .width('100%') + .height(56) + .margin({ top: 36 }) + + Column({ space: 5 }) { + Grid() { + LazyForEach(this.data, (item: number) => { + GridItem() { + // Use reusable custom components + ReusableChildComponent({ item: item }) + } + }, (item: number) => item.toString()) + } + // DocsDot + .cachedCount(2) + .columnsTemplate('1fr 1fr 1fr 1fr') + .columnsGap(10) + .rowsGap(10) + + // DocsDot + } + .margin({ top: 12 }) + } + .backgroundColor('#F5F5F5') + } + + // DocsCode 1 +} + +// Custom components are decorated @Reusable decorators, which signify their ability to be reused by components +@Reusable +@Component +struct ReusableChildComponent { + @State item: number = 0; + + // Simulate time-consuming operations with loop functions + count(): number { + let temp: number = 0; + for (let index = 0; index < 1000000; index++) { + temp += 1; + } + return temp; + } + + aboutToReuse(params: Record): void { + hiTraceMeter.startTrace('ReuseOfGrid', 1001); + this.item = params.item; + // Simulate time-consuming operations + this.count(); + hiTraceMeter.finishTrace('ReuseOfGrid', 1001) + } + + build() { + Column() { + Image($r('app.media.app_icon')) + .width(48) + .height(48) + .margin({ bottom: 12 }) + Text(`image${this.item}`) + .fontSize(12) + .textAlign(TextAlign.Center) + } + .width('100%') + .height(100) + } +} \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/ets/views/NegativeOfOnScroll.ets b/AvoidTimeComsume/entry/src/main/ets/views/NegativeOfOnScroll.ets new file mode 100644 index 0000000000000000000000000000000000000000..bdd2617a28d9dcd1dddef499fd9a3fadfe4f0cb3 --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/ets/views/NegativeOfOnScroll.ets @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog, hiTraceMeter } from '@kit.PerformanceAnalysisKit'; +import { router } from '@kit.ArkUI'; + +// DocsCode 1 +// onWillScroll high-frequency event callback counterexample +@Entry +@Component +struct NegativeOfOnScroll { + private arr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + count(): number { + let temp: number = 0; + for (let i = 0; i < 1000000; i++) { + temp += 1; + } + return temp; + } + + build() { + Column() { + Row({ space: 5 }) { + Column() { + Image($r('app.media.chevron_left')) + .width(16) + .height(16) + } + .width(40) + .height(40) + .justifyContent(FlexAlign.Center) + .backgroundColor('#E8E8E8') + .borderRadius(40) + .onClick(() => { + router.back({ + url: 'pages/Index' + }); + }) + + Text($r('app.string.negative_of_onScroll')) + .fontSize(20) + .fontWeight(700) + .height(26) + } + .width('100%') + .height(56) + .margin({ top: 20 }) + + Scroll() { + List() { + ForEach(this.arr, (item: number) => { + ListItem() { + Text('TextItem' + item) + .width('100%') + .padding({ left: 12 }) + } + .width('100%') + .height(48) + }, (item: number) => item.toString()) + } + .divider({ strokeWidth: 1, color: '#F5F5F5' }) + .width('100%') + .height('100%') + } + .width('100%') + .height(492) + .margin({ top: 8 }) + .backgroundColor(Color.White) + .borderRadius(20) + .onWillScroll(() => { + hiTraceMeter.startTrace('ScrollSlide', 1001); + hilog.info(0x0000, 'Sample', '%{public}s', 'Scroll TextItem'); + // Time-consuming operation + this.count(); + // Business logic + // ... + hiTraceMeter.finishTrace('ScrollSlide', 1001); + }) + } + .padding(16) + .height('100%') + .backgroundColor('#F5F5F5') + } +} + +// DocsCode 1 \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/ets/views/NegativeOfProperty.ets b/AvoidTimeComsume/entry/src/main/ets/views/NegativeOfProperty.ets new file mode 100644 index 0000000000000000000000000000000000000000..92f46c95d014100587dd715a3d63ba8df17db826 --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/ets/views/NegativeOfProperty.ets @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { router } from '@kit.ArkUI'; + +// DocsCode 1 +@Entry +@Component +struct NegativeOfProperty { + // Row Width + @State rowWidth: number = 200; + + getHeight(): number { + let height: number = 0; + // Simulate time-consuming operations with loop functions + for (let index = 0; index < 1000000; index++) { + height += 0.0001; + } + return height; + } + + build() { + Column() { + Row({ space: 5 }) { + Column() { + Image($r('app.media.chevron_left')) + .width(16) + .height(16) + } + .width(40) + .height(40) + .justifyContent(FlexAlign.Center) + .backgroundColor('#E8E8E8') + .borderRadius(40) + .onClick(() => { + router.back({ + url: 'pages/Index' + }); + }) + + Text($r('app.string.negative_of_property')) + .fontSize(20) + .fontWeight(700) + .height(26) + } + .width('100%') + .height(56) + .margin({ top: 36 }) + + Row() + .width(this.rowWidth) + .height(this.getHeight()) + .backgroundColor(Color.Blue) + + Button('change row width') + .onClick(() => { + this.rowWidth = this.rowWidth + 20; + if (this.rowWidth > 300) { + this.rowWidth = 200; + } + }) + .width('100%') + .backgroundColor('#0A59F7') + } + .justifyContent(FlexAlign.SpaceBetween) + .width('100%') + .height('100%') + .padding({ left: 16, right: 16, bottom: 44 }) + .backgroundColor('#F5F5F5') + } +} + +// DocsCode 1 \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/ets/views/NoRedundantOperation.ets b/AvoidTimeComsume/entry/src/main/ets/views/NoRedundantOperation.ets new file mode 100644 index 0000000000000000000000000000000000000000..80c8e67d52d4d048e9197040a174d6e9aec4d5ec --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/ets/views/NoRedundantOperation.ets @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { router } from '@kit.ArkUI'; + +// DocsCode 1 +// Redundancy operation example +@Entry +@Component +struct NoRedundantOperation { + private arr: number[] = []; + + aboutToAppear(): void { + for (let i = 0; i < 500; i++) { + this.arr[i] = i; + } + } + + build() { + Column() { + Row({ space: 5 }) { + Column() { + Image($r('app.media.chevron_left')) + .width(16) + .height(16) + } + .width(40) + .height(40) + .justifyContent(FlexAlign.Center) + .backgroundColor('#E8E8E8') + .borderRadius(40) + .onClick(() => { + router.back({ + url: 'pages/Index' + }); + }) + + Text($r('app.string.no_redundant_operation')) + .fontSize(20) + .fontWeight(700) + .height(26) + } + .width('100%') + .height(56) + .margin({ top: 36 }) + + Scroll() { + List() { + ForEach(this.arr, (item: number) => { + ListItem() { + Text('TextItem' + item) + .width('100%') + .padding({ left: 12 }) + } + .width('100%') + .height(48) + }, (item: number) => item.toString()) + } + .divider({ strokeWidth: 1, color: '#F5F5F5' }) + .width('100%') + .height('100%') + } + .margin({ top: 8 }) + .width('100%') + .height('86%') + .backgroundColor(Color.White) + .borderRadius(20) + .onWillScroll(() => { + // Business logic + // ... + hilog.info(0x0000, 'Sample', '%{public}s', 'Empty callback'); + }) + } + .backgroundColor('#F5F5F5') + .height('100%') + .padding({ left: 16, right: 16, bottom: 16 }) + } +} + +// DocsCode 1 \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/ets/views/PositiveOfGrid.ets b/AvoidTimeComsume/entry/src/main/ets/views/PositiveOfGrid.ets new file mode 100644 index 0000000000000000000000000000000000000000..59ad7326861bbcfa583fb854de1a9c9b2aa5116d --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/ets/views/PositiveOfGrid.ets @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hiTraceMeter } from '@kit.PerformanceAnalysisKit'; +import { router } from '@kit.ArkUI'; + +class MyDataSource implements IDataSource { + private dataArray: number[] = []; + + public pushData(data: number): void { + this.dataArray.push(data); + } + + // The total amount of data from the data source + public totalCount(): number { + return this.dataArray.length; + } + + // Returns data for the specified index location + public getData(index: number): number { + return this.dataArray[index]; + } + + registerDataChangeListener(): void { + } + + unregisterDataChangeListener(): void { + } +} + +@Entry +@Component +struct PositiveOfGrid { + // Data sources + private data: MyDataSource = new MyDataSource(); + + aboutToAppear(): void { + for (let i = 1; i < 1000; i++) { + this.data.pushData(i); + } + } + + build() { + Column() { + Row({ space: 5 }) { + Column() { + Image($r('app.media.chevron_left')) + .width(16) + .height(16) + } + .width(40) + .height(40) + .justifyContent(FlexAlign.Center) + .backgroundColor('#E8E8E8') + .borderRadius(40) + .onClick(() => { + router.back({ + url: 'pages/Index' + }); + }) + + Text($r('app.string.positive_of_grid')) + .fontSize(20) + .fontWeight(700) + .height(26) + } + .padding({ left: 16, right: 16 }) + .width('100%') + .height(56) + .margin({ top: 36 }) + + Column({ space: 5 }) { + Grid() { + LazyForEach(this.data, (item: number) => { + GridItem() { + // Use reusable custom components + ReusableChildComponent({ item: item }) + } + }, (item: number) => item.toString()) + } + .cachedCount(2) + .columnsTemplate('1fr 1fr 1fr 1fr') + .columnsGap(10) + .rowsGap(10) + } + .margin({ top: 12 }) + } + .backgroundColor('#F5F5F5') + } +} + +// Custom components are decorated @Reusable decorators, which signify their ability to be reused by components +@Reusable +@Component +struct ReusableChildComponent { + @State item: number = 0; + + // DocsCode 1 + // ... + aboutToReuse(params: Record): void { + hiTraceMeter.startTrace('ReuseOfGrid', 1001); + this.item = params.item; + hiTraceMeter.finishTrace('ReuseOfGrid', 1001) + } + + // ... + // DocsCode 1 + + build() { + Column() { + Image($r('app.media.app_icon')) + .width(48) + .height(48) + .margin({ bottom: 12 }) + Text(`image${this.item}`) + .fontSize(12) + .textAlign(TextAlign.Center) + } + .width('100%') + .height(82) + } +} \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/ets/views/PositiveOfLazyForEach.ets b/AvoidTimeComsume/entry/src/main/ets/views/PositiveOfLazyForEach.ets new file mode 100644 index 0000000000000000000000000000000000000000..2e314c0d4ba89ce61f7cd1569b3c1cdf99eb1d9f --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/ets/views/PositiveOfLazyForEach.ets @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hiTraceMeter } from '@kit.PerformanceAnalysisKit'; +import { router } from '@kit.ArkUI'; + +class MyDataSource implements IDataSource { + private dataArray: number[] = []; + + public pushData(data: number): void { + this.dataArray.push(data); + } + + // The total amount of data from the data source + public totalCount(): number { + return this.dataArray.length; + } + + // Returns data for the specified index location + public getData(index: number): number { + return this.dataArray[index]; + } + + registerDataChangeListener(): void { + } + + unregisterDataChangeListener(): void { + } +} + +@Entry +@Component +struct PositiveOfLazyForEach { + // Data sources + private data: MyDataSource = new MyDataSource(); + // DocsCode 1 + // The value calculated by the time-consuming operation + private timeConsumingValue: number = 0; + + aboutToAppear(): void { + // DocsDot + for (let i = 1; i < 1000; i++) { + this.data.pushData(i); + } + // DocsDot + // Execute time-consuming asynchronous functions + this.itemGeneratorFunc(); + } + + // Simulate time-consuming operations + itemGeneratorFunc() { + let temp: number = 0; + for (let index = 0; index < 1000000; index++) { + temp += 1; + } + this.timeConsumingValue = temp; + } + + build() { + Column() { + Row({ space: 5 }) { + Column() { + Image($r('app.media.chevron_left')) + .width(16) + .height(16) + } + .width(40) + .height(40) + .justifyContent(FlexAlign.Center) + .backgroundColor('#E8E8E8') + .borderRadius(40) + .onClick(() => { + router.back({ + url: 'pages/Index' + }); + }) + + Text($r('app.string.positive_of_lazy_forEach')) + .fontSize(20) + .fontWeight(700) + .height(26) + } + .padding({ left: 16, right: 16 }) + .width('100%') + .height(56) + .margin({ top: 36 }) + + Column({ space: 5 }) { + Grid() { + LazyForEach(this.data, (item: number) => { + GridItem() { + // Use reusable custom components + ReusableChildComponent({ item: item + this.timeConsumingValue }) + } + }, (item: number) => item.toString()) + } + // DocsDot + .cachedCount(2) + .columnsTemplate('1fr 1fr 1fr 1fr') + .columnsGap(10) + .rowsGap(10) + + // DocsDot + } + .margin({ top: 12 }) + } + .backgroundColor('#F5F5F5') + } + + // DocsCode 1 +} + +// Custom components are decorated @Reusable decorators, which signify their ability to be reused by components +@Reusable +@Component +struct ReusableChildComponent { + @State item: number = 0; + + aboutToReuse(params: Record): void { + hiTraceMeter.startTrace('ReuseOfGrid', 1001); + this.item = params.item; + hiTraceMeter.finishTrace('ReuseOfGrid', 1001) + } + + build() { + Column() { + Image($r('app.media.app_icon')) + .width(48) + .height(48) + .margin({ bottom: 12 }) + Text(`${this.item}`) + .fontSize(12) + .textAlign(TextAlign.Center) + } + .width('100%') + .height(100) + } +} \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/ets/views/PositiveOfOnScroll.ets b/AvoidTimeComsume/entry/src/main/ets/views/PositiveOfOnScroll.ets new file mode 100644 index 0000000000000000000000000000000000000000..889ddb58dd5c30318b947145eb7d00c88c84ae8e --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/ets/views/PositiveOfOnScroll.ets @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog, hiTraceMeter } from '@kit.PerformanceAnalysisKit'; +import { router } from '@kit.ArkUI'; + +// DocsCode 1 +// onWillScroll high-frequency event callback positive example +@Entry +@Component +struct PositiveOfOnScroll { + private arr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + build() { + Column() { + Row({ space: 5 }) { + Column() { + Image($r('app.media.chevron_left')) + .width(16) + .height(16) + } + .width(40) + .height(40) + .justifyContent(FlexAlign.Center) + .backgroundColor('#E8E8E8') + .borderRadius(40) + .onClick(() => { + router.back({ + url: 'pages/Index' + }); + }) + + Text($r('app.string.positive_of_onScroll')) + .fontSize(20) + .fontWeight(700) + .height(26) + } + .width('100%') + .height(56) + .margin({ top: 20 }) + + Scroll() { + List() { + ForEach(this.arr, (item: number) => { + ListItem() { + Text('TextItem' + item) + .width('100%') + .padding({ left: 12 }) + } + .width('100%') + .height(48) + }, (item: number) => item.toString()) + } + .divider({ strokeWidth: 1, color: '#F5F5F5' }) + .width('100%') + .height('100%') + } + .width('100%') + .height(492) + .margin({ top: 8 }) + .backgroundColor(Color.White) + .borderRadius(20) + .onWillScroll(() => { + hiTraceMeter.startTrace('ScrollSlide', 1001); + hilog.info(0x0000, 'Sample', '%{public}s', 'Scroll TextItem'); + // Business logic + // ... + hiTraceMeter.finishTrace('ScrollSlide', 1001); + }) + } + .padding(16) + .height('100%') + .backgroundColor('#F5F5F5') + } +} + +// DocsCode 1 \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/ets/views/PositiveOfProperty.ets b/AvoidTimeComsume/entry/src/main/ets/views/PositiveOfProperty.ets new file mode 100644 index 0000000000000000000000000000000000000000..fb3af072f8daa8d60680a559b096f283b02dd575 --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/ets/views/PositiveOfProperty.ets @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// DocsCode 1 +import { taskpool } from '@kit.ArkTS'; // Task pools +import { router } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +@Concurrent +function getHeight(): number { + let height: number = 0; + // Simulate time-consuming operations with loop functions + for (let index = 0; index < 1000000; index++) { + height += 0.0001; + } + hilog.info(0x0000, 'Sample', '%{public}s', 'Scenario 4 call getHeight'); + return height; +} + +// Execute getHeight +taskpool.execute(getHeight).then((value: Object) => { + AppStorage.SetOrCreate('height', value); +}) + +@Entry +@Component +struct PositiveOfProperty { + // Row width + @State rowWidth: number = 200; + // Row height + @StorageLink('height') rowHeight: number = 0; + // The number of times you click the button to change the width of the row + private count: number = 0; + + build() { + Column({ space: 10 }) { + Row({ space: 5 }) { + Column() { + Image($r('app.media.chevron_left')) + .width(16) + .height(16) + } + .width(40) + .height(40) + .justifyContent(FlexAlign.Center) + .backgroundColor('#E8E8E8') + .borderRadius(40) + .onClick(() => { + router.back({ + url: 'pages/Index' + }); + }) + + Text($r('app.string.positive_of_property')) + .fontSize(20) + .fontWeight(700) + .height(26) + } + .width('100%') + .height(56) + .margin({ top: 36 }) + + Row() + .width(this.rowWidth) + .height(this.rowHeight) + .backgroundColor(Color.Blue) + + Button('change row width') + .width('100%') + .backgroundColor('#0A59F7') + .onClick(() => { + this.rowWidth = this.rowWidth + 20; + this.count++; + hilog.info(0x0000, 'Sample', 'Scenario 4 call getHeight: %{public}s', this.count); + if (this.rowWidth > 300) { + this.rowWidth = 200; + } + }) + } + .justifyContent(FlexAlign.SpaceBetween) + .width('100%') + .height('100%') + .padding({ left: 16, right: 16, bottom: 44 }) + .backgroundColor('#F5F5F5') + } +} + +// DocsCode 1 \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/ets/views/RedundantOperation.ets b/AvoidTimeComsume/entry/src/main/ets/views/RedundantOperation.ets new file mode 100644 index 0000000000000000000000000000000000000000..649b4fa716782e2994d7494d458dcac881a969d4 --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/ets/views/RedundantOperation.ets @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// DocsCode 1 +import { hilog, hiTraceMeter } from '@kit.PerformanceAnalysisKit'; +import { router } from '@kit.ArkUI'; + +// Redundant operations are counterexamples +@Entry +@Component +struct RedundantOperation { + private arr: number[] = []; + + aboutToAppear(): void { + for (let i = 0; i < 500; i++) { + this.arr[i] = i; + } + } + + build() { + Column() { + Row({ space: 5 }) { + Column() { + Image($r('app.media.chevron_left')) + .width(16) + .height(16) + } + .width(40) + .height(40) + .justifyContent(FlexAlign.Center) + .backgroundColor('#E8E8E8') + .borderRadius(40) + .onClick(() => { + router.back({ + url: 'pages/Index' + }); + }) + + Text($r('app.string.redundant_operation')) + .fontSize(20) + .fontWeight(700) + .height(26) + } + .width('100%') + .height(56) + .margin({ top: 36 }) + + Scroll() { + List() { + ForEach(this.arr, (item: number) => { + ListItem() { + Text('TextItem' + item) + .width('100%') + .padding({ left: 12 }) + } + .onAreaChange(() => { + // No business operations + // Negative example. + }) + .width('100%') + .height(48) + }, (item: number) => item.toString()) + } + .divider({ strokeWidth: 1, color: '#F5F5F5' }) + .width('100%') + .height('100%') + } + .width('100%') + .height('86%') + .margin({ top: 8 }) + .backgroundColor(Color.White) + .borderRadius(20) + .onWillScroll(() => { + hiTraceMeter.startTrace('ScrollSlide', 1001); + + hilog.debug(0x0000, 'Sample', 'Debug %{public}s', 'contents: logs'); + // Business logic + // ... + + hiTraceMeter.finishTrace('ScrollSlide', 1001); + }) + } + .backgroundColor('#F5F5F5') + .height('100%') + .padding({ left: 16, right: 16, bottom: 16 }) + } +} + +// DocsCode 1 \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/ets/views/UseAsync.ets b/AvoidTimeComsume/entry/src/main/ets/views/UseAsync.ets new file mode 100644 index 0000000000000000000000000000000000000000..9f43eb568e23d4eb975fd247d1e0eb19139e13ce --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/ets/views/UseAsync.ets @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Item, ResponseData, dataToItem } from '../common/Item'; +import { WaterFlowDataSource } from './WaterFlowDataSource'; +import { buffer } from '@kit.ArkTS'; +import { router } from '@kit.ArkUI'; + +@Entry +@Component +struct WaterFlowExample2 { + @State fontSize: number = 24; + scroller: Scroller = new Scroller(); + dataSource: WaterFlowDataSource = new WaterFlowDataSource(); + + @Builder + itemFoot() { + Text('Footer') + .fontSize(10) + .backgroundColor(Color.Red) + .width(50) + .height(50) + .align(Alignment.Center) + .margin({ top: 2 }) + } + + @Builder + imageCom(item: number) { + Image($r(`app.media.waterFlowTest${item % 3}`)) + .width('100%') + .layoutWeight(1) + .objectFit(ImageFit.Fill) + } + + // DocsCode 1 + build() { + Column({ space: 2 }) { + Row({ space: 5 }) { + Column() { + Image($r('app.media.chevron_left')) + .width(16) + .height(16) + } + .width(40) + .height(40) + .justifyContent(FlexAlign.Center) + .backgroundColor('#E8E8E8') + .borderRadius(40) + .onClick(() => { + router.back({ + url: 'pages/Index' + }); + }) + + Text($r('app.string.use_async')) + .fontSize(20) + .fontWeight(700) + .height(26) + } + .width('100%') + .height(56) + .margin({ top: 20 }) + + + WaterFlow() { + LazyForEach(this.dataSource, (item: number) => { + FlowItem() { + // DocsDot + this.imageCom(item); + // DocsDot + } + .onAppear(() => { + // Add data in advance when you are about to hit the bottom + if (item + 20 === this.dataSource.totalCount()) { + // Simulate the time it takes for the network to acquire data + this.mockRequestData().then((data: Item[]) => { + for (let i = 0; i < data.length; i++) { + this.dataSource.addLastItem(); + } + }) + } + }) + // DocsDot + .width('100%') + .height(320) + + // DocsDot + }, (item: number) => item.toString()) + } + // DocsDot + .cachedCount(2) + .columnsTemplate('1fr 1fr') + .columnsGap(12) + .rowsGap(12) + .width('100%') + .height('100%') + .onScrollFrameBegin((offset: number) => { + return { offsetRemain: offset }; + }) + + // DocsDot + } + .padding(16) + .height('100%') + .backgroundColor('#F5F5F5') + } + + async mockRequestData(): Promise { + let res: ResponseData = new ResponseData(); + // data.json is the local json data, which is about 20 MB in size, and simulates getting data from the network + await getContext().resourceManager.getRawFileContent('data.json').then((data: Uint8Array) => { + // parse json + let str = buffer.from(data).toString(); + res = JSON.parse(str); + }) + return dataToItem(res.data) + } + + // DocsCode 1 +} \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/ets/views/UseTaskPool.ets b/AvoidTimeComsume/entry/src/main/ets/views/UseTaskPool.ets new file mode 100644 index 0000000000000000000000000000000000000000..5bbb328bc3276ea1fff60509ff70d349a550ec41 --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/ets/views/UseTaskPool.ets @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { buffer, taskpool } from '@kit.ArkTS'; +import { Item, ResponseData, dataToItem } from '../common/Item'; +import { WaterFlowDataSource } from './WaterFlowDataSource'; +import { router } from '@kit.ArkUI'; + +@Entry +@Component +struct WaterFlowExample { + @State fontSize: number = 24; + scroller: Scroller = new Scroller(); + dataSource: WaterFlowDataSource = new WaterFlowDataSource(); + + @Builder + itemFoot() { + Text('Footer') + .fontSize(10) + .backgroundColor(Color.Red) + .width(50) + .height(50) + .align(Alignment.Center) + .margin({ top: 2 }) + } + + @Builder + imageCom(item: number) { + Image($r(`app.media.waterFlowTest${item % 3}`)) + .width('100%') + .layoutWeight(1) + .objectFit(ImageFit.Fill) + } + + // DocsCode 1 + build() { + Column({ space: 2 }) { + Row({ space: 5 }) { + Column() { + Image($r('app.media.chevron_left')) + .width(16) + .height(16) + } + .width(40) + .height(40) + .justifyContent(FlexAlign.Center) + .backgroundColor('#E8E8E8') + .borderRadius(40) + .onClick(() => { + router.back({ + url: 'pages/Index' + }); + }) + + Text($r('app.string.use_async')) + .fontSize(20) + .fontWeight(700) + .height(26) + } + .width('100%') + .height(56) + .margin({ top: 20 }) + + WaterFlow() { + LazyForEach(this.dataSource, (item: number) => { + FlowItem() { + // DocsDot + this.imageCom(item) + // DocsDot + } + .onAppear(() => { + // Add data in advance when you are about to hit the bottom + if (item + 20 === this.dataSource.totalCount()) { + // Simulate the time it takes for the network to acquire data + taskPoolExecute().then((data: Item[]) => { + for (let i = 0; i < data.length; i++) { + this.dataSource.addLastItem(); + } + }) + } + }) + // DocsDot + .width('100%') + .height(320) + + // DocsDot + }, (item: number) => item.toString()) + } + // DocsDot + .cachedCount(2) + .columnsTemplate('1fr 1fr') + .columnsGap(12) + .rowsGap(12) + .width('100%') + .height('100%') + .onScrollFrameBegin((offset: number) => { + return { offsetRemain: offset }; + }) + + // DocsDot + } + .padding(16) + .height('100%') + .backgroundColor('#F5F5F5') + } + + // DocsCode 1 +} + +// DocsCode 2 +// The following methods are defined outside of the component +async function taskPoolExecute(): Promise { + let task: taskpool.Task = new taskpool.Task(mockRequestData, getContext()); + return await taskpool.execute(task) as Item[]; +} + +async function mockRequestData(context: Context): Promise { + let res: ResponseData = new ResponseData(); + // data.json is the local json data, which is about 20 MB in size, and simulates getting data from the network + await context.resourceManager.getRawFileContent('data.json').then((data: Uint8Array) => { + // parse json + let str = buffer.from(data).toString(); + res = JSON.parse(str); + }) + let arr = dataToItem(res.data); + return arr; +} + +// DocsCode 2 \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/ets/views/WaterFlowDataSource.ets b/AvoidTimeComsume/entry/src/main/ets/views/WaterFlowDataSource.ets new file mode 100644 index 0000000000000000000000000000000000000000..d56e6a4394741cc57042c7040f7bc3e815b3841f --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/ets/views/WaterFlowDataSource.ets @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class WaterFlowDataSource implements IDataSource { + private dataArray: number[] = []; + private listeners: DataChangeListener[] = []; + + constructor() { + for (let i = 0; i < 40; i++) { + this.dataArray.push(i); + } + } + + // Obtain the data corresponding to the index + public getData(index: number): number { + return this.dataArray[index]; + } + + // Notify the controller of the data reload + notifyDataReload(): void { + this.listeners.forEach(listener => { + listener.onDataReloaded(); + }); + } + + // Notify the controller of the increase in data + notifyDataAdd(index: number): void { + this.listeners.forEach(listener => { + listener.onDataAdd(index); + }); + } + + // Notify the controller of data changes + notifyDataChange(index: number): void { + this.listeners.forEach(listener => { + listener.onDataChange(index); + }); + } + + // Notify the controller of the deletion of data + notifyDataDelete(index: number): void { + this.listeners.forEach(listener => { + listener.onDataDelete(index); + }); + } + + // Notify the controller of the data location change + notifyDataMove(from: number, to: number): void { + this.listeners.forEach(listener => { + listener.onDataMove(from, to); + }); + } + + // Notify the controller of bulk modification of data + notifyDatasetChange(operations: DataOperation[]): void { + this.listeners.forEach(listener => { + listener.onDatasetChange(operations); + }); + } + + // The total amount of data from the data source + public totalCount(): number { + return this.dataArray.length; + } + + // Register the controller who changes the data + registerDataChangeListener(listener: DataChangeListener): void { + if (this.listeners.indexOf(listener) < 0) { + this.listeners.push(listener); + } + } + + // Log out the controller who changed the data + unregisterDataChangeListener(listener: DataChangeListener): void { + const pos = this.listeners.indexOf(listener); + if (pos >= 0) { + this.listeners.slice(pos, 1); + } + } + + // Increase the data + public add1stItem(): void { + this.dataArray.splice(0, 0, this.dataArray.length); + this.notifyDataAdd(0); + } + + // Add an element to the tail of the data + public addLastItem(): void { + this.dataArray.splice(this.dataArray.length, 0, this.dataArray.length); + this.notifyDataAdd(this.dataArray.length - 1); + } + + // Add an element to the specified index location + public addItem(index: number): void { + this.dataArray.splice(index, 0, this.dataArray.length); + this.notifyDataAdd(index); + } + + // Delete the first element + public delete1stItem(): void { + this.dataArray.splice(0, 1); + this.notifyDataDelete(0); + } + + // Delete the second element + public delete2ndItem(): void { + this.dataArray.splice(1, 1); + this.notifyDataDelete(1); + } + + // Delete the last element + public deleteLastItem(): void { + this.dataArray.splice(-1, 1); + this.notifyDataDelete(this.dataArray.length); + } + + // Deletes an element at the specified index location + public deleteItem(index: number): void { + this.dataArray.splice(index, 1); + this.notifyDataDelete(index); + } + + // Reload the data + public reload(): void { + this.dataArray.splice(1, 1); + this.dataArray.splice(3, 2); + this.notifyDataReload(); + } +} \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/module.json5 b/AvoidTimeComsume/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..ad219d733f6afa5ea07f85f580208b08cc3b9041 --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/module.json5 @@ -0,0 +1,50 @@ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ], + } + ] + } +} \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/resources/base/element/color.json b/AvoidTimeComsume/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/resources/base/element/string.json b/AvoidTimeComsume/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..4850915cdb07e9d84f0fa8c3a47ae9d529d5b794 --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/resources/base/element/string.json @@ -0,0 +1,80 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + }, + { + "name": "test", + "value": "test" + }, + { + "name": "redundant_operation", + "value": "含有冗余操作" + }, + { + "name": "no_redundant_operation", + "value": "不含有冗余操作" + }, + { + "name": "negative_of_grid", + "value": "组件复用反例" + }, + { + "name": "positive_of_grid", + "value": "组件复用正例" + }, + { + "name": "negative_of_lazy_forEach", + "value": "循环渲染反例" + }, + { + "name": "positive_of_lazy_forEach", + "value": "循环渲染正例" + }, + { + "name": "negative_of_property", + "value": "组件属性反例" + }, + { + "name": "positive_of_property", + "value": "组件属性正例" + }, + { + "name": "get_str_of_resource", + "value": "通过资源对象" + }, + { + "name": "get_str_of_id", + "value": "通过资源ID" + }, + { + "name": "use_async", + "value": "使用异步" + }, + { + "name": "use_task_pool", + "value": "使用多线程" + }, + { + "name": "negative_of_onScroll", + "value": "高频事件回调执行耗时操作" + }, + { + "name": "positive_of_onScroll", + "value": "高频事件回调不执行耗时操作" + }, + { + "name": "conditional_rendering", + "value": "条件渲染" + } + ] +} \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/resources/base/media/background.png b/AvoidTimeComsume/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d Binary files /dev/null and b/AvoidTimeComsume/entry/src/main/resources/base/media/background.png differ diff --git a/AvoidTimeComsume/entry/src/main/resources/base/media/chevron_left.png b/AvoidTimeComsume/entry/src/main/resources/base/media/chevron_left.png new file mode 100644 index 0000000000000000000000000000000000000000..f609e3aee584d4aa479ad09a863aa3749ec5a3d0 Binary files /dev/null and b/AvoidTimeComsume/entry/src/main/resources/base/media/chevron_left.png differ diff --git a/AvoidTimeComsume/entry/src/main/resources/base/media/foreground.png b/AvoidTimeComsume/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 Binary files /dev/null and b/AvoidTimeComsume/entry/src/main/resources/base/media/foreground.png differ diff --git a/AvoidTimeComsume/entry/src/main/resources/base/media/layered_image.json b/AvoidTimeComsume/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/resources/base/media/startIcon.png b/AvoidTimeComsume/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/AvoidTimeComsume/entry/src/main/resources/base/media/startIcon.png differ diff --git a/AvoidTimeComsume/entry/src/main/resources/base/media/waterFlowTest0.png b/AvoidTimeComsume/entry/src/main/resources/base/media/waterFlowTest0.png new file mode 100644 index 0000000000000000000000000000000000000000..7143d98160a1937761b6b5024dd136207a3657c3 Binary files /dev/null and b/AvoidTimeComsume/entry/src/main/resources/base/media/waterFlowTest0.png differ diff --git a/AvoidTimeComsume/entry/src/main/resources/base/media/waterFlowTest1.png b/AvoidTimeComsume/entry/src/main/resources/base/media/waterFlowTest1.png new file mode 100644 index 0000000000000000000000000000000000000000..37af83960f7b5a2b5a8847384a2747ec424f7b29 Binary files /dev/null and b/AvoidTimeComsume/entry/src/main/resources/base/media/waterFlowTest1.png differ diff --git a/AvoidTimeComsume/entry/src/main/resources/base/media/waterFlowTest2.png b/AvoidTimeComsume/entry/src/main/resources/base/media/waterFlowTest2.png new file mode 100644 index 0000000000000000000000000000000000000000..da1925e66d3a40898f8a5bdc9a907f7183e45c34 Binary files /dev/null and b/AvoidTimeComsume/entry/src/main/resources/base/media/waterFlowTest2.png differ diff --git a/AvoidTimeComsume/entry/src/main/resources/base/profile/backup_config.json b/AvoidTimeComsume/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/resources/base/profile/main_pages.json b/AvoidTimeComsume/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..33506b6f351c4d44061fd76bf803dc8d1bffd933 --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,20 @@ +{ + "src": [ + "pages/Index", + "views/RedundantOperation", + "views/NoRedundantOperation", + "views/NegativeOfGrid", + "views/PositiveOfGrid", + "views/NegativeOfLazyForEach", + "views/PositiveOfLazyForEach", + "views/NegativeOfProperty", + "views/PositiveOfProperty", + "views/GetStrOfResource", + "views/GetStrOfId", + "views/UseAsync", + "views/UseTaskPool", + "views/NegativeOfOnScroll", + "views/PositiveOfOnScroll", + "views/ConditionalRendering" + ] +} diff --git a/AvoidTimeComsume/entry/src/main/resources/en_US/element/string.json b/AvoidTimeComsume/entry/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..aca2433bc6038fe3be7b43f09b1127c39966324a --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/resources/en_US/element/string.json @@ -0,0 +1,80 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "Main Thread Time-consuming Operations Optimization Guide" + }, + { + "name": "test", + "value": "test" + }, + { + "name": "redundant_operation", + "value": "Redundant operations" + }, + { + "name": "no_redundant_operation", + "value": "No redundant operations" + }, + { + "name": "negative_of_grid", + "value": "Component reuse counterexample" + }, + { + "name": "positive_of_grid", + "value": "Component reuse examples" + }, + { + "name": "negative_of_lazy_forEach", + "value": "Loop rendering counterexamples" + }, + { + "name": "positive_of_lazy_forEach", + "value": "Circular rendering normal" + }, + { + "name": "negative_of_property", + "value": "Component property counterexamples" + }, + { + "name": "positive_of_property", + "value": "Component property examples" + }, + { + "name": "get_str_of_resource", + "value": "Through resource objects" + }, + { + "name": "get_str_of_id", + "value": "By resource ID" + }, + { + "name": "use_async", + "value": "Use asynchronous" + }, + { + "name": "use_task_pool", + "value": "Use multithreading" + }, + { + "name": "negative_of_onScroll", + "value": "High-frequency event callbacks perform time-consuming operations" + }, + { + "name": "positive_of_onScroll", + "value": "High-frequency event callbacks do not perform time-consuming operations" + }, + { + "name": "conditional_rendering", + "value": "Conditional rendering" + } + ] +} \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/resources/rawfile/data.json b/AvoidTimeComsume/entry/src/main/resources/rawfile/data.json new file mode 100644 index 0000000000000000000000000000000000000000..f3872a82af173c87c52dde4a8fdc379d1b28911e --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/resources/rawfile/data.json @@ -0,0 +1,24 @@ +{ + "data": [ + { + "id": 0, + "name": "item0", + "url": "xxxx0" + }, + { + "id": 1, + "name": "item1", + "url": "xxxx1" + }, + { + "id": 2, + "name": "item2", + "url": "xxxx2" + }, + { + "id": 3, + "name": "item3", + "url": "xxxx3" + } + ] +} \ No newline at end of file diff --git a/AvoidTimeComsume/entry/src/main/resources/zh_CN/element/string.json b/AvoidTimeComsume/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..d0b3aa80c4f283a7228911620e6dbc27be9e3caf --- /dev/null +++ b/AvoidTimeComsume/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,80 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "主线程耗时操作优化指导" + }, + { + "name": "test", + "value": "test" + }, + { + "name": "redundant_operation", + "value": "含有冗余操作" + }, + { + "name": "no_redundant_operation", + "value": "不含有冗余操作" + }, + { + "name": "negative_of_grid", + "value": "组件复用反例" + }, + { + "name": "positive_of_grid", + "value": "组件复用正例" + }, + { + "name": "negative_of_lazy_forEach", + "value": "循环渲染反例" + }, + { + "name": "positive_of_lazy_forEach", + "value": "循环渲染正例" + }, + { + "name": "negative_of_property", + "value": "组件属性反例" + }, + { + "name": "positive_of_property", + "value": "组件属性正例" + }, + { + "name": "get_str_of_resource", + "value": "通过资源对象" + }, + { + "name": "get_str_of_id", + "value": "通过资源ID" + }, + { + "name": "use_async", + "value": "使用异步" + }, + { + "name": "use_task_pool", + "value": "使用多线程" + }, + { + "name": "negative_of_onScroll", + "value": "高频事件回调执行耗时操作" + }, + { + "name": "positive_of_onScroll", + "value": "高频事件回调不执行耗时操作" + }, + { + "name": "conditional_rendering", + "value": "条件渲染" + } + ] +} \ No newline at end of file diff --git a/AvoidTimeComsume/hvigor/hvigor-config.json5 b/AvoidTimeComsume/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..06b2783670a348f95533b352c1ceda909a842bbc --- /dev/null +++ b/AvoidTimeComsume/hvigor/hvigor-config.json5 @@ -0,0 +1,22 @@ +{ + "modelVersion": "5.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/AvoidTimeComsume/hvigorfile.ts b/AvoidTimeComsume/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..f3cb9f1a87a81687554a76283af8df27d8bda775 --- /dev/null +++ b/AvoidTimeComsume/hvigorfile.ts @@ -0,0 +1,6 @@ +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/AvoidTimeComsume/local.properties b/AvoidTimeComsume/local.properties new file mode 100644 index 0000000000000000000000000000000000000000..20f608699522ce5b5f170457336fbfbf96165c62 --- /dev/null +++ b/AvoidTimeComsume/local.properties @@ -0,0 +1,9 @@ +# This file is automatically generated by DevEco Studio. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file should *NOT* be checked into Version Control Systems, +# as it contains information specific to your local configuration. +# +# For customization when using a Version Control System, please read the header note. + + diff --git a/AvoidTimeComsume/oh-package.json5 b/AvoidTimeComsume/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..8bf916d4a165e0466c65bc49f58ab2e3c27e8931 --- /dev/null +++ b/AvoidTimeComsume/oh-package.json5 @@ -0,0 +1,8 @@ +{ + "modelVersion": "5.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + } +} diff --git a/AvoidTimeComsume/screenshots/output-15_53_54.gif b/AvoidTimeComsume/screenshots/output-15_53_54.gif new file mode 100644 index 0000000000000000000000000000000000000000..42fc9bd5c53efbab0f801c76f336e4b440e5ecdb Binary files /dev/null and b/AvoidTimeComsume/screenshots/output-15_53_54.gif differ diff --git a/README.md b/README.md index e8bd566cf5b2cc677b94da4cf4d5a6ce1eda97d6..b20937e3d4c0347cb35ce68d3533cf97f4d0f603 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ * [AppPrivacyProtection:应用隐私保护](AppPrivacyProtection) * [MultiWindowPractice: 智慧多窗开发实践](MultiWindowPractice) * [PreHttpRequestUseFiles:Image白块解决指导](PreHttpRequestUseFiles) +* [AvoidTimeComsume:主线程耗时操作优化指导](AvoidTimeComsume) ## 使用说明