1# ArkUI Declarative State Management 2 3State management TypeScript library for ArkUI declarative front-end. 4Supports both older 'full update' for Component to Element classes 5and newer 'partial update' for minimal scope NG UINode updates. 6 7Developed at UI Frameworks Team at the Huawei R&D Center Helsinki, Finland. 8 9## Building just state mgmt 10 11The implementation is in Typescript. 12 13Before first build: 14`npm install` 15 16For every debug build 17`npm run build` 18 19The output is one JS file: 20`./dist/stateMgmt.js` 21 22For every release build 23`npm run build_release` 24 25The output is one JS file: 26`./distRelease/stateMgmt.js` 27 28For profiler build. See StateMgmt Profiler. 29`npm run build_profile` 30 31The output is one JS file: 32`./distProfile/stateMgmt.js` 33 34The difference between debug build and release/profiler build is the removal 35of all `stateMgmtConsole.log`/`.debug`/`.info` statements from the 36release version JS output code. 37 38NOTE: After compiling with npm run X command. You need to copy stateMgmt.js from output folder to ../engine/. Then build the device SW again. Output folder is one of following (dist, distRelease or distProfile). 39 40## File Organising into Directories 41 42- `./src/lib/*.ts` - implementation 43 * `./src/lib/sdk/*.ts` - all files that include SDK definitons 44 * `./src/lib/common/*.ts` - common files that do not include any SDK functionality 45 * `./src/lib/full_update/*.ts` - files specific to the older version of state mgmt for full Component to Element update 46 * `./src/lib/partial_update/*.ts` - files specfic to the newer version of state mgmt for NG UINode minimal scope updates 47 -`./src/index.ts` - implementation 'main' creates singletons. 48 49## StateMgmt Profiler 50 51### Building 52 53Execute follwing commands in framework/bridge/declarative_frontend/state_mgmt. 54 55```bash 56npm install 57npm run build_profile 58cp ./distProfile/stateMgmt.js ../engine/ 59``` 60 61Then compile SW and flash / update .so 62 63#### Initialization for App (DevEco) 64 65By default you can see timing infor from framework. If you want to add something to your App then... 66First, initialize an instance of the profiler in your ETS, at the top. 67NOTE: The class declarations provided below are needed for DevEco apps 68 69```typescript 70// Native class 71declare class StateMgmtProfiler { 72 constructor(suite: string); 73 begin(block: string): void; 74 end(): void; 75 report(): void; 76 clear(): void; 77} 78 79// JS global object 80declare class stateMgmtProfiler { 81 static begin(blockName: string) : void; 82 static end() : void; 83 static report() : void; 84 static clear(): void; 85 static init(instance: StateMgmtProfiler) : void; 86} 87 88stateMgmtProfiler.init(new StateMgmtProfiler("MyProfiler")); 89``` 90 91#### Placing blocks in code 92 93In your JS code, wrap the code to be measured between `stateMgmtProfiler.begin("blockNameHere")` and `stateMgmtProfiler.end()`: 94 95```typescript 96stateMgmtProfiler.begin("HeavyMethodCall"); 97myObject.myVeryHeavyMethodCall(); 98// Nested blocks also work: 99{ 100 stateMgmtProfiler.begin("EvenHeavierMethodCall"); 101 myObject.evenHeavierMethodCall(); 102 stateMgmtProfiler.end(); 103} 104stateMgmtProfiler.end(); 105``` 106 107#### Print results 108 109To print the results, you can use this script. You need to replace the package ID with your own and also see the WindowID of your package. 110The last command invokes DFX log. The argument `-jsdump` is to invoke JS DFX logging and `-profiler` is the arg to dump profiler results. 111 112```bash 113#! /bin/bash 114hdc shell param set persist.ace.debug.enabled 0 (needs to be done once) 115Start the Test application NOW 116hdc shell "hidumper -s WindowManagerService -a '-a'" 117Check WinId of your app. Lets say its 11. Put it to -w arg. 118hdc shell "hidumper -s WindowManagerService -a '-w 11 -jsdump -profiler'" 119``` 120 121The output will be like this: 122Total include children. 123 124```bash 125============================================================================================================ 126Block name #Calls Self Total 127============================================================================================================ 128MyProfiler 129 HeavyMethodCall 1 1.465ms 1.465ms 130 EvenHeavierMethodCall 1 1.417ms 1.417ms 131============================================================================================================ 132``` 133 134- Calling `stateMgmtProfiler.clear()` will clear the results. 135- Calling `stateMgmtProfiler.report()` will print the results and then clear them. 136 137## DFX Debug Log 138 139DFX Debug Log is built to work on top of `hidumper`, which is OHOS info dump tool. The DFX Debug Log is used to request information from the process in a shell. 140 141### Commands 142 143- `-jsdump` 144 * Requests JS debug logging from the `hidumper` service. It is followed by additional commands and arguments to format the output. See below. 145 146Two output modifiers are defined in order to facilitate the usage of the commands: 147 148- `-viewId` 149 * Specifies the view for which information is obtaineed. It acts as an aditional argument to the command providing the view ID in the following format `viewId=##`. where `##` is the numerical ID of the target view. 150- `-r` 151 * Specifies whether the output of the command should be recursive or not. Non-recursive prints the information for the target view ommiting the same information about it's decendants. 152 153For the purpose of logging the following commands are accepted as input: 154 155- `-dumpAll` 156 * Prints all information about the view. This combines the output of all other commands for the specified view. Default print is for root view if no view is specified. 157- `-viewHierarchy` 158 * Prints the view hierarchy of a particular view, namely the custom component children. Accepts `-viewId` argument and `-r` flag. Depending on the flags provided it can be either recursive, from a specific view downwards, or just the immediate children of the view. Default print is for root view non-recursive if no flags are provided. It also indicates the freeze state of the component if it is configured to be frozen while inactive. 159- `-stateVariables` 160 * Prints the variables dependencies of the view, and their respective owners and sync peers. Accepts `-viewId` argument. Default print is for root view if no view is specified. 161- `-registeredElementIds` 162 * Prints a list of components, namely JS classes such as `Column`, `TapGesture` etc. and their ID-s owned by the view. Accepts `-viewId` argument. Default print is for root view if not specified otherwise. 163- `-dirtyElementIds` 164 * Prints a list of dependent elmtIds that need partial update in next re-render. Accepts `-viewId` argument. Default print is for root view if not specified otherwise. 165- `-inactiveComponents` 166 * Prints the list of the components that are presently in an inactive or frozen state. These components are not actively processing updates and will stay inactive while in the background. 167 168The application must be running and visible in order to receive commands. The `hidumper` service delivers the commands through the `WindowManagerService`. and the window ID is used to target a specific application. 169 170```bash 171#! /bin/bash 172hdc shell "param set persist.ace.debug.enabled 0" (needs to be done once) 173Start the Test application NOW 174hdc shell "hidumper -s WindowManagerService -a '-a'" 175Check WinId of your app. Lets say its 11. Put it to -w arg. 176hdc shell "hidumper -s WindowManagerService -a '-w 11 -jsdump -dumpAll'" 177hdc shell "hidumper -s WindowManagerService -a '-w 11 -jsdump -viewHierarchy'" 178hdc shell "hidumper -s WindowManagerService -a '-w 11 -jsdump -viewHierarchy -inactiveComponents'" 179``` 180 181### Important for Profiler and JSDump 182 183PartialUpdateMode MUST be configured for your application. This can be made for example by changing following. 184For API10...\OpenHarmony\Sdk\10\ets\build-tools\ets-loader\main.js and change const partialUpdateConfig = { 185partialUpdateMode: true, // from false 186 187RK3568 /etc/acenewpipe.config must have application name under EANBLED to use newpipeline. 188Example content of acenewpipe.config 189 190```bash 191ENABLED 192com.example.myapplication 193``` 194 195### Usefull examples 196 197All the following commands concern a hypothetical window with ID 11 and custom component viewId with ID 8. Note that -viewId is optional and you should not use @Entry main page id. It is only for custom components 198 199| Info | Shell command | 200|-------|----------| 201|Dump all info | `hidumper -s WindowManagerService -a '-w 11 -jsdump -dumpAll -viewId=42'`| 202|Dump view hierarchy recursively | `hidumper -s WindowManagerService -a '-w 11 -jsdump -viewHierarchy -viewId=42 -r'`| 203|Dump view hierarchy only for the target view | `hidumper -s WindowManagerService -a '-w 11 -jsdump -viewHierarchy -viewId=42'`| 204|Dump the list of all registered element ids | `hidumper -s WindowManagerService -a '-w 11 -jsdump -registeredElementIds -viewId=42'`| 205|Dump the list of all dirty element ids | `hidumper -s WindowManagerService -a '-w 11 -jsdump -dirtyElementIds -viewId=42'`| 206 207### Example with dependent elements 208 209`hidumper -s WindowManagerService -a '-w 11 -jsdump -dumpAll'` 210 211Showing dependent elements for Link "stringValue". 212``` 213@State/@Provide 'stringValue'[..] 214 |--Dependent elements: 'Text[..]'; @Component 'Child1'[..], 'Text[..]'; @Component 'Child2'[..], Text[..]'; 215``` 216