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 7## Building just state mgmt 8 9The implementation is in Typescript. 10 11Before first build: 12`npm install` 13 14For every debug build 15`npm run build` 16 17The output is one JS file: 18`./dist/stateMgmt.js` 19 20For every release build (default by build system) 21`npm run build_release` 22 23The output is one JS file: 24`./distRelease/stateMgmt.js` 25 26For profiler build. See StateMgmt Profiler. 27`npm run build_profile` 28 29The output is one JS file: 30`./distProfile/stateMgmt.js` 31 32The difference between debug build and release build is the removal 33of all `stateMgmtConsole.log`/`.debug`/`.info` statements from the 34release version JS output code. 35 36NOTE: Output folder is one of following (dist, distRelease or distProfile). In ace_engine build distRelease output is copied to 37```bash 38./out/rk3568/obj/foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/stateMgmt.js 39``` 40## To get all logs 41Change selected aceConsole.debug to aceConsole.error. At least from public statig debug. In file state_mgmt_console_trace.ts 42Enable debug: hdc shell param set persist.ace.debug.enabled 1 43Build debug version npm run build 44Generate .abc from dist/stateMgmt.js and copy to device and reboot. 45 46## File Organising into Directories 47 48- `./src/lib/*.ts` - implementation 49 * `./src/lib/sdk/*.ts` - all files that include SDK definitons 50 * `./src/lib/common/*.ts` - common files that do not include any SDK functionality 51 * `./src/lib/full_update/*.ts` - files specific to the older version of state mgmt for full Component to Element update 52 * `./src/lib/partial_update/*.ts` - files specfic to the newer version of state mgmt for NG UINode minimal scope updates 53 * `./src/lib/v2/*.ts` - files specfic to V2 implementation 54-`./src/index.ts` - implementation 'main' creates singletons. 55 56## How to Develop - StateMgmt 57* Change files .ts in src/lib folder 58* Do npm install once after repo sync in state_mgmt folder... Then after that 'npm run build_release' 59* Output file is in distRelease/stateMgmt.js 60* Do script to convers stateMgmt.js to .abc and copy that to device. 61 62```bash 63# Make target RK3568 writable 64hdc target mount 65# Remove old file 66hdc shell rm -rf /etc/abc/framework/stateMgmt.abc 67# Use es2abc.exe with output parameter --output stateMgmt.abc 68# Then copy stateMgmt.abc from build server to local disk and send to /etc/abc/framework 69hdc file send stateMgmt.abc /etc/abc/framework 70# Reboot device and it will load stateMgmt.abc at start up 71hdc shell reboot 72``` 73 74## StateMgmt Profiler 75 76### Building 77 78Execute follwing commands in framework/bridge/declarative_frontend/state_mgmt. 79 80```bash 81npm install 82npm run build_profile 83Adjust your script to copy stateMgmt.js from distProfile folder. 84``` 85 86Then compile SW and flash / update .so 87 88#### Initialization for App (DevEco) 89 90By default you can see timing infor from framework. If you want to add something to your App then... 91First, initialize an instance of the profiler in your ETS, at the top. 92NOTE: The class declarations provided below are needed for DevEco apps 93 94```typescript 95// Native class 96declare class StateMgmtProfiler { 97 constructor(suite: string); 98 begin(block: string): void; 99 end(): void; 100 report(): void; 101 clear(): void; 102} 103 104// JS global object 105declare class stateMgmtProfiler { 106 static begin(blockName: string) : void; 107 static end() : void; 108 static report() : void; 109 static clear(): void; 110 static init(instance: StateMgmtProfiler) : void; 111} 112 113stateMgmtProfiler.init(new StateMgmtProfiler("MyProfiler")); 114``` 115 116#### Placing blocks in code 117 118In your JS code, wrap the code to be measured between `stateMgmtProfiler.begin("blockNameHere")` and `stateMgmtProfiler.end()`: 119 120```typescript 121stateMgmtProfiler.begin("HeavyMethodCall"); 122myObject.myVeryHeavyMethodCall(); 123// Nested blocks also work: 124{ 125 stateMgmtProfiler.begin("EvenHeavierMethodCall"); 126 myObject.evenHeavierMethodCall(); 127 stateMgmtProfiler.end(); 128} 129stateMgmtProfiler.end(); 130``` 131 132#### Print results 133 134To 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. 135The last command invokes DFX log. The argument `-jsdump` is to invoke JS DFX logging and `-profiler` is the arg to dump profiler results. 136 137```bash 138#! /bin/bash 139hdc shell param set persist.ace.debug.enabled 0 (needs to be done once) 140Start the Test application NOW 141hdc shell "hidumper -s WindowManagerService -a '-a'" 142Check WinId of your app. Lets say its 11. Put it to -w arg. 143hdc shell "hidumper -s WindowManagerService -a '-w 11 -jsdump -profiler'" 144``` 145 146The output will be like this: 147Total include children. 148 149```bash 150============================================================================================================ 151Block name #Calls Self Total 152============================================================================================================ 153MyProfiler 154 HeavyMethodCall 1 1.465ms 1.465ms 155 EvenHeavierMethodCall 1 1.417ms 1.417ms 156============================================================================================================ 157``` 158 159- Calling `stateMgmtProfiler.clear()` will clear the results. 160- Calling `stateMgmtProfiler.report()` will print the results and then clear them. 161 162## DFX Debug Log 163 164DFX 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. 165 166### Commands 167 168- `-jsdump` 169 * Requests JS debug logging from the `hidumper` service. It is followed by additional commands and arguments to format the output. See below. 170 171Two output modifiers are defined in order to facilitate the usage of the commands: 172 173- `-viewId` 174 * 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. 175- `-r` 176 * 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. 177 178For the purpose of logging the following commands are accepted as input: 179 180- `-dumpAll` 181 * 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. 182- `-viewHierarchy` 183 * 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. 184- `-stateVariables` 185 * 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. 186- `-registeredElementIds` 187 * 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. 188- `-dirtyElementIds` 189 * 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. 190- `-inactiveComponents` 191 * 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. 192 193The 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. 194 195```bash 196#! /bin/bash 197hdc shell "param set persist.ace.debug.enabled 0" (needs to be done once) 198Start the Test application NOW 199hdc shell "hidumper -s WindowManagerService -a '-a'" 200Check WinId of your app. Lets say its 11. Put it to -w arg. 201hdc shell "hidumper -s WindowManagerService -a '-w 11 -jsdump -dumpAll'" 202hdc shell "hidumper -s WindowManagerService -a '-w 11 -jsdump -viewHierarchy'" 203hdc shell "hidumper -s WindowManagerService -a '-w 11 -jsdump -viewHierarchy -inactiveComponents'" 204``` 205 206### Important for Profiler and JSDump 207 208PartialUpdateMode MUST be configured for your application. This can be made for example by changing following. 209For API10...\OpenHarmony\Sdk\10\ets\build-tools\ets-loader\main.js and change const partialUpdateConfig = { 210 partialUpdateMode: true, // from false 211 212RK3568 /etc/acenewpipe.config must have application name under EANBLED to use newpipeline. 213Example content of acenewpipe.config 214 215```bash 216ENABLED 217com.example.myapplication 218``` 219### Usefull examples 220 221All the following commands concern a hypothetical window with ID 11 and view with ID 42. Note that -viewId is optional. 222 223| Info | Shell command | 224|-------|----------| 225|Dump all info | `hidumper -s WindowManagerService -a '-w 11 -jsdump -dumpAll -viewId=42'`| 226|Dump view hierarchy recursively | `hidumper -s WindowManagerService -a '-w 11 -jsdump -viewHierarchy -viewId=42 -r'`| 227|Dump view hierarchy only for the target view | `hidumper -s WindowManagerService -a '-w 11 -jsdump -viewHierarchy -viewId=42'`| 228|Dump the list of all registered element ids | `hidumper -s WindowManagerService -a '-w 11 -jsdump -registeredElementIds -viewId=42'`| 229|Dump the list of all dirty element ids | `hidumper -s WindowManagerService -a '-w 11 -jsdump -dirtyElementIds -viewId=42'`| 230 231### Example with dependent elements 232 233`hidumper -s WindowManagerService -a '-w 11 -jsdump -dumpAll'` 234 235Showing dependent elements for Link "stringValue". 236``` 237@State/@Provide 'stringValue'[..] 238 |--Dependent elements: 'Text[..]'; @Component 'Child1'[..], 'Text[..]'; @Component 'Child2'[..], Text[..]'; 239``` 240