介绍
本示例使用[@ohos.data.relationalStore]接口和[@ohos.distributedDeviceManager] 接口展示了在eTS中分布式关系型数据库的使用,在增、删、改、查的基本操作外,还包括分布式数据库的数据同步同能。
效果预览
使用说明:
鸿蒙OS开发 | 更多内容↓点击 《鸿蒙NEXT星河版开发学习文档》 | HarmonyOS与OpenHarmony技术 |
---|
- 启动应用后点击“ + ”按钮可以添加联系人;
- 点击联系人可以进入编辑界面编辑联系人信息;
- 长按联系人进入多选状态,底部有“全选”、“取消”、“删除”、“退出”按钮,点击退出可以退出多选状态;
- 点击右上角更多按钮,点击“连接设备”,选择要同步数据的设备,连接成功后可以开始将本端数据同步到对端;
- 点击右上角更多按钮,点击“设置”可以进入设置界面设置数据同步方式,包括自动同步和手动同步。
具体实现
鸿蒙开发技术更新在mau123789拿取前往是v喔
- 数据库的增、删、改、查操作都在RdbModel中,源码参考[RdbModel.ets]:
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import data_rdb from '@ohos.data.relationalStore'
import common from '@ohos.app.ability.common'
import Contact from '../model/Contact'
import Logger from '../model/Logger'
import { STORE_CONFIG } from '../model/RdbConst'
import { ValuesBucket } from '@ohos.data.ValuesBucket';
const TAG = 'RdbModel'
export default class RdbModel {
private rdbStore: data_rdb.RdbStore | undefined = undefined
private tableName: string = ''
private sqlCreateTable: string = ''
private columns: Array<string> = []
private distributedTable: string = ''
private dataChangeCallback : Function| null = null
private isCreateDbDone: boolean = false
private context: common.UIAbilityContext
constructor(tableName: string, sqlCreateTable: string, columns: Array<string>, context: common.UIAbilityContext) {
this.tableName = tableName
this.sqlCreateTable = sqlCreateTable
this.columns = columns
this.context = context
this.getRdbStore()
}
// 初始化数据库
async getRdbStore() {
Logger.info(TAG, 'getRdbStore begin')
if (this.isCreateDbDone) {
Logger.info(TAG, 'getRdbStore isCreateDbDone')
return
}
try {
// 获取数据库存储对象
this.rdbStore = await data_rdb.getRdbStore(this.context, STORE_CONFIG);
} catch (err) {
console.info(`getRdbStore err ${JSON.stringify(err)}`);
}
Logger.info(TAG, 'getRdbStore end')
try {
// 执行sql语句,联系人个各个属性设定
if(this.rdbStore != undefined) {
await this.rdbStore.executeSql(this.sqlCreateTable)
console.info(`create tabe start ` + this.sqlCreateTable);
// 设置分布式表,表明为contact
await this.rdbStore.setDistributedTables([this.tableName])
}
} catch (e) {
Logger.error(TAG, 'getRdbStore:' + JSON.stringify(e))
}
// 分布式数据库创建为完成
this.isCreateDbDone = true
Logger.info(TAG, 'create table done')
}
async insertData(contact: Contact) {
let value1 = contact.name;
let value2 = contact.gender;
let value3 = contact.phone;
let value4 = contact.remark;
let value5 = contact.age;
const valueBucket: ValuesBucket = {
'name': value1,
'gender': value2,
'phone': value3,
'remark': value4,
'age': value5,
}
if(this.rdbStore != undefined) {
let ret = await this.rdbStore.insert(this.tableName, valueBucket, data_rdb.ConflictResolution.ON_CONFLICT_REPLACE)
Logger.info(TAG, `insert done:${ret}`)
}
}
async updateData(contact: Contact) {
let value1 = contact.name;
let value2 = contact.gender;
let value3 = contact.phone;
let value4 = contact.remark;
let value5 = contact.age;
const valueBucket: ValuesBucket = {
'name': value1,
'gender': value2,
'phone': value3,
'remark': value4,
'age': value5,
}
let predicates = new data_rdb.RdbPredicates(this.tableName)
Logger.info(TAG, `updateData id=${contact.id}`)
predicates.equalTo('id', contact.id)
if (this.rdbStore != undefined) {
let ret = await this.rdbStore.update(valueBucket, predicates)
Logger.info(TAG, `updated row count: ${ret}`)
}
}
async deleteContacts(contacts: Array<Contact>) {
let predicates = new data_rdb.RdbPredicates(this.tableName)
contacts.forEach((contact) => {
predicates.or()
.equalTo('id', contact.id)
})
if (this.rdbStore != undefined) {
let rows = await this.rdbStore.delete(predicates)
Logger.info(TAG, `delete rows: ${rows}`)
}
}
async query(predicates: data_rdb.RdbPredicates): Promise<Array<Contact>> {
Logger.info(TAG, 'query start')
Logger.info(TAG, 'predicates is ' + JSON.stringify(predicates))
Logger.info(TAG, 'columns ' + JSON.stringify(this.columns))
if (this.rdbStore != undefined) {
// 默认查询所有列
let resultSet: data_rdb.ResultSet = await this.rdbStore.query(predicates, this.columns);
Logger.info(TAG, 'result is ' + JSON.stringify(resultSet.rowCount))
// 处理查询到的结果数组
return this.getListFromResultSet(resultSet)
}
return []
}
async syncData(predicates: data_rdb.RdbPredicates) {
Logger.info(TAG, 'syncData')
if (this.rdbStore != undefined) {
let result = await this.rdbStore.sync(data_rdb.SyncMode.SYNC_MODE_PUSH, predicates)
for (let i = 0; i < result.length; i++) {
Logger.info(TAG, `device=${result[i][0]}, status = ${result[i][1]}`)
}
}
}
async onDataChange(device: string, callback: Function) {
Logger.info(TAG, `onDataChange enter,device=` + device + ` ,tableName = ` + this.tableName)
try {
if (this.rdbStore != undefined) {
this.distributedTable = await this.rdbStore.obtainDistributedTableName(device, this.tableName)
Logger.info(TAG, `obtainDistributedTableName,distributedTable=` + this.distributedTable)
}
}
catch (err) {
Logger.error(TAG, `ObtainDistributedTableName failed, code is ${err.code},message is ${err.message}`)
}
this.dataChangeCallback = callback
await this.pullData()
if (this.rdbStore != undefined) {
this.rdbStore.on('dataChange', data_rdb.SubscribeType.SUBSCRIBE_TYPE_REMOTE, async (devices) => {
Logger.info(TAG, `on dataChange, callback`)
await this.pullData()
})
}
}
async pullData() {
Logger.info(TAG, `start pullData`)
if (this.rdbStore != undefined) {
await this.rdbStore.executeSql('delete from ' + this.tableName)
let predicates = new data_rdb.RdbPredicates(this.distributedTable)
let resultSet = await this.rdbStore.query(predicates, this.columns)
let result = this.getListFromResultSet(resultSet)
Logger.info(TAG, `on dataChange,result.length=${result.length}`)
for (let i = 0; i < result.length; i++) {
Logger.info(TAG, `on dataChange,insert${result[i].name}`)
let predicate = new data_rdb.RdbPredicates(this.tableName)
predicate.equalTo('name', result[i].name)
let exit = await this.rdbStore.query(predicate, this.columns)
exit.goToFirstRow()
if (exit.rowCount === 0) {
await this.insertData(result[i])
} else {
result[i].id = exit.getDouble(resultSet.getColumnIndex('id'))
await this.updateData(result[i])
}
}
if (this.dataChangeCallback != null) {
this.dataChangeCallback(result)
}
}
}
offDataChange() {
if(this.rdbStore != undefined) {
this.rdbStore.off('dataChange', data_rdb.SubscribeType.SUBSCRIBE_TYPE_REMOTE, (devices) => {
for (let i = 0; i < devices.length; i++) {
Logger.info(TAG, `device=${devices[i]} off data changed`)
}
})
}
}
// 处理数据格式
getListFromResultSet(resultSet: data_rdb.ResultSet): Array<Contact> {
// 声明结果变量
let contacts: Array<Contact> = []
// 进入结果集的第一行
resultSet.goToFirstRow()
// 如果没有结束就继续遍历
while (!resultSet.isEnded) {
// 读取各个属性,初始化临时变量contact
let contact: Contact = new Contact(resultSet.getDouble(resultSet.getColumnIndex('id'))
, resultSet.getString(resultSet.getColumnIndex('name'))
, resultSet.getDouble(resultSet.getColumnIndex('gender'))
, resultSet.getString(resultSet.getColumnIndex('phone'))
, resultSet.getLong(resultSet.getColumnIndex('age'))
, resultSet.getString(resultSet.getColumnIndex('remark')))
if (!contacts.includes(contact)) {
// 如果数据集合中没有这条数据就添加进去
contacts.push(contact)
}
// 进入下一行
resultSet.goToNextRow()
}
// 数据整合完毕就释放资源
resultSet.close()
Logger.info(TAG, 'contacts number is ' + contacts.length)
// 返回整合的联系人数据
return contacts
}
}
- 数据库操作:使用[@ohos.data.relationalStore] 接口的getRdbStore获得一个相关的操作型关系数据库RdbStore,通过这个RdbStore调用相关接口进行增删改查,RdbStore.insert数据插入,RdbStore.delete数据删除,RdbStore.update更新数据,RdbStore.query根据条件查询数据;
- 数据同步:RdbStore.on注册数据库观察者,使用RdbStore.obtainDistributedTableName根据本地表名获取指定远程设备的分布式表名,数据发生变动时通过RdbStore.sync同步数据,不需要用时删除指定观察者使用RdbStore.off。
连接设备管理在RemoteDeviceModel中,源码参考[RemoteDeviceModel.ets]:
/* * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import deviceManager from '@ohos.distributedDeviceManager'; import Logger from '../model/Logger' import { BUNDLE } from '../model/RdbConst' import { BusinessError } from '@ohos.base'; let SUBSCRIBE_ID = 100 const TAG: string = 'RemoteDeviceModel' class Data { device: deviceManager.DeviceBasicInfo = { deviceId: "", deviceName: "", deviceType: "", networkId: "", } } class RemoteDeviceModel { public deviceList: Array<deviceManager.DeviceBasicInfo> = []; public discoverList: Array<deviceManager.DeviceBasicInfo> = []; private callback: () => void = () => {}; private authCallback: (device: deviceManager.DeviceBasicInfo) => void = (device: deviceManager.DeviceBasicInfo) => ''; private deviceManager: deviceManager.DeviceManager | undefined = undefined registerDeviceListCallback(callback: () => void) { if (typeof (this.deviceManager) !== 'undefined') { this.registerDeviceListCallbackImplement(callback) return } Logger.info(TAG, 'deviceManager.createDeviceManager begin') try { let dmInstance = deviceManager.createDeviceManager(BUNDLE); Logger.info(TAG, `dmInstance= ${JSON.stringify (dmInstance)}`); this.deviceManager = dmInstance; this.registerDeviceListCallbackImplement(callback); Logger.info(TAG, `createDeviceManager callback returned, value= ${JSON.stringify(this.deviceManager)}`); } catch (error) { Logger.error(TAG, `createDeviceManager throw error, code: ${(error as BusinessError).code} message: ${(error as BusinessError).message}`); } Logger.info(TAG, 'deviceManager.createDeviceManager end'); } deviceStateChangeActionOnline(device: deviceManager.DeviceBasicInfo) { this.deviceList[this.deviceList.length] = device Logger.info(TAG, `online, device list=${JSON.stringify(this.deviceList)}`) if (this.authCallback !== undefined) { this.authCallback(device) this.authCallback = () => {} } } deviceStateChangeActionReady(device: deviceManager.DeviceBasicInfo) { if (this.deviceList.length <= 0) { this.callback() return } let list: Array<deviceManager.DeviceBasicInfo> = new Array() for (let i = 0; i < this.deviceList.length; i++) { if (this.deviceList[i].deviceId !== device.deviceId) { list[i] = device } } this.deviceList = list Logger.info(TAG, `ready, device list=${JSON.stringify(this.deviceList)}`) this.callback() } deviceStateChangeActionOffline(device: deviceManager.DeviceBasicInfo) { if (this.deviceList.length <= 0) { this.callback() return } for (let j = 0; j < this.deviceList.length; j++) { if (this.deviceList[j].deviceId === device.deviceId) { this.deviceList[j] = device break } } Logger.info(TAG, `offline, device list=${JSON.stringify(this.deviceList)}`) } getLocalDevice(): string { Logger.info(TAG, `getLocalDevice`); if(this.deviceManager != undefined) { let deviceId: string = this.deviceManager.getLocalDeviceId(); Logger.info(TAG, `local deviceInfo=${JSON.stringify(deviceId)}`); return deviceId; } return '' } registerDeviceListCallbackImplement(callback: () => void) { Logger.info(TAG, 'registerDeviceListCallback' + JSON.stringify(this.deviceManager)) this.callback = callback if (this.deviceManager === undefined) { Logger.error(TAG, 'deviceManager has not initialized') this.callback() return } Logger.info(TAG, 'getTrustedDeviceListSync begin' + JSON.stringify(this.deviceManager)); let list = this.deviceManager.getAvailableDeviceListSync(); Logger.info(TAG, `getTrustedDeviceListSync end, deviceList=${JSON.stringify(list)}`) if (typeof (list) !== 'undefined' && typeof (list.length) !== 'undefined') { this.deviceList = list } this.callback() Logger.info(TAG, 'callback finished') this.deviceManager.on('deviceStateChange', (data) => { Logger.info(TAG, 'deviceStateChange on:' + JSON.stringify(data)); if (data === null) { return } switch (data.action) { case deviceManager.DeviceStateChange.UNKNOWN: this.deviceStateChangeActionOnline(data.device) break case deviceManager.DeviceStateChange.AVAILABLE: this.deviceStateChangeActionReady(data.device) break case deviceManager.DeviceStateChange.UNAVAILABLE: this.deviceStateChangeActionOffline(data.device) break default: break } }) this.deviceManager.on('discoverSuccess', (data: Data) => { if (data === null) { return } Logger.info(TAG, `discoverSuccess data=${JSON.stringify(data)}`); this.deviceFound(data); }) this.deviceManager.on('discoverFailure', (data) => { Logger.info(TAG, `discoverFailure data=${JSON.stringify(data)}`); }) this.deviceManager.on('serviceDie', () => { Logger.info(TAG, 'serviceDie') }) this.startDeviceDiscovery() } deviceFound(data: Data) { if(data != undefined) { if (data.device != undefined) { for (let i = 0; i < this.discoverList.length; i++) { if (this.discoverList[i].deviceId === data.device.deviceId) { Logger.info(TAG, 'device founded ignored') return } } this.discoverList[this.discoverList.length] = data.device Logger.info(TAG, `deviceFound self.discoverList=${JSON.stringify(this.discoverList)}`); this.callback() } } } startDeviceDiscovery() { let discoverParam: Record<string, number> = { 'discoverTargetType': 1 }; let filterOptions: Record<string, number> = { 'availableStatus': 0 }; Logger.info(TAG, `startDeviceDiscovery${SUBSCRIBE_ID}`); try { if(this.deviceManager != undefined) { this.deviceManager.startDiscovering(discoverParam, filterOptions); } } catch (error) { Logger.error(TAG, `startDeviceDiscovery throw error, code: ${(error as BusinessError).code} message: ${(error as BusinessError).message}`); } } unregisterDeviceListCallback() { if(this.deviceManager != undefined) { Logger.info(TAG, `stopDeviceDiscovery${SUBSCRIBE_ID}`); this.deviceManager.stopDiscovering(); this.deviceManager.off('deviceStateChange'); this.deviceManager.off('discoverSuccess'); this.deviceManager.off('discoverFailure'); this.deviceManager.off('serviceDie'); } this.deviceList = []; this.discoverList = []; } authenticateDevice(device: deviceManager.DeviceBasicInfo, callBack: (device: deviceManager.DeviceBasicInfo) => void) { Logger.info(TAG, `bindTarget${JSON.stringify(device)}`); for (let i = 0; i < this.discoverList.length; i++) { if (this.discoverList[i].deviceId !== device.deviceId) { continue } if (this.deviceManager === undefined) { return } try { if (this.deviceManager !== null) { this.deviceManager.bindTarget(device.deviceId, { bindType: 1, targetPkgName: BUNDLE, appName: 'Distributed distributedrdb', }, (err, data) => { if (err) { Logger.error(TAG, `authenticateDevice throw error, code: ${(err as BusinessError).code} message: ${(err as BusinessError).message}`); this.authCallback = () => { } return } Logger.debug(TAG, `authenticateDevice succeed: ${JSON.stringify(data)}`); this.authCallback = callBack; }) } } catch (error) { Logger.error(TAG, `authenticateDevice throw error, code: ${(error as BusinessError).code} message: ${(error as BusinessError).message}`); } } } } export default new RemoteDeviceModel()
- 设备同步:设备同步数据需要[ohos.permission.DISTRIBUTED_DATASYNC] 权限,在页面渲染前申请权限,源码参考[Index.ets],
/*
* Copyright (c) 2022-2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import data_rdb from '@ohos.data.relationalStore'
import common from '@ohos.app.ability.common'
import Want from '@ohos.app.ability.Want'
import router from '@ohos.router'
import Contact from '../model/Contact'
import ContactDataSource from '../common/BasicDataSource'
import LiteStore from '../model/LiteStore'
import Logger from '../model/Logger'
import RdbModel from '../model/RdbModel'
import { BottomBtn } from '../common/BottomBtn'
import { ContactItem } from '../common/ContactItem'
import { PopupMenu } from '../common/PopupMenu'
import { SyncState } from '../model/LiteStore'
import { SearchBar } from '../common/SearchBar'
import { TitleBar } from '../common/TitleBar'
import { TABLE_NAME, BUNDLE, ABILITY, SQL_CREATE_TABLE, COLUMNS } from '../model/RdbConst'
const TAG: string = 'Index'
export interface stateType {
popupMenu: boolean,
isDistributed: boolean,
isStage: boolean,
selectedIndex: number,
syncState: string,
distributedDevice: string,
opacityValue: number
}
@Entry
@Component
struct Index {
private liteStore = new LiteStore("sync_state", getContext(this) as common.UIAbilityContext)
private rdbModel = new RdbModel(TABLE_NAME, SQL_CREATE_TABLE, COLUMNS, getContext(this) as common.UIAbilityContext)
private intervalId: number = 0
@State contacts: ContactDataSource = new ContactDataSource([])
@State isMultiCheck: boolean = false
@State isSelectedAll: boolean = false
@State state: stateType = {
popupMenu: false,
isDistributed: false,
isStage: false,
selectedIndex: 0,
syncState: SyncState.ManualSync,
distributedDevice: '',
opacityValue: 1
}
async aboutToAppear() {
Logger.info(TAG, 'aboutToAppear')
await this.rdbModel.getRdbStore();
await this.getData();
}
// 拉起应用后读取数据,暂定为分布式功能
getWant() {
let want = AppStorage.Get<Want>('want') as Want
if(want.parameters != undefined) {
if (this.state.isDistributed && want.parameters.isStage === 'EXIT') {
Logger.info(TAG, 'isStage = EXIT')
this.state.isStage = false
this.state.isDistributed = false
this.state.selectedIndex = 0
this.state.distributedDevice = ''
this.rdbModel.offDataChange()
}
if (!this.state.isDistributed && want.parameters.isStage === 'Stage') {
Logger.info(TAG, 'isStage = Stage')
this.state.isStage = true
this.state.isDistributed = true
this.state.distributedDevice = want.parameters.dmsSrcNetworkId as string;
let context = getContext(this) as common.UIAbilityContext
context.startAbility({
bundleName: BUNDLE,
abilityName: ABILITY,
deviceId: this.state.distributedDevice,
parameters: {
isStage: 'CONNECT'
}
})
Logger.info(TAG, 'onDataChange')
this.rdbModel.onDataChange(this.state.distributedDevice, (result: Array<Contact>)=> {
this.contacts.dataArray = result
this.contacts.notifyDataReload()
})
}
}
}
async onPageShow() {
try {
// 初始化分部署数据库
await this.rdbModel.getRdbStore()
this.intervalId = setInterval(() => {
// 手动侦听应用被拉起的动作
this.getWant()
}, 1000)
// 读取数据库数据
await this.getData()
} catch (err) {
Logger.error('onPageShow:' + JSON.stringify(err))
}
}
async getData() {
Logger.info(TAG, 'getData')
// 初始化数据库的表,表名为contact
let predicates = new data_rdb.RdbPredicates(TABLE_NAME)
// 读取表中的数据
this.contacts.replaceDataArray(await this.rdbModel.query(predicates));
// 通知懒加载数据变更
this.contacts.notifyDataReload()
Logger.info(TAG, 'getData contacts count' + this.contacts.dataArray.length)
// 读取Preferences中的数据
let syncState = await this.liteStore.getValue()
this.state.syncState = `${syncState}`
if (!this.state.isStage && this.state.isDistributed && syncState === SyncState.AutomaticSync) {
await this.syncData()
}
}
showDeleteDialog() {
let deleteContacts: Contact[] = []
this.contacts.dataArray.forEach((contact) => {
if (contact.isSelected) {
deleteContacts.push(contact)
}
})
if (deleteContacts.length == 0) {
return
}
AlertDialog.show({
message: $r('app.string.delete_contact'),
primaryButton: {
value: $r('app.string.sure'),
fontColor: Color.Red,
action: async () => {
await this.rdbModel.deleteContacts(deleteContacts)
await this.getData()
this.quitMultiCheck()
}
},
secondaryButton: {
value: $r('app.string.cancel'),
fontColor: Color.Blue,
action: () => {
}
}
})
}
handleClickContact(item: Contact, index: number) {
Logger.info(TAG, `handleClickContact, item = ${JSON.stringify(item)}`)
if (this.isMultiCheck) {
let tempContacts = this.contacts.dataArray
this.contacts.dataArray = []
tempContacts[index].isSelected = !item.isSelected
this.contacts.dataArray = tempContacts
this.contacts.notifyDataReload()
} else {
router.pushUrl({
url: 'pages/ContactEdit',
params: { contact: item, isInsert: false }
})
}
}
refreshSelectState(isSelect: boolean) {
this.contacts.dataArray.forEach((contact) => {
contact.isSelected = isSelect
})
this.contacts.notifyDataReload()
}
quitMultiCheck() {
this.isSelectedAll = false
this.refreshSelectState(this.isSelectedAll)
this.isMultiCheck = false
}
handleBottomBtnClick = (index: number) => {
switch (index) {
case 0:
this.isSelectedAll = !this.isSelectedAll
this.refreshSelectState(this.isSelectedAll)
break
case 1:
this.showDeleteDialog()
break
case 2:
this.quitMultiCheck()
break
default:
break
}
}
handleRightBtn = () => {
this.state.popupMenu = true;
this.state.opacityValue = 1;
}
syncData = () => {
Logger.info(TAG, 'sync data')
let predicates = new data_rdb.RdbPredicates(TABLE_NAME)
predicates.inAllDevices()
this.rdbModel.syncData(predicates)
}
build() {
Stack({ alignContent: Alignment.BottomEnd }) {
Column() {
Stack() {
if (this.state.isStage) {
TitleBar()
} else {
TitleBar({ rightBtn: $r('app.media.more'), handleRightBtn: this.handleRightBtn })
}
if (this.state.isDistributed && !this.state.isStage && this.state.syncState === SyncState.ManualSync) {
Row() {
Blank()
Image($r('app.media.ic_syncto'))
.size({ width: 50, height: 60 })
.onClick(this.syncData)
}.width('80%')
}
}.width('100%')
SearchBar()
List() {
LazyForEach(this.contacts, (item: Contact, index) => {
ListItem() {
ContactItem({ contact: item, isMultiCheck: $isMultiCheck })
}
.onClick(() => {
this.handleClickContact(item, index)
})
}, (item: Contact) => JSON.stringify(item))
}
.width('100%')
.layoutWeight(1)
.padding({ left: 10, right: 10 })
.divider({ strokeWidth: 1, color: Color.Gray, startMargin: 16, endMargin: 16 })
}
.width('100%')
.height('100%')
if (this.state.popupMenu) {
PopupMenu({ state: $state, handleStartAbility: this.syncData })
}
BottomBtn({
isMultiCheck: this.isMultiCheck,
isSelectedAll: this.isSelectedAll,
handleBottomBtnClick: this.handleBottomBtnClick
})
if (!this.isMultiCheck && !this.state.isStage) {
Button() {
Image($r('app.media.add'))
.height('100%')
.width('100%')
.objectFit(ImageFit.Contain)
.align(Alignment.End)
}
.id('btnAdd')
.width(80)
.height(80)
.margin({ right: 20, bottom: 50 })
.type(ButtonType.Circle)
.backgroundColor('#0D9FFB')
.onClick(() => {
Logger.info(TAG, 'onClick')
router.pushUrl({
url: 'pages/ContactEdit',
params: { contact: new Contact(0, '', 0, '', -1, ''), isInsert: true }
})
})
}
}
.width('100%')
.height('100%')
}
onBackPress() {
Logger.info(TAG, 'onBackPress')
let context = getContext(this) as common.UIAbilityContext
context.startAbility({
bundleName: BUNDLE,
abilityName: ABILITY,
deviceId: this.state.distributedDevice,
parameters: {
isStage: 'EXIT'
}
})
this.rdbModel.offDataChange()
}
onPageHide() {
Logger.info(TAG, 'onBackPress')
clearInterval(this.intervalId)
}
}
使用[@ohos.distributedDeviceManager]接口,首先通过createDeviceManager创建设备管理器实例,然后通过getTrustedDeviceListSync同步获取所有可信设备列表;
- 设备连接:首先通过on方法注册设备状态,例如发现设备,设备连接失败,然后通过startDeviceDiscovery方法发现周边设备,然后选择连接设备,再用[startAbility]启动连接设备的应用。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。