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

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

推薦する

アーカイブ、バックアップ、災害復旧を通じてマルチクラウドデータ保護を実現する方法

マルチクラウド ユーザーは、どのようにして災害復旧、バックアップ、アーカイブを効果的に統合できるでし...

VMware のブリッジ ネットワークと NAT ネットワーク モードを理解する方法

まず、VMware の学習で遭遇した問題が理解できなかったので、それ以上続けるつもりはありませんでし...

Kubernetesのステートフルアプリケーション管理について話す

「Kubernetes ワークロード管理」では、主にステートレスアプリケーションの管理について紹介し...

バーチャルカード: Alipay チャージ + PayPal の認証 + Googleplay バーチャルクレジットカード

本日ご紹介するのは、バーチャルカードです。一言で言えば、バーチャルカードは使い過ぎない、非常に簡単に...

hostunmetered - 日本専用サーバー/1Gbps帯域幅/3ネットワーク直接接続

日本の専用サーバーを安く直接購入することはできますか?日本国内の多くのコンピュータルームは、基本的に...

Kuba.com の興隆と衰退

最近、国美の電子商取引プラットフォームである国美オンラインは、「国美オンライン」を「Kuba.com...

百度によるiQiyiの買収:動画サイトの未来がより明確になる

11月7日の午後、いつになく息苦しい百度ビルで、唐和松氏はノートを手に、2回の会議の合間に我が新聞の...

クラウドネイティブ データ ウェアハウスは、大規模クラスター内の関連クエリのパフォーマンス問題をどのように解決するのでしょうか?

著者 |ユ・イー序文近年、データベース システムによって提供されるデータの量は飛躍的に増加しており、...

アリ副社長の于燕氏:タオバオは明日、販売業者向けに「タオバオ番号」を公開する

9月24日、アリババグループの于燕副社長は本日メディアに対し、淘宝は明日淘宝アカウントを販売者に開放...

私にとって Docker とは何を意味しますか?それが私を変えた

Windows 向け Docker サポート気がつけば、私は Docker を使い始めてほぼ 5 年...

画像の最適化はもはや難しくありません。半分の労力で 2 倍の結果を達成するための鍵はイノベーションです。

検索エンジンの誕生以来、画像はウェブサイトの最適化に影響を与える重要な要素となっています。これは、検...

Qixi電子商取引ブランドのマーケティング事例の分析

今年も下半期が始まったばかりですが、すでに多くのブランドが派手なマーケティングで先陣を切り、市場を掌...

インターネットSEOから:個人の生活のSEO最適化について語る

SEO に長年取り組んでいると、人生でちょっとしたことに遭遇したときに、それを自然に最適化と関連付け...

強化された制御、統合、スケーラビリティ、コンテナサポートを備えた Red Hat Ansible Tower 3.3 がリリースされました

オープンソース ソリューションの大手グローバル プロバイダーである Red Hat, Inc. (N...

clouveo: 月額 2.1 ドルから、ロサンゼルス\アムステルダム、無制限のトラフィック、カスタム ISO をサポート、Windows が付属

clouveo は、現在から 7 月 23 日まで、米国ロサンゼルスとオランダのアムステルダムのデー...