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 を騙す

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

推薦する

ストレージコストがクラウドコンピューティングのTCOに与える影響を理解する

ユーザーが支払うクラウド コンピューティング料金は、クラウド コンピューティング サービス プロバイ...

SEO とユーザー エクスペリエンスの接続が失われた場合はどうすればよいでしょうか?

この記事を書く準備をするにあたって、まずは祈りを捧げましょう。マレーシア航空便が連絡不能になってから...

オンライン配車サービスは大きな転換点を迎える

滴滴出行がユーザー情報の問題により規制当局から市場からの撤退を命じられた後、オンライン配車サービス市...

budgetvm-サーバーを1台購入すると1台無料、最大150ドル/4台のコンピュータルーム

budgetvm は、ローエンド サーバー市場で一定の評判や規模を持っています。現在、5,000 台...

内部リンク構築を正確に改善して減量を防ぐ

最近、フォーラムでウェブマスターが内部リンクの構築について議論しているのを見ました。Baidu はウ...

Akamai IoT エッジ プラットフォームをベースにしたサーバーレス位置情報共有アプリケーションの構築方法

地理的位置に関連するアプリケーションについては、誰もがよくご存知だと思います。 IMソフトウェアでの...

dogyun: Broken Station フォーラム - カスタマイズされた VPS、生涯 20% オフ、香港\韓国\米国 cn2 など、月額 12 元から

国内の大物が立ち上げたクラウドサーバーブランドDogyunは現在、「 Bazhan Forum 」向...

シュナイダーエレクトリック: アマゾン ウェブ サービスと提携してスマートなグローバル サプライ チェーンを推進

シュナイダーエレクトリックは2023年半ばに、エネルギー管理と自動化の専門知識をAIモデルに統合し、...

テンセントIDC製品群は、新しいインフラの進歩を促進するためにフルシナリオのサービスエコシステムを構築します

[51CTO.com からのオリジナル記事] データ センターは、情報が集中的に処理、保存、交換され...

ftpit: バレンタインデーに50%オフ、ウェブサイト構築におすすめ、安価で安定したVPSベンダー

ftpit はバレンタインデー プロモーションを実施しています。これはこれまでで最大の割引となるはず...

IaaS 環境における SaaS (Security as a Service) モデルの分析

1 クラウドコンピューティングIaaSの開発IaaS はインフラストラクチャ レベルのクラウド コン...

マルチクラウドアーキテクチャを計画する方法

マルチクラウド アーキテクチャは現在、ほとんどの組織が採用しているクラウド コンピューティング戦略の...

vhost: ベトナム VPS、無制限トラフィック、$3.52/1g メモリ/20g ハードディスク

ベトナムの会社であるvhost.vn (0310213840) は、8年間運営されています。同社の事...

Containerd は Docker と同じくらい簡単に使用できますか?

[[419814]]先ほど、ctr を使用して containerd イメージ コンテナーを管理する...