鸿蒙HarmonyOS开发实例:【分布式关系型数据库】

电子说

1.3w人已加入

描述

分布式关系型数据库

介绍

本示例使用[@ohos.data.relationalStore]接口和[@ohos.distributedDeviceManager] 接口展示了在eTS中分布式关系型数据库的使用,在增、删、改、查的基本操作外,还包括分布式数据库的数据同步同能。

效果预览

HarmonyOS

使用说明:

  1. 启动应用后点击“ + ”按钮可以添加联系人;
  2. 点击联系人可以进入编辑界面编辑联系人信息;
  3. 长按联系人进入多选状态,底部有“ 全选 ”、“ 取消 ”、“ 删除 ”、“ 退出 ”按钮,点击退出可以退出多选状态;
  4. 点击右上角更多按钮,点击“ 连接设备 ”,选择要同步数据的设备,连接成功后可以开始将本端数据同步到对端;
  5. 点击右上角更多按钮,点击“ 设置 ”可以进入设置界面设置数据同步方式,包括自动同步和手动同步。
    HarmonyOS

具体实现

  • 数据库的增、删、改、查操作都在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]启动连接设备的应用。

审核编辑 黄宇

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分