• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Cross-Device Synchronization of Distributed Data Objects
2
3
4## When to Use
5
6To implement traditional data synchronization between devices, you need to design the message processing logic, including setting up a communication link, sending, receiving, and processing messages, retry mechanism upon errors, and resolving data conflicts. The workload is heavy. In addition, the debugging complexity increases with the number of devices.
7
8The device status, message sending progress, and data transmitted are variables. If these variables support global access, they can be accessed as local variables on difference devices. This simplifies data synchronization between multiple devices.
9
10The distributed data object (**DataObject**) implements global access to variables. **DataObject** provides basic data object management capabilities and distributed capabilities. You can use the APIs to create, query, delete, and modify in-memory objects and subscribe to event notifications. OpenHarmony also provides easy-to-use JS APIs for distributed application scenarios to easily implement cross-device data collaboration for the same application. In addition, object status and data changes on different devices can be observed. This feature implements data object collaboration for the same application between multiple devices that form a Super Device. **DataObject** greatly reduces the development workloads compared with the traditional mode.
11
12
13## Basic Concepts
14
15- Distributed in-memory database<br>
16  The distributed in-memory database caches data in the memory so that applications can quickly access data without persisting data. If the database is closed, the data is not retained.
17
18- Distributed data object
19  A distributed data object is an encapsulation of the JS object type. Each distributed data object instance creates a data table in the in-memory database. The in-memory databases created for different applications are isolated from each other. Reading data from and writing data to a distributed data object are mapped to the **get()** and **put()** operations in the corresponding database, respectively.
20
21  The distributed data object can be in the following states in its lifecycle:
22
23  - **Uninitialized**: The distributed data object is not instantiated or has been destroyed.
24  - **Local**: The data table is created, but the data cannot be synchronized.
25  - **Distributed**: The data table is created, and there are at least two online devices with the same session ID. In this case, data can be synchronized across devices. If a device is offline or the session ID is empty, the distributed data object changes to the local state.
26
27
28## Working Principles
29
30**Figure 1** Working mechanism
31
32![distributedObject](figures/distributedObject.jpg)
33
34The distributed data objects are encapsulated into JS objects in distributed in-memory databases. This allows the distributed data objects to be operated in the same way as local variables. The system automatically implements cross-device data synchronization.
35
36
37### JS Object Storage and Encapsulation Mechanism
38
39- An in-memory database is created for each distributed data object instance and identified by a session ID (**SessionId**). The in-memory databases created for different applications are isolated from each other.
40
41- When a distributed data object is instantiated, all properties of the object are traversed recursively. **Object.defineProperty** is used to define the **set()** and **get()** methods of all properties. The **set()** and **get()** methods correspond to the **put** and **get** operations of a record in the database, respectively. **Key** specifies the property name, and **Value** specifies the property value.
42
43- When a distributed data object is read or written, the **set()** and **get()** methods are automatically called to perform the related operations to the database.
44
45**Table 1** Correspondence between a distributed data object and a distributed database
46
47| Distributed Data Object Instance| Object Instance| Property Name| Property Value|
48| -------- | -------- | -------- | -------- |
49| Distributed in-memory database| Database identified by **sessionID**| Key of a record in the database| Value of a record in the database|
50
51
52### Cross-Device Synchronization and Data Change Notification Mechanism
53
54The distributed data object is used to implement data synchronization between objects. You can create a distributed data object and set **sessionID** for the devices on a trusted network. The distributed data objects with the same **sessionID** on different devices can synchronize data with each other.
55
56As shown in the following figure, distributed data object 1 on device A and device B have the same session ID **session1**. The synchronization relationship of session1 is established between the two objects.
57
58  **Figure 2** Object synchronization relationship
59
60![distributedObject_sync](figures/distributedObject_sync.jpg)
61
62For each device, only one object can be added to a synchronization relationship. As shown in the preceding figure, distributed data object 2 of device A cannot be added to session 1 because distributed data object 1 of device A has been added to session 1.
63
64After the synchronization relationship is established, each session has a copy of shared object data. The distributed data objects added to the same session support the following operations:
65
66 (1) Reading or modifying the data in the session.
67
68 (2) Listening for data changes made by other devices.
69
70 (3) Listening for status changes, such as the addition and removal of other devices.
71
72
73### Minimum Unit to Synchronize
74
75Attribute is the minimum unit to synchronize in distributed data objects. For example, object 1 in the following figure has three attributes: name, age, and parents. If one of the attributes is changed, only the changed attribute needs to be synchronized.
76
77**Figure 3** Synchronization of distributed data objects
78
79
80![distributedObject_syncView](figures/distributedObject_syncView.jpg)
81
82
83### Object Persistence Mechanism
84
85Distributed data objects run in the process space of applications. When the data of a distributed data object is persisted in the distributed database, the data will not be lost after the application exits.
86
87You need to persist distributed data objects in the following scenarios:
88
89- Enable an application to retrieve the exact same data after it is opened again. In this case, you need to persist the distributed data object (for example, object 1). After the application is opened again, create a distributed data object (for example, object 2) and set the session ID of object 1 for object 2. Then, the application can retrieve the data of object 1.
90
91- Enable an application opened on another device to retrieve the exact same data. In this case, you need to persist the distributed data object (for example, object 1) on device A and synchronize the data to device B. Then, create a distributed data object (for example, object 2) and set the session ID of object 1 for object 2. When the application is opened on device B, it can retrieve the same application data used on device A before the application is closed.
92
93
94## Constraints
95
96- Data synchronization can be implemented across devices only for the applications with the same **bundleName**.
97
98- Data can be synchronized only for the distributed data objects with the same **sessionID** of the same application.
99
100- Each distributed data object occupies 100 KB to 150 KB of memory. Therefore, you are advised not to create too many distributed data objects.
101
102- The maximum size of a distributed data object is 500 KB.
103
104- It takes about 50 ms from the time when 1 KB of data starts to be modified on a device to the time when another device receives a data change notification.
105
106- A maximum of 16 distributed data object instances can be created for an application.
107
108- For optimal performance and user experience, the maximum number of devices for data collaboration is 3.
109
110- For the distributed data object of the complex type, only the root attribute can be modified. The subordinate attributes cannot be modified.
111
112- Only JS APIs are supported.
113
114
115## Available APIs
116
117The following table lists the APIs for cross-device synchronization of distributed data objects. Most of the interfaces are executed asynchronously, using a callback or promise to return the result. The following table uses the callback-based APIs as an example. For more information about the APIs, see [Distributed Data Object](../reference/apis/js-apis-data-distributedobject.md).
118
119| API| Description|
120| -------- | -------- |
121| create(context: Context, source: object): DataObject | Creates a distributed data object instance.|
122| genSessionId(): string | Generates a session ID for distributed data objects.|
123| setSessionId(sessionId: string, callback: AsyncCallback&lt;void&gt;): void | Sets a session ID for data synchronization. Automatic synchronization is performed for devices with the same session ID on a trusted network.|
124| setSessionId(callback: AsyncCallback&lt;void&gt;): void | Exits all sessions.|
125| on(type: 'change', callback: Callback&lt;{ sessionId: string, fields: Array&lt;string&gt; }&gt;): void | Subscribes to data changes of this distributed data object.|
126| on(type: 'status', callback: Callback&lt;{ sessionId: string, networkId: string, status: 'online' \| 'offline' }&gt;): void | Subscribes to status changes of this distributed data object.|
127| save(deviceId: string, callback: AsyncCallback&lt;SaveSuccessResponse&gt;): void | Saves a distributed data object.|
128| revokeSave(callback: AsyncCallback&lt;RevokeSaveSuccessResponse&gt;): void | Revokes the save operation of the distributed data object.|
129
130
131## How to Develop
132
133The following example demonstrates how to implement a distributed data object synchronization.
134
1351. Import the **@ohos.data.distributedDataObject** module.
136
137   ```js
138   import distributedDataObject from '@ohos.data.distributedDataObject';
139   ```
140
1412. Request permissions.
142
143   1. Request the **ohos.permission.DISTRIBUTED_DATASYNC** permission. For details, see [Declaring Permissions in the Configuration File](../security/accesstoken-guidelines.md#declaring-permissions-in-the-configuration-file).
144   2. Display a dialog box to ask authorization from the user when the application is started for the first time. For details, see [Requesting User Authorization](../security/accesstoken-guidelines.md#requesting-user-authorization).
145
1463. Creates a distributed data object instance.
147
148   Stage model:
149
150   ```js
151   // Import the module.
152   import distributedDataObject from '@ohos.data.distributedDataObject';
153   import UIAbility from '@ohos.app.ability.UIAbility';
154
155   class EntryAbility extends UIAbility {
156     onWindowStageCreate(windowStage) {
157       // Create a distributed data object, which contains attributes of the string, number, boolean, and object types.
158       let localObject = distributedDataObject.create(this.context, {
159         name: 'jack',
160         age: 18,
161         isVis: false,
162         parent: { mother: 'jack mom', father: 'jack Dad' },
163         list: [{ mother: 'jack mom' }, { father: 'jack Dad' }]
164       });
165     }
166   }
167   ```
168
169   FA model:
170
171
172   ```js
173   // Import the module.
174   import distributedDataObject from '@ohos.data.distributedDataObject';
175   import featureAbility from '@ohos.ability.featureAbility';
176   // Obtain the context.
177   let context = featureAbility.getContext();
178   // Create a distributed data object, which contains attributes of the string, number, boolean, and object types.
179   let localObject = distributedDataObject.create(context, {
180     name: 'jack',
181     age: 18,
182     isVis: false,
183     parent: { mother: 'jack mom', father: 'jack Dad' },
184     list: [{ mother: 'jack mom' }, { father: 'jack Dad' }]
185   });
186   ```
187
1884. Set the same session ID for the distributed data objects for data synchronization. The data objects in the synchronization network include the local and remote objects.
189
190   ```js
191   // Set a session ID, for example, 123456, for device 1.
192   let sessionId = '123456';
193
194   localObject.setSessionId(sessionId);
195
196   // Set the same session ID for device 2.
197
198   // Create a distributed data object, which contains attributes of the string, number, boolean, and object types.
199   let remoteObject = distributedDataObject.create(this.context, {
200     name: undefined,
201     age: undefined, // undefined indicates that the data comes from the peer end.
202     isVis: true,
203     parent: undefined,
204     list: undefined
205   });
206   // After learning that the device goes online, the remote object synchronizes data. That is, name changes to jack and age to 18.
207   remoteObject.setSessionId(sessionId);
208   ```
209
2105. Observe data changes of a distributed data object. You can subscribe to data changes of the remote object. When the data in the remote object changes, a callback will be invoked to return a data change event.
211
212   ```js
213   function changeCallback(sessionId, changeData) {
214     console.info(`change: ${sessionId}`);
215
216     if (changeData !== null && changeData !== undefined) {
217       changeData.forEach(element => {
218         console.info(`The element ${localObject[element]} changed.`);
219       });
220     }
221   }
222
223   // To refresh the page in changeCallback, correctly bind (this) to the changeCallback.
224   localObject.on("change", this.changeCallback.bind(this));
225   ```
226
2276. Modify attributes of the distributed data object. The object attributes support basic data types (number, Boolean, and string) and complex data types (array and nested basic types).
228
229   ```js
230   localObject.name = 'jack1';
231   localObject.age = 19;
232   localObject.isVis = false;
233   localObject.parent = { mother: 'jack1 mom', father: 'jack1 Dad' };
234   localObject.list = [{ mother: 'jack1 mom' }, { father: 'jack1 Dad' }];
235   ```
236
237   > **NOTE**
238   >
239   > For the distributed data object of the complex type, only the root attribute can be modified. The subordinate attributes cannot be modified.
240
241
242   ```js
243   // Supported modification.
244   localObject.parent = { mother: 'mom', father: 'dad' };
245   // Modification not supported.
246   localObject.parent.mother = 'mom';
247   ```
248
2497. Access a distributed data object. Obtain the distributed data object attributes, which are the latest data on the network.
250
251   ```js
252   console.info(`name:${localObject['name']}`);
253   ```
254
2558. Unsubscribe from data changes. You can specify the callback to unregister. If you do not specify the callback, all data change callbacks of the distributed data object will be unregistered.
256
257   ```js
258   // Unregister this.changeCallback.
259   localObject.off('change', this.changeCallback);
260   // Unregister all data change callbacks.
261   localObject.off('change');
262   ```
263
2649. Subscribes to status changes of a distributed data object. A callback will be invoked to report the status change when the target distributed data object goes online or offline.
265
266   ```js
267   function statusCallback(sessionId, networkId, status) {
268     // Service processing.
269   }
270
271   localObject.on('status', this.statusCallback);
272   ```
273
27410. Save a distributed data object and revoke the data saving operation.
275
276    ```js
277    // Save the data object if the device on the network needs to retrieve the object data after the application exits.
278    localObject.save('local').then((result) => {
279      console.info(`Succeeded in saving. SessionId:${result.sessionId},version:${result.version},deviceId:${result.deviceId}`);
280    }).catch((err) => {
281      console.error(`Failed to save. Code:${err.code},message:${err.message}`);
282    });
283
284    // Revoke the save of a distributed data object.
285    localObject.revokeSave().then((result) => {
286      console.info(`Succeeded in revokeSaving. Session:${result.sessionId}`);
287    }).catch((err) => {
288      console.error(`Failed to revokeSave. Code:${err.code},message:${err.message}`);
289    });
290    ```
291
29211. Unsubscribe from the status changes of a distributed data object. You can specify the callback to unregister. If you do not specify the callback, this API unregisters all status change callbacks of this distributed data object.
293
294    ```js
295    // Unregister this.statusCallback.
296    localObject.off('status', this.statusCallback);
297    // Unregister all status change callbacks.
298    localObject.off('status');
299    ```
300
30112. Remove a distributed data object from the synchronization network. The data of the removed distributed data object will not be synchronized to other devices.
302
303    ```js
304    localObject.setSessionId(() => {
305        console.info('leave all lession.');
306    });
307    ```
308