已开启
feat: add MultiThreadIO 多线程I/O实践示例(纯仓颉实现) #422
stwilliam503388创建于 10 天前
feat: add MultiThreadIO 多线程I/O实践示例(纯仓颉实现) #422
已开启
共 37 个文件变更+1137-0
| @@ -0,0 +1,18 @@ | |||
| 1 | +/node_modules | ||
| 2 | +/oh_modules | ||
| 3 | +/local.properties | ||
| 4 | +/.idea | ||
| 5 | +**/build | ||
| 6 | +/.hvigor | ||
| 7 | +.cxx | ||
| 8 | +/.clangd | ||
| 9 | +/.clang-format | ||
| 10 | +/.clang-tidy | ||
| 11 | +**/.test | ||
| 12 | +/.appanalyzer | ||
| 13 | +**/cj_res | ||
| 14 | +**/*.cj.macrocall | ||
| 15 | +**/ability_mainability_entry.cj | ||
| 16 | +**/module_**_entry.cj | ||
| 17 | +**/IDL_Dependencies_List~ | ||
| 18 | +**/build-script-cache | ||
| @@ -0,0 +1,10 @@ | |||
| 1 | +{ | ||
| 2 | + "app": { | ||
| 3 | + "bundleName": "com.huawei.multithreadio", | ||
| 4 | + "vendor": "example", | ||
| 5 | + "versionCode": 1000000, | ||
| 6 | + "versionName": "1.0.0", | ||
| 7 | + "icon": "$media:layered_image", | ||
| 8 | + "label": "$string:app_name" | ||
| 9 | + } | ||
| 10 | +} | ||
| @@ -0,0 +1,8 @@ | |||
| 1 | +{ | ||
| 2 | + "string": [ | ||
| 3 | + { | ||
| 4 | + "name": "app_name", | ||
| 5 | + "value": "MultiThreadIO" | ||
| 6 | + } | ||
| 7 | + ] | ||
| 8 | +} | ||
| @@ -0,0 +1,7 @@ | |||
| 1 | +{ | ||
| 2 | + "layered-image": | ||
| 3 | + { | ||
| 4 | + "background" : "$media:background", | ||
| 5 | + "foreground" : "$media:foreground" | ||
| 6 | + } | ||
| 7 | +} | ||
| @@ -0,0 +1,153 @@ | |||
| 1 | +# MultiThreadIO - 多线程 I/O 实践示例(纯仓颉语言实现) | ||
| 2 | + | ||
| 3 | +> 基于 Cangjie(仓颉)编程语言的 HarmonyOS 多线程 I/O 实践示例,对应华为开发者文档:[多线程IO](https://developer.huawei.com/consumer/cn/doc/cangjie-practices/multithreadio) | ||
| 4 | + | ||
| 5 | +## 场景介绍 | ||
| 6 | + | ||
| 7 | +I/O 密集型任务(批量文件读写、数据库批量写入)是应用开发中最容易阻塞 UI 线程的场景之一。本示例演示在仓颉中使用 **`spawn` 轻量线程** 并发完成文件读写与关系型数据库(RDB)操作,并通过进度条实时反馈任务执行进度,任务期间 UI 仍可正常响应。 | ||
| 8 | + | ||
| 9 | +核心目标: | ||
| 10 | +- 理解仓颉 `spawn` / `Future` 并发模型的使用方法 | ||
| 11 | +- 掌握 I/O 密集型任务(文件读写、数据库批量写入)的多线程优化 | ||
| 12 | +- 实践子线程与 ArkUI 主线程之间的协作(`launch` 回主线程更新 UI) | ||
| 13 | +- 学习共享状态的线程安全保护(`Mutex` + `synchronized`) | ||
| 14 | + | ||
| 15 | +## 效果预览 | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +## 实现思路 | ||
| 20 | + | ||
| 21 | +### 1. spawn 轻量线程 + Future 任务收集 | ||
| 22 | + | ||
| 23 | +`spawn` 表达式启动一个轻量线程并立即返回 `Future<T>`。文件写入将 30 个写入任务并发派发,统一收集到 `ArrayList<Future<Unit>>` 中: | ||
| 24 | + | ||
| 25 | +```cangjie | ||
| 26 | +public func writeFile(content: String, onProgress: (Float64) -> Unit, onFinish: () -> Unit) { | ||
| 27 | + let path = Global.abilityContext.filesDir | ||
| 28 | + let allTasks = ArrayList<Future<Unit>>() | ||
| 29 | + for (i in 0..all) { | ||
| 30 | + let task = spawn { | ||
| 31 | + let fileName = "${path}${CommonConstants.FILE_PREFIX}${i}${CommonConstants.FILE_SUFFIX}" | ||
| 32 | + let file = FileIo.open(fileName, mode: OpenMode.READ_WRITE | OpenMode.CREATE) | ||
| 33 | + FileIo.write(file.fd, content) | ||
| 34 | + FileIo.close(file) | ||
| 35 | + launch { | ||
| 36 | + onProgress(100.0 / Float64(all)) | ||
| 37 | + } | ||
| 38 | + } | ||
| 39 | + allTasks.add(task) | ||
| 40 | + } | ||
| 41 | + // 监视线程:等待全部任务完成后回调 | ||
| 42 | + spawn { | ||
| 43 | + for (task in allTasks) { | ||
| 44 | + task.get() | ||
| 45 | + } | ||
| 46 | + onFinish() | ||
| 47 | + } | ||
| 48 | +} | ||
| 49 | +``` | ||
| 50 | + | ||
| 51 | +### 2. launch 回主线程更新 UI | ||
| 52 | + | ||
| 53 | +子线程中不能直接操作 UI 状态。`launch` 表达式将闭包调度回主上下文执行,因此进度回调和 Toast 提示都通过 `launch` 包裹: | ||
| 54 | + | ||
| 55 | +```cangjie | ||
| 56 | +writeFile(this.content, { progress => | ||
| 57 | + synchronized(mtx) { | ||
| 58 | + this.progress += progress // 多个子线程并发累加,需加锁保护 | ||
| 59 | + } | ||
| 60 | +}) { | ||
| 61 | + this.disabled = false | ||
| 62 | + launch { this.showToast(@r(app.string.success_remind)) } | ||
| 63 | +} | ||
| 64 | +``` | ||
| 65 | + | ||
| 66 | +### 3. Mutex 保护共享进度状态 | ||
| 67 | + | ||
| 68 | +30 个子线程并发回调进度时,`this.progress` 累加存在数据竞争,使用 `std.sync.Mutex` + `synchronized` 串行化: | ||
| 69 | + | ||
| 70 | +```cangjie | ||
| 71 | +let mtx = Mutex() | ||
| 72 | +// ... | ||
| 73 | +synchronized(mtx) { | ||
| 74 | + this.progress += progress | ||
| 75 | +} | ||
| 76 | +``` | ||
| 77 | + | ||
| 78 | +### 4. 关系型数据库批量写入 | ||
| 79 | + | ||
| 80 | +使用 ArkData Kit 的 RDB,一次 `batchInsert` 批量写入 1000 行 EMPLOYEE 数据,写入也在子线程中执行: | ||
| 81 | + | ||
| 82 | +```cangjie | ||
| 83 | +let STORE_CONFIG = StoreConfig(RelationalStoreSecurityLevel.S1, name: "RDB2.db") | ||
| 84 | + | ||
| 85 | +public func writeDatabase(onFinish: () -> Unit) { | ||
| 86 | + spawn { | ||
| 87 | + let rdbStore = getRdbStore(Global.abilityContext, STORE_CONFIG) | ||
| 88 | + rdbStore.executeSql(CommonConstants.SQL_CREATE) | ||
| 89 | + let valueBucketArray = Array<Map<String, RelationalStoreValueType>>(1000) { index => | ||
| 90 | + let map = HashMap<String, RelationalStoreValueType>() | ||
| 91 | + map.add("NAME", RelationalStoreValueType.StringValue("LISA")) | ||
| 92 | + map.add("AGE", RelationalStoreValueType.Integer(15)) | ||
| 93 | + map.add("SALARY", RelationalStoreValueType.Double(100.5)) | ||
| 94 | + map | ||
| 95 | + } | ||
| 96 | + rdbStore.batchInsert("EMPLOYEE", valueBucketArray) | ||
| 97 | + onFinish() | ||
| 98 | + } | ||
| 99 | +} | ||
| 100 | +``` | ||
| 101 | + | ||
| 102 | +### 5. 资源与本地化 | ||
| 103 | + | ||
| 104 | +- UI 文案全部通过 `@r(app.string.xxx)` 资源引用(LocalizationKit),支持多语言 | ||
| 105 | +- 测试数据在 `aboutToAppear` 中通过 `Global.resourceManager.getRawFileContent` 从 rawfile 读取,避免硬编码大字符串 | ||
| 106 | + | ||
| 107 | +## 功能特性 | ||
| 108 | + | ||
| 109 | +- ✅ 多线程写文件(30 个并发写入任务,进度条实时反馈) | ||
| 110 | +- ✅ 多线程读文件(并发读取并汇总字节内容) | ||
| 111 | +- ✅ 多线程写数据库(RDB 批量插入 1000 行) | ||
| 112 | +- ✅ 多线程读数据库(`RdbPredicates` 查询并回传结果) | ||
| 113 | +- ✅ 任务执行期间按钮防重入(`disabled` 状态互斥) | ||
| 114 | +- ✅ 子线程结果安全回传主线程(`launch`) | ||
| 115 | +- ✅ 共享状态加锁保护(`Mutex` + `synchronized`) | ||
| 116 | + | ||
| 117 | +## 环境要求 | ||
| 118 | + | ||
| 119 | +- DevEco Studio(含 Cangjie 支持) | ||
| 120 | +- HarmonyOS SDK 6.0.2(22),API Level 22 | ||
| 121 | +- 仓颉语言插件(DevEco Studio 内安装) | ||
| 122 | + | ||
| 123 | +## 使用说明 | ||
| 124 | + | ||
| 125 | +1. 用 DevEco Studio 打开本目录,等待仓颉依赖解析完成 | ||
| 126 | +2. 运行应用后,依次点击「写文件 → 读文件 → 写数据库 → 读数据库」四个按钮 | ||
| 127 | +3. 文件任务执行时观察顶部线性进度条的实时推进;任务执行期间重复点击会收到「请等待任务完成」提示 | ||
| 128 | +4. 未写入数据时直接读取,会收到空数据提醒 | ||
| 129 | + | ||
| 130 | +## 工程目录 | ||
| 131 | + | ||
| 132 | +``` | ||
| 133 | +entry/src/main/cangjie/ | ||
| 134 | +├── index.cj # 主界面:标题/进度条/四个任务按钮与回调处理 | ||
| 135 | +├── main_ability.cj # Ability 生命周期管理 | ||
| 136 | +├── ability_stage.cj # Stage 模型配置 | ||
| 137 | +├── constants/CommonConstants.cj # 公共常量(文件名前后缀、SQL 语句、时长等) | ||
| 138 | +├── global/Global.cj # 全局上下文(abilityContext / resourceManager) | ||
| 139 | +└── utils/ | ||
| 140 | + ├── FileUtils.cj # 文件读写(spawn + Future 并发实现) | ||
| 141 | + └── DatabaseUtils.cj # RDB 读写(子线程批量写入/查询) | ||
| 142 | +``` | ||
| 143 | + | ||
| 144 | +## 难点与踩坑记录 | ||
| 145 | + | ||
| 146 | +- 子线程中不能直接更新 UI 状态:进度回调与 Toast 都必须经 `launch` 回到主上下文执行 | ||
| 147 | +- 多线程并发累加进度存在数据竞争:`this.progress += progress` 必须用 `synchronized(mtx)` 包裹 | ||
| 148 | +- 数据库连接的线程安全:写入操作收敛到单个 `spawn` 块内串行执行,避免并发写同一 RDB 实例 | ||
| 149 | +- 任务防重入:按钮点击后置 `disabled`,任务完成回调中复位,避免重复派发任务 | ||
| 150 | + | ||
| 151 | +## 原项目 | ||
| 152 | + | ||
| 153 | +本项目源自个人原创仓库:[MultiThreadIO](https://github.com/stwilliam503388-creator/MultiThreadIO) | ||
| @@ -0,0 +1,42 @@ | |||
| 1 | +{ | ||
| 2 | + "app": { | ||
| 3 | + "signingConfigs": [], | ||
| 4 | + "products": [ | ||
| 5 | + { | ||
| 6 | + "name": "default", | ||
| 7 | + "signingConfig": "default", | ||
| 8 | + "targetSdkVersion": "6.0.2(22)", | ||
| 9 | + "compatibleSdkVersion": "6.0.2(22)", | ||
| 10 | + "runtimeOS": "HarmonyOS", | ||
| 11 | + "buildOption": { | ||
| 12 | + "strictMode": { | ||
| 13 | + "caseSensitiveCheck": true, | ||
| 14 | + "useNormalizedOHMUrl": true | ||
| 15 | + } | ||
| 16 | + } | ||
| 17 | + } | ||
| 18 | + ], | ||
| 19 | + "buildModeSet": [ | ||
| 20 | + { | ||
| 21 | + "name": "debug", | ||
| 22 | + }, | ||
| 23 | + { | ||
| 24 | + "name": "release" | ||
| 25 | + } | ||
| 26 | + ] | ||
| 27 | + }, | ||
| 28 | + "modules": [ | ||
| 29 | + { | ||
| 30 | + "name": "entry", | ||
| 31 | + "srcPath": "./entry", | ||
| 32 | + "targets": [ | ||
| 33 | + { | ||
| 34 | + "name": "default", | ||
| 35 | + "applyToProducts": [ | ||
| 36 | + "default" | ||
| 37 | + ] | ||
| 38 | + } | ||
| 39 | + ] | ||
| 40 | + } | ||
| 41 | + ] | ||
| 42 | +} | ||
| @@ -0,0 +1,33 @@ | |||
| 1 | +{ | ||
| 2 | + "files": [ | ||
| 3 | + "**/*.ets", | ||
| 4 | + "**/*.cj" | ||
| 5 | + ], | ||
| 6 | + "ignore": [ | ||
| 7 | + "**/src/ohosTest/**/*", | ||
| 8 | + "**/src/test/**/*", | ||
| 9 | + "**/src/mock/**/*", | ||
| 10 | + "**/node_modules/**/*", | ||
| 11 | + "**/oh_modules/**/*", | ||
| 12 | + "**/build/**/*", | ||
| 13 | + "**/.preview/**/*" | ||
| 14 | + ], | ||
| 15 | + "ruleSet": [ | ||
| 16 | + "plugin:@performance/recommended", | ||
| 17 | + "plugin:@typescript-eslint/recommended" | ||
| 18 | + ], | ||
| 19 | + "rules": { | ||
| 20 | + "@security/no-unsafe-aes": "error", | ||
| 21 | + "@security/no-unsafe-hash": "error", | ||
| 22 | + "@security/no-unsafe-mac": "warn", | ||
| 23 | + "@security/no-unsafe-dh": "error", | ||
| 24 | + "@security/no-unsafe-dsa": "error", | ||
| 25 | + "@security/no-unsafe-ecdsa": "error", | ||
| 26 | + "@security/no-unsafe-rsa-encrypt": "error", | ||
| 27 | + "@security/no-unsafe-rsa-sign": "error", | ||
| 28 | + "@security/no-unsafe-rsa-key": "error", | ||
| 29 | + "@security/no-unsafe-dsa-key": "error", | ||
| 30 | + "@security/no-unsafe-dh-key": "error", | ||
| 31 | + "@security/no-unsafe-3des": "error" | ||
| 32 | + } | ||
| 33 | +} | ||
| @@ -0,0 +1,8 @@ | |||
| 1 | +/node_modules | ||
| 2 | +/oh_modules | ||
| 3 | +/.preview | ||
| 4 | +/build | ||
| 5 | +/.cxx | ||
| 6 | +/.test | ||
| 7 | +**/IDL_Dependencies_List~ | ||
| 8 | +**/build-script-cache | ||
| @@ -0,0 +1,23 @@ | |||
| 1 | +{ | ||
| 2 | + "apiType": "stageMode", | ||
| 3 | + "buildOption": { | ||
| 4 | + "cangjieOptions": { | ||
| 5 | + "path": "./cjpm.toml", | ||
| 6 | + "abiFilters": [ | ||
| 7 | + "arm64-v8a" | ||
| 8 | + ] | ||
| 9 | + }, | ||
| 10 | + "nativeLib": { | ||
| 11 | + "filter": { | ||
| 12 | + "enableOverride": true | ||
| 13 | + } | ||
| 14 | + } | ||
| 15 | + }, | ||
| 16 | + "buildOptionSet": [ | ||
| 17 | + ], | ||
| 18 | + "targets": [ | ||
| 19 | + { | ||
| 20 | + "name": "default" | ||
| 21 | + } | ||
| 22 | + ] | ||
| 23 | +} | ||
| @@ -0,0 +1,36 @@ | |||
| 1 | +[package] | ||
| 2 | + cjc-version = "0.48.2" | ||
| 3 | + compile-option = "--dy-std --cfg=\"${COMPILE_CONDITION_ENTRY}\"" | ||
| 4 | + description = "CangjieUI Application" | ||
| 5 | + link-option = "" | ||
| 6 | + name = "ohos_app_cangjie_entry" | ||
| 7 | + output-type = "dynamic" | ||
| 8 | + src-dir = "./src/main/cangjie" | ||
| 9 | + target-dir = "" | ||
| 10 | + version = "1.0.0" | ||
| 11 | + package-configuration = {} | ||
| 12 | + scripts = {} | ||
| 13 | + | ||
| 14 | +[profile] | ||
| 15 | + [profile.build] | ||
| 16 | + incremental = true | ||
| 17 | + lto = "" | ||
| 18 | + [profile.customized-option] | ||
| 19 | + debug = "-g -Woff all -Won apilevel-check" | ||
| 20 | + release = "--fast-math -O2 -s -Woff all -Won apilevel-check" | ||
| 21 | + [profile.test] | ||
| 22 | + | ||
| 23 | +[target.aarch64-linux-ohos] | ||
| 24 | + compile-option = "-B \"${DEVECO_CANGJIE_HOME}/build-tools/third_party/llvm/bin\" -B \"${DEVECO_OH_NATIVE_HOME}/sysroot/usr/lib/aarch64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/sysroot/usr/lib/aarch64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/llvm/lib/clang/15.0.4/lib/aarch64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/llvm/lib/aarch64-linux-ohos\" --sysroot \"${DEVECO_OH_NATIVE_HOME}/sysroot\"" | ||
| 25 | +[target.aarch64-linux-ohos.bin-dependencies] | ||
| 26 | + path-option = ["${AARCH64_LIBS}", "${AARCH64_MACRO_LIBS}", "${AARCH64_KIT_LIBS}"] | ||
| 27 | + package-option = {} | ||
| 28 | + | ||
| 29 | +[target.x86_64-linux-ohos] | ||
| 30 | + compile-option = "-B \"${DEVECO_CANGJIE_HOME}/build-tools/third_party/llvm/bin\" -B \"${DEVECO_OH_NATIVE_HOME}/sysroot/usr/lib/x86_64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/sysroot/usr/lib/x86_64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/llvm/lib/clang/15.0.4/lib/x86_64-linux-ohos\" -L \"${DEVECO_OH_NATIVE_HOME}/llvm/lib/x86_64-linux-ohos\" --sysroot \"${DEVECO_OH_NATIVE_HOME}/sysroot\"" | ||
| 31 | +[target.x86_64-linux-ohos.bin-dependencies] | ||
| 32 | + path-option = ["${X86_64_OHOS_LIBS}", "${X86_64_OHOS_MACRO_LIBS}", "${X86_64_OHOS_KIT_LIBS}"] | ||
| 33 | + | ||
| 34 | +[target.x86_64-unknown-windows-gnu.bin-dependencies] | ||
| 35 | + path-option = ["${X86_64_LIBS}", "${X86_64_MACRO_LIBS}"] | ||
| 36 | + package-option = {} | ||
| @@ -0,0 +1,6 @@ | |||
| 1 | +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; | ||
| 2 | + | ||
| 3 | +export default { | ||
| 4 | + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ | ||
| 5 | + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ | ||
| 6 | +} | ||
| @@ -0,0 +1,10 @@ | |||
| 1 | +{ | ||
| 2 | + "name": "entry", | ||
| 3 | + "version": "1.0.0", | ||
| 4 | + "description": "Please describe the basic information.", | ||
| 5 | + "main": "", | ||
| 6 | + "author": "", | ||
| 7 | + "license": "", | ||
| 8 | + "dependencies": {} | ||
| 9 | +} | ||
| 10 | + | ||
| @@ -0,0 +1,25 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2025 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | +package ohos_app_cangjie_entry | ||
| 17 | + | ||
| 18 | +internal import ohos.app.ability.ability_stage.AbilityStage | ||
| 19 | +import kit.PerformanceAnalysisKit.Hilog | ||
| 20 | + | ||
| 21 | +class MyAbilityStage <: AbilityStage { | ||
| 22 | + public override func onCreate(): Unit { | ||
| 23 | + Hilog.info(1, "MyAbilityStage", "MyAbilityStage onCreated.") | ||
| 24 | + } | ||
| 25 | +} | ||
| @@ -0,0 +1,45 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2025 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | +package ohos_app_cangjie_entry.constants | ||
| 17 | + | ||
| 18 | +public class CommonConstants { | ||
| 19 | + /** | ||
| 20 | + * Toast duration time. | ||
| 21 | + */ | ||
| 22 | + public static const DURATION_TIME: UInt32 = 2000 | ||
| 23 | + /** | ||
| 24 | + * File name. | ||
| 25 | + */ | ||
| 26 | + public static const FILE_NAME: String = 'test.txt' | ||
| 27 | + /** | ||
| 28 | + * Encoding. | ||
| 29 | + */ | ||
| 30 | + public static const ENCODING: String = 'utf-8' | ||
| 31 | + /** | ||
| 32 | + * Create SQL. | ||
| 33 | + */ | ||
| 34 | + public static const SQL_CREATE: String = | ||
| 35 | + 'CREATE TABLE IF NOT EXISTS EMPLOYEE (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, AGE INTEGER, ' + | ||
| 36 | + 'SALARY REAL)' | ||
| 37 | + /** | ||
| 38 | + * File suffix. | ||
| 39 | + */ | ||
| 40 | + public static const FILE_SUFFIX: String = '.txt' | ||
| 41 | + /** | ||
| 42 | + * File prefix. | ||
| 43 | + */ | ||
| 44 | + public static const FILE_PREFIX: String = '/file' | ||
| 45 | +} | ||
| @@ -0,0 +1,34 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2025 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | +package ohos_app_cangjie_entry.global | ||
| 17 | + | ||
| 18 | +import ohos.app.ability.ui_ability.UIAbilityContext | ||
| 19 | +import ohos.resource_manager.ResourceManager | ||
| 20 | + | ||
| 21 | +public class Global { | ||
| 22 | + public static var _abilityContext: ?UIAbilityContext = None | ||
| 23 | + public static prop abilityContext: UIAbilityContext { | ||
| 24 | + get() { | ||
| 25 | + _abilityContext.getOrThrow() | ||
| 26 | + } | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + public static prop resourceManager: ResourceManager { | ||
| 30 | + get() { | ||
| 31 | + abilityContext.resourceManager | ||
| 32 | + } | ||
| 33 | + } | ||
| 34 | +} | ||
| @@ -0,0 +1,153 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2025 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | +package ohos_app_cangjie_entry | ||
| 17 | + | ||
| 18 | +import kit.ArkUI.* | ||
| 19 | +import ohos.arkui.state_management.* | ||
| 20 | +import ohos.base.* | ||
| 21 | +import ohos.arkui.state_macro_manage.* | ||
| 22 | +import ohos.resource.AppResource | ||
| 23 | +import ohos.arkui.ui_context.* | ||
| 24 | +import ohos_app_cangjie_entry.utils.* | ||
| 25 | +import std.sync.Mutex | ||
| 26 | +import ohos_app_cangjie_entry.constants.* | ||
| 27 | +import ohos_app_cangjie_entry.global.Global | ||
| 28 | +import ohos.resource.__GenerateResource__ | ||
| 29 | + | ||
| 30 | +let mtx = Mutex() | ||
| 31 | + | ||
| 32 | +@Entry | ||
| 33 | +@Component | ||
| 34 | +class EntryView { | ||
| 35 | + @State var disabled: Bool = false | ||
| 36 | + @State var content: String = '' | ||
| 37 | + @State var progress: Float64 = 0.0 | ||
| 38 | + | ||
| 39 | + func showToast(content: String) { | ||
| 40 | + getUIContext() | ||
| 41 | + .getPromptAction() | ||
| 42 | + .showToast(ShowToastOptions(message: content, duration: CommonConstants.DURATION_TIME)) | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + func showToast(resource: AppResource) { | ||
| 46 | + getUIContext() | ||
| 47 | + .getPromptAction() | ||
| 48 | + .showToast( | ||
| 49 | + ShowToastOptions(message: Global.resourceManager.getString(resource.id), duration: CommonConstants.DURATION_TIME)) | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + public func aboutToAppear() { | ||
| 53 | + let value = Global.resourceManager.getRawFileContent(CommonConstants.FILE_NAME) | ||
| 54 | + this.content = String.fromUtf8(value) | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + @Builder | ||
| 58 | + func MyButtonBuilder(title: AppResource, onClick: (ClickEvent) -> Unit) { | ||
| 59 | + Button(title) | ||
| 60 | + .width(100.percent) | ||
| 61 | + .margin(top: 12) | ||
| 62 | + .onClick ({ ctx => | ||
| 63 | + if (this.disabled) { | ||
| 64 | + this.showToast(@r(app.string.remind)) | ||
| 65 | + return | ||
| 66 | + } | ||
| 67 | + this.showToast(@r(app.string.start_remind)) | ||
| 68 | + onClick(ctx) | ||
| 69 | + }) | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + func build() { | ||
| 73 | + Flex(direction: FlexDirection.Column, justifyContent: FlexAlign.SpaceBetween) { | ||
| 74 | + Text(@r(app.string.title)) | ||
| 75 | + .fontSize(30) | ||
| 76 | + .textAlign(TextAlign.Start) | ||
| 77 | + .width(100.percent) | ||
| 78 | + .fontWeight(FontWeight.Bold) | ||
| 79 | + .padding( | ||
| 80 | + top: 56, | ||
| 81 | + left: 16, | ||
| 82 | + right: 16 | ||
| 83 | + ) | ||
| 84 | + | ||
| 85 | + Progress(value: this.progress, progressType: ProgressType.Linear) | ||
| 86 | + .width(100.percent) | ||
| 87 | + .padding( | ||
| 88 | + left: 16, | ||
| 89 | + right: 16 | ||
| 90 | + ) | ||
| 91 | + | ||
| 92 | + Column() { | ||
| 93 | + MyButtonBuilder(@r(app.string.button_name_1), { ctx => | ||
| 94 | + this.disabled = true | ||
| 95 | + this.progress = 0.0 | ||
| 96 | + writeFile(this.content, { progress => | ||
| 97 | + synchronized(mtx) { | ||
| 98 | + this.progress += progress | ||
| 99 | + } | ||
| 100 | + }) { | ||
| 101 | + this.disabled = false | ||
| 102 | + launch { this.showToast(@r(app.string.success_remind)) } | ||
| 103 | + } | ||
| 104 | + }) | ||
| 105 | + | ||
| 106 | + MyButtonBuilder(@r(app.string.button_name_2), { ctx => | ||
| 107 | + this.disabled = true | ||
| 108 | + this.progress = 0.0 | ||
| 109 | + readFile({ progress => | ||
| 110 | + synchronized(mtx) { | ||
| 111 | + this.progress += progress | ||
| 112 | + } | ||
| 113 | + }) { result => | ||
| 114 | + this.disabled = false | ||
| 115 | + if (result.size == 0) { | ||
| 116 | + launch { this.showToast(@r(app.string.empty_remind)) } | ||
| 117 | + return | ||
| 118 | + } | ||
| 119 | + launch { this.showToast(@r(app.string.success_remind)) } | ||
| 120 | + } | ||
| 121 | + }) | ||
| 122 | + | ||
| 123 | + MyButtonBuilder(@r(app.string.button_name_3), { ctx => | ||
| 124 | + this.disabled = true | ||
| 125 | + writeDatabase { => | ||
| 126 | + this.disabled = false | ||
| 127 | + launch { this.showToast(@r(app.string.success_remind)) } | ||
| 128 | + } | ||
| 129 | + }) | ||
| 130 | + | ||
| 131 | + MyButtonBuilder(@r(app.string.button_name_4), { ctx => | ||
| 132 | + this.disabled = true | ||
| 133 | + readDatabase { result => | ||
| 134 | + this.disabled = false | ||
| 135 | + if (result.size == 0) { | ||
| 136 | + launch { this.showToast(@r(app.string.empty_remind)) } | ||
| 137 | + return | ||
| 138 | + } | ||
| 139 | + launch { this.showToast(@r(app.string.success_remind)) } | ||
| 140 | + } | ||
| 141 | + }) | ||
| 142 | + } | ||
| 143 | + .width(100.percent) | ||
| 144 | + .padding( | ||
| 145 | + left: 16, | ||
| 146 | + right: 16 | ||
| 147 | + ) | ||
| 148 | + .alignSelf(ItemAlign.End) | ||
| 149 | + } | ||
| 150 | + .width(100.percent) | ||
| 151 | + .height(100.percent) | ||
| 152 | + } | ||
| 153 | +} | ||
| @@ -0,0 +1,45 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2025 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | +package ohos_app_cangjie_entry | ||
| 17 | + | ||
| 18 | +internal import ohos.hilog.* | ||
| 19 | +internal import ohos.app.ability.want.Want | ||
| 20 | +internal import ohos.app.ability.ui_ability.UIAbility | ||
| 21 | +internal import ohos.app.ability.ability_constant.LaunchParam | ||
| 22 | +internal import ohos.app.ability.ability_constant.LaunchReason | ||
| 23 | +internal import ohos.window.WindowStage | ||
| 24 | +import ohos_app_cangjie_entry.global.Global | ||
| 25 | + | ||
| 26 | +class MainAbility <: UIAbility { | ||
| 27 | + public init() { | ||
| 28 | + super() | ||
| 29 | + registerSelf() | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + public override func onCreate(want: Want, launchParam: LaunchParam): Unit { | ||
| 33 | + Hilog.info(1, "MainAbility", "MainAbility OnCreated.${want.abilityName}") | ||
| 34 | + match (launchParam.launchReason) { | ||
| 35 | + case LaunchReason.StartAbility => Hilog.info(1, "MainAbility", "START_ABILITY") | ||
| 36 | + case _ => () | ||
| 37 | + } | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + public override func onWindowStageCreate(windowStage: WindowStage): Unit { | ||
| 41 | + Global._abilityContext = this.context | ||
| 42 | + Hilog.info(1, "MainAbility", "MainAbility onWindowStageCreate.") | ||
| 43 | + windowStage.loadContent("EntryView") | ||
| 44 | + } | ||
| 45 | +} | ||
| @@ -0,0 +1,67 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2025 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | +package ohos_app_cangjie_entry.utils | ||
| 17 | + | ||
| 18 | +import std.collection.{ArrayList, Map, HashMap} | ||
| 19 | +import kit.ArkData.* | ||
| 20 | +import ohos_app_cangjie_entry.constants.CommonConstants | ||
| 21 | +import ohos_app_cangjie_entry.global.Global | ||
| 22 | +import ohos.business_exception.BusinessException | ||
| 23 | + | ||
| 24 | +let STORE_CONFIG = StoreConfig(RelationalStoreSecurityLevel.S1, name: "RDB2.db") | ||
| 25 | + | ||
| 26 | +public func writeDatabase(onFinish: () -> Unit) { | ||
| 27 | + spawn { | ||
| 28 | + let rdbStore = getRdbStore(Global.abilityContext, STORE_CONFIG) | ||
| 29 | + rdbStore.executeSql(CommonConstants.SQL_CREATE) | ||
| 30 | + let valueBucketArray = Array<Map<String, RelationalStoreValueType>>(1000) { index => | ||
| 31 | + let map = HashMap<String, RelationalStoreValueType>() | ||
| 32 | + map.add("NAME", RelationalStoreValueType.StringValue("LISA")) | ||
| 33 | + map.add("AGE", RelationalStoreValueType.Integer(15)) | ||
| 34 | + map.add("SALARY", RelationalStoreValueType.Double(100.5)) | ||
| 35 | + map | ||
| 36 | + } | ||
| 37 | + rdbStore.batchInsert("EMPLOYEE", valueBucketArray) | ||
| 38 | + onFinish() | ||
| 39 | + } | ||
| 40 | +} | ||
| 41 | + | ||
| 42 | +public func readDatabase(onFinish: (ArrayList<Map<String, RelationalStoreValueType>>) -> Unit) { | ||
| 43 | + spawn { | ||
| 44 | + let rdbStore = getRdbStore(Global.abilityContext, STORE_CONFIG) | ||
| 45 | + rdbStore.executeSql(CommonConstants.SQL_CREATE) | ||
| 46 | + let resultSet = rdbStore.query(RdbPredicates("EMPLOYEE")) | ||
| 47 | + if (resultSet.rowCount == 0) { | ||
| 48 | + onFinish(ArrayList()) | ||
| 49 | + return | ||
| 50 | + } | ||
| 51 | + resultSet.goToFirstRow() | ||
| 52 | + let result = ArrayList<Map<String, RelationalStoreValueType>>() | ||
| 53 | + var hasNext: Bool = false | ||
| 54 | + do { | ||
| 55 | + result.add(resultSet.getRow()) | ||
| 56 | + try { | ||
| 57 | + resultSet.goToNextRow() | ||
| 58 | + hasNext = true | ||
| 59 | + } catch (e: BusinessException) { | ||
| 60 | + hasNext = false | ||
| 61 | + } | ||
| 62 | + } while (hasNext) | ||
| 63 | + resultSet.close() | ||
| 64 | + onFinish(result) | ||
| 65 | + return | ||
| 66 | + } | ||
| 67 | +} | ||
| @@ -0,0 +1,104 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2025 Huawei Device Co., Ltd. | ||
| 3 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + * you may not use this file except in compliance with the License. | ||
| 5 | + * You may obtain a copy of the License at | ||
| 6 | + * | ||
| 7 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + * | ||
| 9 | + * Unless required by applicable law or agreed to in writing, software | ||
| 10 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + * See the License for the specific language governing permissions and | ||
| 13 | + * limitations under the License. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | +package ohos_app_cangjie_entry.utils | ||
| 17 | + | ||
| 18 | +import std.collection.ArrayList | ||
| 19 | +import ohos_app_cangjie_entry.constants.CommonConstants | ||
| 20 | +import ohos.hilog.Hilog | ||
| 21 | +import kit.CoreFileKit.* | ||
| 22 | +import ohos.base.launch | ||
| 23 | +import ohos.business_exception.BusinessException | ||
| 24 | +import ohos_app_cangjie_entry.global.Global | ||
| 25 | + | ||
| 26 | +let all = 30 | ||
| 27 | + | ||
| 28 | +public func writeFile(content: String, onProgress: (Float64) -> Unit, onFinish: () -> Unit) { | ||
| 29 | + let path = Global.abilityContext.filesDir | ||
| 30 | + let allTasks = ArrayList<Future<Unit>>() | ||
| 31 | + for (i in 0..all) { | ||
| 32 | + let task = spawn { | ||
| 33 | + let fileName = "${path}${CommonConstants.FILE_PREFIX}${i}${CommonConstants.FILE_SUFFIX}" | ||
| 34 | + let file = FileIo.open(fileName, mode: OpenMode.READ_WRITE | OpenMode.CREATE) | ||
| 35 | + FileIo.write(file.fd, content) | ||
| 36 | + FileIo.close(file) | ||
| 37 | + launch { | ||
| 38 | + onProgress(100.0 / Float64(all)) | ||
| 39 | + } | ||
| 40 | + } | ||
| 41 | + allTasks.add(task) | ||
| 42 | + } | ||
| 43 | + spawn { | ||
| 44 | + for (task in allTasks) { | ||
| 45 | + task.get() | ||
| 46 | + } | ||
| 47 | + onFinish() | ||
| 48 | + } | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +public func readFile(onProgress: (Float64) -> Unit, onFinish: (ArrayList<ArrayList<UInt8>>) -> Unit) { | ||
| 52 | + let path = Global.abilityContext.filesDir | ||
| 53 | + let result = ArrayList<ArrayList<UInt8>>() | ||
| 54 | + let allTasks = ArrayList<Future<ArrayList<UInt8>>>() | ||
| 55 | + for (i in 0..all) { | ||
| 56 | + let task = spawn { | ||
| 57 | + let fileName = "${path}${CommonConstants.FILE_PREFIX}${i}${CommonConstants.FILE_SUFFIX}" | ||
| 58 | + let fileStat = FileIo.stat(fileName) | ||
| 59 | + let file = FileIo.open(fileName, mode: OpenMode.READ_ONLY) | ||
| 60 | + let result = ArrayList<UInt8>() | ||
| 61 | + var bufferSize = 1024 | ||
| 62 | + let buffer = Array<UInt8>(min(bufferSize, fileStat.size)) { _ => 1 } | ||
| 63 | + var len = try { | ||
| 64 | + Hilog.debug(0xff00, "MultiThread", "start read ${i}.") | ||
| 65 | + FileIo.read(file.fd, buffer, options: ReadOptions(length: UIntNative(bufferSize))) | ||
| 66 | + } catch (e: BusinessException) { | ||
| 67 | + Hilog.debug(0xff00, "MultiThread", "read ${i} error: ${e.code}, ${e.message}") | ||
| 68 | + 0 | ||
| 69 | + } | ||
| 70 | + var offset = 0 | ||
| 71 | + while (len > 0) { | ||
| 72 | + offset += len | ||
| 73 | + result.add(all: buffer) | ||
| 74 | + if (fileStat.size - offset < bufferSize) { | ||
| 75 | + bufferSize = fileStat.size - offset | ||
| 76 | + } | ||
| 77 | + len = try { | ||
| 78 | + FileIo.read(file.fd, buffer, options: ReadOptions(offset: offset, length: UIntNative(bufferSize))) | ||
| 79 | + } catch (e: BusinessException) { | ||
| 80 | + Hilog.debug(0xff00, "MultiThread", "read ${i} error: ${e.code}, ${e.message}") | ||
| 81 | + 0 | ||
| 82 | + } | ||
| 83 | + } | ||
| 84 | + FileIo.close(file) | ||
| 85 | + launch { | ||
| 86 | + onProgress(100.0 / Float64(all)) | ||
| 87 | + } | ||
| 88 | + Hilog.debug(0xff00, "MultiThread", "finish read: ${i}") | ||
| 89 | + result | ||
| 90 | + } | ||
| 91 | + allTasks.add(task) | ||
| 92 | + } | ||
| 93 | + spawn { | ||
| 94 | + for (task in allTasks) { | ||
| 95 | + try { | ||
| 96 | + result.add(task.get()) | ||
| 97 | + Hilog.debug(0xff00, "MultiThread", "got result") | ||
| 98 | + } catch (e: Exception) { | ||
| 99 | + Hilog.error(0xff00, "MultiThread", "error: ${e.message}") | ||
| 100 | + } | ||
| 101 | + } | ||
| 102 | + onFinish(result) | ||
| 103 | + } | ||
| 104 | +} | ||
| @@ -0,0 +1,36 @@ | |||
| 1 | +{ | ||
| 2 | + "module": { | ||
| 3 | + "name": "entry", | ||
| 4 | + "type": "entry", | ||
| 5 | + "description": "$string:module_desc", | ||
| 6 | + "mainElement": "EntryAbility", | ||
| 7 | + "deviceTypes": [ | ||
| 8 | + "phone" | ||
| 9 | + ], | ||
| 10 | + "deliveryWithInstall": true, | ||
| 11 | + "installationFree": false, | ||
| 12 | + "srcEntry": "ohos_app_cangjie_entry.MyAbilityStage", | ||
| 13 | + "abilities": [ | ||
| 14 | + { | ||
| 15 | + "name": "EntryAbility", | ||
| 16 | + "srcEntry": "ohos_app_cangjie_entry.MainAbility", | ||
| 17 | + "description": "$string:EntryAbility_desc", | ||
| 18 | + "icon": "$media:layered_image", | ||
| 19 | + "label": "$string:EntryAbility_label", | ||
| 20 | + "startWindowIcon": "$media:startIcon", | ||
| 21 | + "startWindowBackground": "$color:start_window_background", | ||
| 22 | + "exported": true, | ||
| 23 | + "skills": [ | ||
| 24 | + { | ||
| 25 | + "entities": [ | ||
| 26 | + "entity.system.home" | ||
| 27 | + ], | ||
| 28 | + "actions": [ | ||
| 29 | + "action.system.home" | ||
| 30 | + ] | ||
| 31 | + } | ||
| 32 | + ] | ||
| 33 | + } | ||
| 34 | + ] | ||
| 35 | + } | ||
| 36 | +} | ||
| @@ -0,0 +1,8 @@ | |||
| 1 | +{ | ||
| 2 | + "color": [ | ||
| 3 | + { | ||
| 4 | + "name": "start_window_background", | ||
| 5 | + "value": "#FFFFFF" | ||
| 6 | + } | ||
| 7 | + ] | ||
| 8 | +} | ||
| @@ -0,0 +1,68 @@ | |||
| 1 | +{ | ||
| 2 | + "string": [ | ||
| 3 | + { | ||
| 4 | + "name": "module_desc", | ||
| 5 | + "value": "module description" | ||
| 6 | + }, | ||
| 7 | + { | ||
| 8 | + "name": "EntryAbility_desc", | ||
| 9 | + "value": "description" | ||
| 10 | + }, | ||
| 11 | + { | ||
| 12 | + "name": "EntryAbility_label", | ||
| 13 | + "value": "MultiThreadIO" | ||
| 14 | + }, | ||
| 15 | + { | ||
| 16 | + "name": "title", | ||
| 17 | + "value": "Multi threaded operation intensive relational database and file read/write" | ||
| 18 | + }, | ||
| 19 | + { | ||
| 20 | + "name": "button_name_1", | ||
| 21 | + "value": "Multi Thread File-Write" | ||
| 22 | + }, | ||
| 23 | + { | ||
| 24 | + "name": "button_name_2", | ||
| 25 | + "value": "TaskPool File-Read" | ||
| 26 | + }, | ||
| 27 | + { | ||
| 28 | + "name": "button_name_3", | ||
| 29 | + "value": "Multi Thread DataBase-Write" | ||
| 30 | + }, | ||
| 31 | + { | ||
| 32 | + "name": "button_name_4", | ||
| 33 | + "value": "Multi Thread DataBase-Read" | ||
| 34 | + }, | ||
| 35 | + { | ||
| 36 | + "name": "button_name_5", | ||
| 37 | + "value": "TaskPool DataBase-Write" | ||
| 38 | + }, | ||
| 39 | + { | ||
| 40 | + "name": "button_name_6", | ||
| 41 | + "value": "TaskPool DataBase-Read" | ||
| 42 | + }, | ||
| 43 | + { | ||
| 44 | + "name": "button_name_7", | ||
| 45 | + "value": "@Sendable DataBase-Write" | ||
| 46 | + }, | ||
| 47 | + { | ||
| 48 | + "name": "button_name_8", | ||
| 49 | + "value": "@Sendable DataBase-Read" | ||
| 50 | + }, | ||
| 51 | + { | ||
| 52 | + "name": "remind", | ||
| 53 | + "value": "Please wait while executing the task." | ||
| 54 | + }, | ||
| 55 | + { | ||
| 56 | + "name": "success_remind", | ||
| 57 | + "value": "success" | ||
| 58 | + }, | ||
| 59 | + { | ||
| 60 | + "name": "empty_remind", | ||
| 61 | + "value": "Read content is empty, please write." | ||
| 62 | + }, | ||
| 63 | + { | ||
| 64 | + "name": "start_remind", | ||
| 65 | + "value": "Start executing the task" | ||
| 66 | + } | ||
| 67 | + ] | ||
| 68 | +} | ||
| @@ -0,0 +1,7 @@ | |||
| 1 | +{ | ||
| 2 | + "layered-image": | ||
| 3 | + { | ||
| 4 | + "background" : "$media:background", | ||
| 5 | + "foreground" : "$media:foreground" | ||
| 6 | + } | ||
| 7 | +} | ||
| @@ -0,0 +1,3 @@ | |||
| 1 | +{ | ||
| 2 | + "allowToBackupRestore": true | ||
| 3 | +} | ||
| @@ -0,0 +1,5 @@ | |||
| 1 | +{ | ||
| 2 | + "src": [ | ||
| 3 | + "pages/Index" | ||
| 4 | + ] | ||
| 5 | +} | ||
| @@ -0,0 +1,8 @@ | |||
| 1 | +{ | ||
| 2 | + "color": [ | ||
| 3 | + { | ||
| 4 | + "name": "start_window_background", | ||
| 5 | + "value": "#000000" | ||
| 6 | + } | ||
| 7 | + ] | ||
| 8 | +} | ||
| @@ -0,0 +1,68 @@ | |||
| 1 | +{ | ||
| 2 | + "string": [ | ||
| 3 | + { | ||
| 4 | + "name": "module_desc", | ||
| 5 | + "value": "module description" | ||
| 6 | + }, | ||
| 7 | + { | ||
| 8 | + "name": "EntryAbility_desc", | ||
| 9 | + "value": "description" | ||
| 10 | + }, | ||
| 11 | + { | ||
| 12 | + "name": "EntryAbility_label", | ||
| 13 | + "value": "MultiThreadIO" | ||
| 14 | + }, | ||
| 15 | + { | ||
| 16 | + "name": "title", | ||
| 17 | + "value": "Multi threaded operation intensive relational database and file read/write" | ||
| 18 | + }, | ||
| 19 | + { | ||
| 20 | + "name": "button_name_1", | ||
| 21 | + "value": "Multi Thread File-Write" | ||
| 22 | + }, | ||
| 23 | + { | ||
| 24 | + "name": "button_name_2", | ||
| 25 | + "value": "Multi Thread File-Read" | ||
| 26 | + }, | ||
| 27 | + { | ||
| 28 | + "name": "button_name_3", | ||
| 29 | + "value": "Multi Thread DataBase-Write" | ||
| 30 | + }, | ||
| 31 | + { | ||
| 32 | + "name": "button_name_4", | ||
| 33 | + "value": "Multi Thread DataBase-Read" | ||
| 34 | + }, | ||
| 35 | + { | ||
| 36 | + "name": "button_name_5", | ||
| 37 | + "value": "TaskPool DataBase-Write" | ||
| 38 | + }, | ||
| 39 | + { | ||
| 40 | + "name": "button_name_6", | ||
| 41 | + "value": "TaskPool DataBase-Read" | ||
| 42 | + }, | ||
| 43 | + { | ||
| 44 | + "name": "button_name_7", | ||
| 45 | + "value": "@Sendable DataBase-Write" | ||
| 46 | + }, | ||
| 47 | + { | ||
| 48 | + "name": "button_name_8", | ||
| 49 | + "value": "@Sendable DataBase-Read" | ||
| 50 | + }, | ||
| 51 | + { | ||
| 52 | + "name": "remind", | ||
| 53 | + "value": "Please wait while executing the task." | ||
| 54 | + }, | ||
| 55 | + { | ||
| 56 | + "name": "success_remind", | ||
| 57 | + "value": "success" | ||
| 58 | + }, | ||
| 59 | + { | ||
| 60 | + "name": "empty_remind", | ||
| 61 | + "value": "Read content is empty, please write." | ||
| 62 | + }, | ||
| 63 | + { | ||
| 64 | + "name": "start_remind", | ||
| 65 | + "value": "Start executing the task" | ||
| 66 | + } | ||
| 67 | + ] | ||
| 68 | +} | ||
| @@ -0,0 +1,68 @@ | |||
| 1 | +{ | ||
| 2 | + "string": [ | ||
| 3 | + { | ||
| 4 | + "name": "module_desc", | ||
| 5 | + "value": "module description" | ||
| 6 | + }, | ||
| 7 | + { | ||
| 8 | + "name": "EntryAbility_desc", | ||
| 9 | + "value": "description" | ||
| 10 | + }, | ||
| 11 | + { | ||
| 12 | + "name": "EntryAbility_label", | ||
| 13 | + "value": "多线程IO读写" | ||
| 14 | + }, | ||
| 15 | + { | ||
| 16 | + "name": "title", | ||
| 17 | + "value": "多线程操作密集型关系型数据库和文件读写" | ||
| 18 | + }, | ||
| 19 | + { | ||
| 20 | + "name": "button_name_1", | ||
| 21 | + "value": "多线程 文件-写入" | ||
| 22 | + }, | ||
| 23 | + { | ||
| 24 | + "name": "button_name_2", | ||
| 25 | + "value": "多线程 文件-读取" | ||
| 26 | + }, | ||
| 27 | + { | ||
| 28 | + "name": "button_name_3", | ||
| 29 | + "value": "多线程 数据库-写入" | ||
| 30 | + }, | ||
| 31 | + { | ||
| 32 | + "name": "button_name_4", | ||
| 33 | + "value": "多线程 数据库-读取" | ||
| 34 | + }, | ||
| 35 | + { | ||
| 36 | + "name": "button_name_5", | ||
| 37 | + "value": "TaskPool 数据库-写入" | ||
| 38 | + }, | ||
| 39 | + { | ||
| 40 | + "name": "button_name_6", | ||
| 41 | + "value": "TaskPool 数据库-读取" | ||
| 42 | + }, | ||
| 43 | + { | ||
| 44 | + "name": "button_name_7", | ||
| 45 | + "value": "@Sendable 数据库-写入" | ||
| 46 | + }, | ||
| 47 | + { | ||
| 48 | + "name": "button_name_8", | ||
| 49 | + "value": "@Sendable 数据库-读取" | ||
| 50 | + }, | ||
| 51 | + { | ||
| 52 | + "name": "remind", | ||
| 53 | + "value": "在执行任务,请稍后" | ||
| 54 | + }, | ||
| 55 | + { | ||
| 56 | + "name": "success_remind", | ||
| 57 | + "value": "成功" | ||
| 58 | + }, | ||
| 59 | + { | ||
| 60 | + "name": "empty_remind", | ||
| 61 | + "value": "读取内容为空,请写入" | ||
| 62 | + }, | ||
| 63 | + { | ||
| 64 | + "name": "start_remind", | ||
| 65 | + "value": "开始执行任务" | ||
| 66 | + } | ||
| 67 | + ] | ||
| 68 | +} | ||
| @@ -0,0 +1,23 @@ | |||
| 1 | +{ | ||
| 2 | + "modelVersion": "6.0.2", | ||
| 3 | + "dependencies": { | ||
| 4 | + }, | ||
| 5 | + "execution": { | ||
| 6 | + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | "ultrafine" | false ]. Default: "normal" */ | ||
| 7 | + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ | ||
| 8 | + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ | ||
| 9 | + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ | ||
| 10 | + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ | ||
| 11 | + // "optimizationStrategy": "memory" /* Define the optimization strategy. Value: [ "memory" | "performance" ]. Default: "memory" */ | ||
| 12 | + }, | ||
| 13 | + "logging": { | ||
| 14 | + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ | ||
| 15 | + }, | ||
| 16 | + "debugging": { | ||
| 17 | + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ | ||
| 18 | + }, | ||
| 19 | + "nodeOptions": { | ||
| 20 | + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ | ||
| 21 | + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ | ||
| 22 | + } | ||
| 23 | +} | ||
| @@ -0,0 +1,6 @@ | |||
| 1 | +import { appTasks } from '@ohos/hvigor-ohos-plugin'; | ||
| 2 | + | ||
| 3 | +export default { | ||
| 4 | + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ | ||
| 5 | + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ | ||
| 6 | +} | ||
| @@ -0,0 +1,10 @@ | |||
| 1 | +{ | ||
| 2 | + "modelVersion": "6.0.2", | ||
| 3 | + "description": "Please describe the basic information.", | ||
| 4 | + "dependencies": { | ||
| 5 | + }, | ||
| 6 | + "devDependencies": { | ||
| 7 | + "@ohos/hypium": "1.0.23", | ||
| 8 | + "@ohos/hamock": "1.0.1-rc2" | ||
| 9 | + } | ||
| 10 | +} | ||