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 (default by build system) 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 build is the removal 35of all `stateMgmtConsole.log`/`.debug`/`.info` statements from the 36release version JS output code. 37NOTE: Output folder is one of following (dist, distRelease or distProfile). In ace_engine build distRelease output is copied to 38```bash 39./out/rk3568/obj/foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/stateMgmt.js 40``` 41## To get all logs 42Change selected aceConsole.debug to aceConsole.error. At least from public statig debug. In file state_mgmt_console_trace.ts 43Enable debug: hdc shell param set persist.ace.debug.enabled 1 44Build debug version npm run build 45Generate .abc from dist/stateMgmt.js and copy to device and reboot. 46 47## File Organising into Directories 48 49- `./src/lib/*.ts` - implementation 50 * `./src/lib/sdk/*.ts` - all files that include SDK definitons 51 * `./src/lib/common/*.ts` - common files that do not include any SDK functionality 52 * `./src/lib/full_update/*.ts` - files specific to the older version of state mgmt for full Component to Element update 53 * `./src/lib/partial_update/*.ts` - files specfic to the newer version of state mgmt for NG UINode minimal scope updates 54 * `./src/lib/v2/*.ts` - files specfic to V2 implementation 55-`./src/index.ts` - implementation 'main' creates singletons. 56 57## How to Develop - StateMgmt 58* Change files .ts in src/lib folder 59* Do npm install once after repo sync in state_mgmt folder... Then after that 'npm run build_release' 60* Output file is in distRelease/stateMgmt.js 61* Do script to convers stateMgmt.js to .abc and copy that to device. 62 63```bash 64# Make target RK3568 writable 65hdc target mount 66# Remove old file 67hdc shell rm -rf /etc/abc/framework/stateMgmt.abc 68# Use es2abc.exe with output parameter --output stateMgmt.abc 69# Then copy stateMgmt.abc from build server to local disk and send to /etc/abc/framework 70hdc file send stateMgmt.abc /etc/abc/framework 71# Reboot device and it will load stateMgmt.abc at start up 72hdc shell reboot 73``` 74 75## StateMgmt Profiling 76 77### Building 78 79Execute follwing commands in framework/bridge/declarative_frontend/state_mgmt. 80 81```bash 82npm install 83npm run build_profile 84Adjust your script to copy stateMgmt.js from distProfile folder. 85``` 86 87Then compile SW and flash / update .so 88 89#### Initialization for App (DevEco) 90 91By default you can see timing infor from framework. If you want to add something to your App then... 92First, initialize an instance of the profiler in your ETS, at the top. 93NOTE: The class declarations provided below are needed for DevEco apps 94 95```typescript 96// Native class 97declare class StateMgmtProfiler { 98 constructor(suite: string); 99 begin(block: string): void; 100 end(): void; 101 report(): void; 102 clear(): void; 103} 104 105// JS global object 106declare class stateMgmtProfiler { 107 static begin(blockName: string) : void; 108 static end() : void; 109 static report() : void; 110 static clear(): void; 111 static init(instance: StateMgmtProfiler) : void; 112} 113 114stateMgmtProfiler.init(new StateMgmtProfiler("MyProfiler")); 115``` 116 117#### Placing blocks in code 118 119In your JS code, wrap the code to be measured between `stateMgmtProfiler.begin("blockNameHere")` and `stateMgmtProfiler.end()`: 120 121```typescript 122stateMgmtProfiler.begin("HeavyMethodCall"); 123myObject.myVeryHeavyMethodCall(); 124// Nested blocks also work: 125{ 126 stateMgmtProfiler.begin("EvenHeavierMethodCall"); 127 myObject.evenHeavierMethodCall(); 128 stateMgmtProfiler.end(); 129} 130stateMgmtProfiler.end(); 131``` 132 133#### Print results 134 135To 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. 136The last command invokes DFX log. The argument `-jsdump` is to invoke JS DFX logging and `-profiler` is the arg to dump profiler results. 137 138```bash 139#! /bin/bash 140hdc shell param set persist.ace.debug.enabled 0 (needs to be done once) 141Start the Test application NOW 142hdc shell "hidumper -s WindowManagerService -a '-a'" 143Check WinId of your app. Lets say its 11. Put it to -w arg. 144hdc shell "hidumper -s WindowManagerService -a '-w 11 -jsdump -profiler'" 145``` 146 147The output will be like this: 148Total include childrens. 149 150```bash 151============================================================================================================ 152Block name #Calls Self Total 153============================================================================================================ 154MyProfiler 155 HeavyMethodCall 1 1.465ms 1.465ms 156 EvenHeavierMethodCall 1 1.417ms 1.417ms 157============================================================================================================ 158``` 159 160- Calling `stateMgmtProfiler.clear()` will clear the results. 161- Calling `stateMgmtProfiler.report()` will print the results and then clear them. 162 163## DFX Debug Log 164 165DFX 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. 166 167### Commands 168 169- `-jsdump` 170 * Requests JS debug logging from the `hidumper` service. It is followed by additional commands and arguments to format the output. See below. 171 172Two output modifiers are defined in order to facilitate the usage of the commands: 173 174- `-viewId` 175 * 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. 176- `-r` 177 * 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. 178 179For the purpose of logging the following commands are accepted as input: 180 181- `-dumpAll` 182 * 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. 183- `-viewHierarchy` 184 * 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. 185- `-stateVariables` 186 * 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. 187- `-registeredElementIds` 188 * 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. 189- `-dirtyElementIds` 190 * 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. 191- `-inactiveComponents` 192 * 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. 193 194The 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. 195 196```bash 197#! /bin/bash 198hdc shell "param set persist.ace.debug.enabled 0" (needs to be done once) 199Start the Test application NOW 200hdc shell "hidumper -s WindowManagerService -a '-a'" 201Check WinId of your app. Lets say its 11. Put it to -w arg. 202hdc shell "hidumper -s WindowManagerService -a '-w 11 -jsdump -dumpAll'" 203hdc shell "hidumper -s WindowManagerService -a '-w 11 -jsdump -viewHierarchy'" 204hdc shell "hidumper -s WindowManagerService -a '-w 11 -jsdump -viewHierarchy -inactiveComponents'" 205``` 206 207### Important for Profiler and JSDump 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