HarmonyOS 分散チャットルームアプリケーション

HarmonyOS 分散チャットルームアプリケーション

[[434771]]

詳細については、以下をご覧ください。

51CTOとHuaweiが共同で構築したHongmengテクノロジーコミュニティ

https://harmonyos..com

導入

以前、[#星光计划1.0# HarmonyOS 分散型 TikTok 風アプリケーション] を紹介しました。今回は、HarmonyOS 分散データ サービスをベースに開発されたチャット ルーム アプリケーションを紹介します。実際のチャットルームでの会話をシミュレートし、友達と交流したり、ストーリーを共有したりすることができます。

効果のデモンストレーション


プロジェクトクラスの説明


主な知識ポイント

分散データサービス

公式紹介: 分散データ サービスは、主にユーザー デバイス内のアプリケーションのデータ コンテンツの分散同期を実現します。デバイス 1 上のアプリケーション A が分散データベース内のデータを追加、削除、または変更すると、デバイス 2 上のアプリケーション A もデータベースの変更を取得できます。要約すると、複数のデバイスが 1 つのデータベースを共有します。

ホームページコード

特に複雑なロジックはなく、分散データサービスの利用が中心で、要所にコメントが入っています。

  1. com.ldd.myapp.bean.ChatDataBean をインポートします。
  2. com.ldd.myapp.provider.ChatProvider をインポートします。
  3. com.ldd.myapp.util.Tools をインポートします。
  4. ohos.aafwk.ability.AbilitySlice をインポートします。
  5. ohos.aafwk.content.Intent をインポートします。
  6. ohos.agp.components.Button をインポートします。
  7. ohos.agp.components.ListContainer をインポートします。
  8. ohos.agp.components.TextField をインポートします。
  9. ohos.app.Context をインポートします。
  10. ohos.bundle.IBundleManager をインポートします。
  11. ohos.data.distributed.common.* をインポートします。
  12. ohos.data.distributed.user .SingleKvStoreをインポートします
  13. ohos.utils.zson.ZSONArray をインポートします。
  14. ohos.utils.zson.ZSONObject をインポートします。
  15.  
  16. java.util.ArrayList をインポートします。
  17. java.util.List をインポートします。
  18.  
  19. 静的ohos.security.SystemPermission.DISTRIBUTED_DATASYNC をインポートします。
  20.  
  21. /**
  22. * ホームページ
  23. */
  24. パブリッククラス MainAbilitySlice は AbilitySlice を拡張します {
  25. プライベートコンテキストmContext;
  26. // チャットリスト
  27. プライベート ListContainer lcList;
  28. //チャットデータ
  29. プライベート最終リスト<ChatDataBean> listData = new ArrayList<>();
  30. //チャットデータアダプタ
  31. プライベート ChatProvider チャットプロバイダー;
  32. // 入力ボックス
  33. プライベート TextField tfContent;
  34. //送信ボタン
  35. プライベートボタン btnSend;
  36.  
  37. // 分散データベースマネージャー
  38. プライベート KvManager kvManager;
  39. // 分散データベース
  40. プライベート SingleKvStore シングルKvストア;
  41. // データベース名
  42. プライベート静的最終文字列 STORE_NAME = "ChatStore" ;
  43. // 保存されたリストデータキー 
  44. プライベート静的最終文字列 KEY_DATA = "key_data" ;
  45. // 保存されたアバターのインデックス
  46. プライベート静的最終文字列 KEY_PIC_INDEX = "key_pic_index" ;
  47. プライベートint picIndex = 0;
  48.  
  49. @オーバーライド
  50. パブリックvoid onStart(インテント インテント) {
  51. super.onStart(インテント);
  52. UIContent をスーパーに設定します。
  53. mContext = これ;
  54. リクエストパーミッション();
  55. コンポーネントを初期化します。
  56. データベースを初期化します。
  57. }
  58.  
  59. /**
  60. * 分散権限を要求する
  61. */
  62. プライベートvoid requestPermission() {
  63. if (verifySelfPermission(DISTRIBUTED_DATASYNC) != IBundleManager.PERMISSION_GRANTED) {
  64. (DISTRIBUTED_DATASYNCの許可をリクエストできる場合){
  65. requestPermissionsFromUser(新しい文字列[]{DISTRIBUTED_DATASYNC}, 0);
  66. }
  67. }
  68. }
  69.  
  70. /**
  71. * コンポーネントを初期化する
  72. */
  73. プライベートvoid initComponent() {
  74. lcList = (ListContainer) リソーステーブルId_lc_list でコンポーネントIDを検索します。
  75. tfContent = (テキストフィールド) findComponentById(ResourceTable.Id_tf_content);
  76. tfContent.setAdjustInputPanel( true );
  77. btnSend = (ボタン) findComponentById(ResourceTable.Id_btn_send);
  78. btnSend.setEnabled( false );
  79.  
  80. // アダプタを初期化する
  81. チャットプロバイダー = 新しいチャットプロバイダー (mContext、リストデータ);
  82. lcList.setItemProvider(チャットプロバイダー);
  83.  
  84. // 入力ボックスの内容変更の監視
  85. tfContent.addTextObserver((テキスト、開始、前、カウント) -> {
  86. btnSend.setEnabled(text.length() != 0);
  87. });
  88. // 送信ボタンをクリック
  89. btnSend.setClickedListener(コンポーネント -> {
  90. 文字列コンテンツ = tfContent.getText().trim();
  91. listData.add (新しい ChatDataBean(Tools.getDeviceId(mContext),picIndex,content));
  92. // データベースに保存
  93. 単一のKvStore.putString(KEY_DATA、ZSONObject.toZSONString(listData));
  94.  
  95. // 入力ボックスをクリアする
  96. tfContent.setText( "" );
  97. });
  98. }
  99.  
  100. /**
  101. * 分散データベースを初期化する
  102. */
  103. プライベートvoid initDatabase() {
  104. // 分散データベースマネージャーを作成する
  105. kvManager = KvManagerFactory.getInstance().createKvManager(新しい KvManagerConfig(this));
  106.  
  107. // データベース構成
  108. オプション options = new Options();
  109. options.setCreateIfMissing( true ) // データベースが存在しない場合に作成するかどうかを設定します
  110. .setEncrypt( false ) // データベースが暗号化されているかどうかを設定します
  111. .setKvStoreType(KvStoreType.SINGLE_VERSION); //データベースタイプ
  112. // 分散データベースを作成する
  113. 単一のKvStore = kvManager.getKvStore(オプション、STORE_NAME);
  114. //データベースデータの変更を監視する
  115. 単一のKvStore.subscribe(SubscribeType.SUBSCRIBE_TYPE_ALL、新しいKvStoreObserver() {
  116. @オーバーライド
  117. パブリックvoid onChange(ChangeNotification changeNotification) {
  118. リスト<Entry> insertEntries = changeNotification.getInsertEntries();
  119. リスト<Entry> updateEntries = changeNotification.getUpdateEntries();
  120.  
  121. // 初めてデータを保存するときは、insertEntries を取得します
  122. (挿入エントリのサイズ( )>0)の場合{
  123. for (エントリ entry : insertEntries) {
  124. KEY_DATAがentry.getKey()と等しい場合{
  125. // コールバックは非UIスレッドであり、UIはUIスレッドで更新される必要がある
  126. getUITaskDispatcher().syncDispatch(() -> {
  127. リストデータをクリアします。
  128. listData.addAll(ZSONArray.stringToClassList(entry.getValue().getString(),ChatDataBean.class));
  129. チャットプロバイダーに通知データが変更されました();
  130. lcList.scrollTo(リストデータ.size () - 1);
  131. });
  132. }
  133. }
  134. }そうでない場合( updateEntries.size ()>0){
  135. for (エントリ entry : updateEntries) {
  136. KEY_DATAがentry.getKey()と等しい場合{
  137. // コールバックは非UIスレッドであり、UIはUIスレッドで更新される必要がある
  138. getUITaskDispatcher().syncDispatch(() -> {
  139. リストデータをクリアします。
  140. listData.addAll(ZSONArray.stringToClassList(entry.getValue().getString(),ChatDataBean.class));
  141. チャットプロバイダーに通知データが変更されました();
  142. lcList.scrollTo(リストデータ.size () - 1);
  143. });
  144. }
  145. }
  146. }
  147. }
  148. });
  149.  
  150. 試す {
  151. picIndex = singleKvStore.getInt(KEY_PIC_INDEX);
  152. singleKvStore.putInt(KEY_PIC_INDEX, picIndex + 1);
  153. } キャッチ (KvStoreException e) {
  154. e.printStackTrace();
  155. // 見つかりません、最初のエントリ
  156. (e.getKvStoreErrorCode() == KvStoreErrorCode.KEY_NOT_FOUND) の場合 {
  157. picインデックス = 0;
  158. singleKvStore.putInt(KEY_PIC_INDEX, picIndex + 1);
  159. }
  160. }
  161. }
  162.  
  163. @オーバーライド
  164. 保護されたvoid onStop() {
  165. スーパーのonStop();
  166. kvManager.closeKvStore(単一のKvStore);
  167. }
  168. }

シンプルなケース

1. config.json の設定

  1. 「必要な権限」 : [
  2. {
  3. 「理由」 「マルチデバイスコラボレーション」
  4. 「名前」 : 「ohos.permission.DISTRIBUTED_DATASYNC」
  5. 「使用シーン」 : {
  6. "能力" : [
  7. 「メインアビリティ」  
  8. ]、
  9. 「いつ」 「常に」  
  10. }
  11. },
  12. {
  13. 「名前」 : 「ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE」  
  14. },
  15. {
  16. 「名前」 : 「ohos.permission.GET_DISTRIBUTED_DEVICE_INFO」  
  17. },
  18. {
  19. 「名前」 : 「ohos.permission.GET_BUNDLE_INFO」  
  20. }
  21. ]

2. レイアウトページ

  1. <?xml バージョン = "1.0"エンコーディング = "utf-8" ?>
  2. <方向レイアウト
  3. xmlns:ohos= "http://schemas.huawei.com/res/ohos"  
  4. ohos:height= "match_parent"  
  5. ohos:width= "match_parent"  
  6. ohos:alignment= "中央"  
  7. ohos:orientation= "垂直" >
  8.  
  9. <テキスト
  10. ohos:id= "$+id:テキスト"  
  11. ohos:height= "match_content"  
  12. ohos:width= "match_content"  
  13. ohos:text= "データ:0"  
  14. ohos:text_size= "15fp" />
  15.  
  16. <ボタン
  17. ohos:margin= "20vp"  
  18. ohos:id= "$+id:ボタン"  
  19. ohos:height= "match_content"  
  20. ohos:width= "match_parent"  
  21. ohos:background_element= "$graphic:button_bg"  
  22. ohos:padding= "10vp"  
  23. ohos:text= "+1 をクリック"  
  24. ohos:text_color= "白"  
  25. ohos:text_size= "15fp" />
  26.  
  27. </方向レイアウト>

3. MainAbilitySliceコード

  1. ohos.aafwk.ability.AbilitySlice をインポートします。
  2. ohos.aafwk.content.Intent をインポートします。
  3. ohos.agp.components.Button をインポートします。
  4. ohos.agp.components.ListContainer をインポートします。
  5. ohos.agp.components.Text をインポートします。
  6. ohos.agp.components.TextField をインポートします。
  7. ohos.bundle.IBundleManager をインポートします。
  8. ohos.data.distributed.common.* をインポートします。
  9. ohos.data.distributed.user .SingleKvStoreをインポートします
  10. ohos.utils.zson.ZSONArray をインポートします。
  11.  
  12. java.util.List をインポートします。
  13.  
  14. 静的ohos.security.SystemPermission.DISTRIBUTED_DATASYNC をインポートします。
  15.  
  16. パブリッククラス MainAbilitySlice は AbilitySlice を拡張します {
  17. // データを表示
  18. プライベートテキストテキスト;
  19. // 分散データベースマネージャー
  20. プライベート KvManager kvManager;
  21. // 分散データベース
  22. プライベート SingleKvStore シングルKvストア;
  23. // データベース名
  24. プライベート静的最終文字列 STORE_NAME = "MyStore" ;
  25. // 保存するデータキー 
  26. プライベート静的最終文字列 KEY_COUNT = "key_count" ;
  27.  
  28. @オーバーライド
  29. パブリックvoid onStart(インテント インテント) {
  30. super.onStart(インテント);
  31. UIContent をスーパーに設定します。
  32. リクエストパーミッション();
  33. データベースを初期化します。
  34. コンポーネントを初期化します。
  35. }
  36.  
  37. /**
  38. * 分散権限を要求する
  39. */
  40. プライベートvoid requestPermission() {
  41. if (verifySelfPermission(DISTRIBUTED_DATASYNC) != IBundleManager.PERMISSION_GRANTED) {
  42. (DISTRIBUTED_DATASYNCの許可をリクエストできる場合){
  43. requestPermissionsFromUser(新しい文字列[]{DISTRIBUTED_DATASYNC}, 0);
  44. }
  45. }
  46. }
  47.  
  48. /**
  49. * 分散データベースを初期化する
  50. */
  51. プライベートvoid initDatabase() {
  52. // 分散データベースマネージャーを作成する
  53. kvManager = KvManagerFactory.getInstance().createKvManager(新しい KvManagerConfig(this));
  54.  
  55. // データベース構成
  56. オプション options = new Options();
  57. options.setCreateIfMissing( true ) // データベースが存在しない場合に作成するかどうかを設定します
  58. .setEncrypt( false ) // データベースが暗号化されているかどうかを設定します
  59. .setKvStoreType(KvStoreType.SINGLE_VERSION); //データベースタイプ
  60. // 分散データベースを作成する
  61. 単一の KvStore = kvManager.getKvStore(オプション、STORE_NAME);
  62. //データベースデータの変更を監視する
  63. 単一のKvStore.subscribe(SubscribeType.SUBSCRIBE_TYPE_ALL、新しいKvStoreObserver() {
  64. @オーバーライド
  65. パブリックvoid onChange(ChangeNotification changeNotification) {
  66. リスト<Entry> insertEntries = changeNotification.getInsertEntries();
  67. リスト<エントリ> updateEntries = changeNotification.getUpdateEntries();
  68.  
  69. // 初めてデータを保存するときは、insertEntries を取得します
  70. ( insertEntries.size () > 0)の場合{
  71. for (エントリ entry : insertEntries) {
  72. KEY_COUNTがentry.getKey()と等しい場合{
  73. // コールバックは非UIスレッドであり、UIはUIスレッドで更新される必要がある
  74. getUITaskDispatcher().syncDispatch(() -> {
  75. 整数 カウント= entry.getValue().getInt();
  76. text.setText( "データ: " + count );
  77. });
  78. }
  79. }
  80. }そうでない場合( updateEntries.size () > 0) {
  81. for (エントリ entry : updateEntries) {
  82. KEY_COUNTがentry.getKey()と等しい場合{
  83. // コールバックは非UIスレッドであり、UIはUIスレッドで更新される必要がある
  84. getUITaskDispatcher().syncDispatch(() -> {
  85. 整数 カウント= entry.getValue().getInt();
  86. text.setText( "データ: " + count );
  87. });
  88. }
  89. }
  90. }
  91. }
  92. });
  93.  
  94. }
  95.  
  96. /**
  97. * コンポーネントを初期化する
  98. */
  99. プライベートvoid initComponent() {
  100. テキスト = (テキスト) findComponentById(ResourceTable.Id_text);
  101. ボタン button = (Button) findComponentById(ResourceTable.Id_button);
  102.  
  103. // クリックイベント
  104. button.setClickedListener(コンポーネント -> {
  105. 試す {
  106. 整数 カウント= singleKvStore.getInt(KEY_COUNT);
  107. 単一のKvStore.putInt(KEY_COUNT、カウント+1);
  108. } キャッチ (KvStoreException e) {
  109. e.printStackTrace();
  110. // 見つかりません、最初のエントリ
  111. (e.getKvStoreErrorCode() == KvStoreErrorCode.KEY_NOT_FOUND) の場合 {
  112. 整数 カウント= 0;
  113. 単一のKvStore.putInt(KEY_COUNT、カウント+1);
  114. }
  115. }
  116. });
  117. }
  118. }

コメントは非常に詳細で、主に次の 2 つの点に注目してください。

  1. キーが見つからない状況に対処するために、データを取得するときにtry catchブロックを追加します。
  2. データベース データ変更監視コールバックは非 UI スレッドです。 UI を更新する場合は、UI スレッドに切り替える必要があります。

上記の簡単なケースは、複数のデバイス上の同じアプリケーション間で同じデータベースを使用する分散データ サービスをすぐに習得するのに役立ちます。

詳細については、以下をご覧ください。

51CTOとHuaweiが共同で構築したHongmengテクノロジーコミュニティ

https://harmonyos..com

<<:  JavaAgent を使用して JVM を騙す

>>:  マルチクラウド戦略を構築するための考慮事項

推薦する

検索エンジンの今後の発展方向について語る

フェーズ1: コンテンツ関連コンテンツの関連性とは、ユーザーが検索エンジンでキーワードを検索すると、...

ウェブマスターネットワークニュース: アリババがXiami.comを買収、5d6dがサービス停止を発表

1. タオバオが様相を変え、ソーシャルショッピングガイドサイトになる最近、百度で美麗碼や莫孤街などの...

有名なブログを作るには、粘り強さだけでは不十分

最近、偶然、Lu Songsong 氏の「有名なブログを作るにはどのくらいの時間がかかりますか?」と...

Baidu サイト アプリ トライアル: 独自の Web サイトを Web アプリに変える

序文このタイトル全体を見ると、多くの人が「Web アプリとは何ですか? Baidu サイト アプリと...

2022 年の DevOps: 成功と課題

2022 年になると、セキュリティと価値が DevOps の 2 つの重要な側面になります。しかし、...

QingCloud が CNCF に参加: オープンソース エコシステムに貢献し、クラウドネイティブ アプリケーションの推進を継続

エンタープライズレベルのフルスタッククラウドICTサービスプロバイダーであるQingCloudは最近...

中小企業のオンラインマーケティングを体系的に行う方法(第4回)ターゲットユーザー分析

これまでの 3 つの記事では、オンライン マーケティングの 2 つの主要な側面、つまりコミュニケーシ...

Baiduのアルゴリズムは重要だが、SEO担当者はそれほど心配する必要はない

SEO Kongcheng は、Baidu のアルゴリズムにはあまり注意を払う必要がないと提案してい...

リリース戦略の選択: ZadigX、Alibaba Cloud、Argo、Spinnaker、Harness、Codefresh...

ソフトウェアの開発と運用の分野において、グレースケール リリースは、潜在的なリスクと影響を軽減するた...

WaveCom-エストニア/月額5.6ドル特別価格kvm仮想VPS(1Gメモリ)

Wavecom は、エストニアの老舗企業 (登録番号: 10756058) で、2001 年から事業...

bitaccel-7 USD/3G RAM/60G HDD/1T フロー/ダラス

bitacce の最後のプロモーションは 6 か月前でした。今回は、ダラス データ センターにある ...

Witkey ウェブサイトのボトルネックが明らかに、O2O モデルが今後の道となる可能性

現在運営されているウィトキーサイトの中で、竹八街は最も人気のあるサイトです。老舗のウィトキーサイトと...

Hyper-V リモート管理でどこからでもサーバーを実行

Hyper-V マネージャーは、Microsoft の Hyper-V を管理するためのデフォルトの...

bigrock - .net ドメイン名の登録には 3.69 ドル、.space ドメイン名の登録には 3.19 ドル

インドの有名なIDCマーチャントであるbigrockは、インドと米国の両方で企業を登録しています。サ...

クラウド移行チェックリストに必須の 7 つのステップ

データとアプリケーションをクラウドに移行する企業は、いくつかの考慮事項を理解し、クラウド移行を完了す...