README.md
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