想了解更多内容,请访问:
51CTO和华为官方合作共建的鸿蒙技术社区
https://harmonyos.51cto.com
介绍之前给大家介绍过【#星光计划1.0# HarmonyOS 分布式之仿抖音应用】,此次给大家介绍一下基于鸿蒙分布式数据服务开发的聊天室应用,模拟现实中的聊天室对话,可以与小伙伴们互动、分享自己的故事给小伙伴。
效果演示分布式数据服务
官方介绍:分布式数据服务主要实现用户设备中应用程序的数据内容的分布式同步。当设备1上的应用A在分布式数据库中增、删、改数据后,设备2上的应用A也可以获取到该数据库变化,总结一句话:多个设备共用一个数据库。
主页代码没有特别复杂的逻辑,主要是分布式数据服务的使用,关键地方都有注释。
简单案例1、config.json配置
- import com.ldd.myapp.bean.ChatDataBean; import com.ldd.myapp.provider.ChatProvider;
- import com.ldd.myapp.util.Tools; import ohos.aafwk.ability.AbilitySlice;
- import ohos.aafwk.content.Intent; import ohos.agp.components.Button;
- import ohos.agp.components.ListContainer; import ohos.agp.components.TextField;
- import ohos.app.Context; import ohos.bundle.IBundleManager;
- import ohos.data.distributed.common.*; import ohos.data.distributed.user.SingleKvStore;
- import ohos.utils.zson.ZSONArray; import ohos.utils.zson.ZSONObject;
- import java.util.ArrayList;
- import java.util.List;
- import static ohos.security.SystemPermission.DISTRIBUTED_DATASYNC;
- public class MainAbilitySlice extends AbilitySlice {
- private Context mContext; // 聊天列表
- private ListContainer lcList; // 聊天数据
- private final List
listData = new ArrayList<>(); // 聊天数据适配器 - private ChatProvider chatProvider; // 输入框
- private TextField tfContent; // 发送按钮
- private Button btnSend;
- // 分布式数据库管理器 private KvManager kvManager;
- // 分布式数据库 private SingleKvStore singleKvStore;
- // 数据库名称 private static final String STORE_NAME = "ChatStore";
- // 存入的列表数据key private static final String KEY_DATA = "key_data";
- // 存入的头像索引 private static final String KEY_PIC_INDEX = "key_pic_index";
- private int picIndex = 0;
- @Override public void onStart(Intent intent) {
- super.onStart(intent); super.setUIContent(ResourceTable.Layout_ability_main);
- mContext = this; requestPermission();
- initComponent(); initDatabase();
- }
- private void requestPermission() {
- if (verifySelfPermission(DISTRIBUTED_DATASYNC) != IBundleManager.PERMISSION_GRANTED) { if (canRequestPermission(DISTRIBUTED_DATASYNC)) {
- requestPermissionsFromUser(new String[]{DISTRIBUTED_DATASYNC}, 0); }
- } }
- private void initComponent() { lcList = (ListContainer) findComponentById(ResourceTable.Id_lc_list);
- tfContent = (TextField) findComponentById(ResourceTable.Id_tf_content); tfContent.setAdjustInputPanel(true);
- btnSend = (Button) findComponentById(ResourceTable.Id_btn_send); btnSend.setEnabled(false);
- // 初始化适配器
- chatProvider = new ChatProvider(mContext, listData); lcList.setItemProvider(chatProvider);
- // 输入框内容变化监听
- tfContent.addTextObserver((text, start, before, count) -> { btnSend.setEnabled(text.length() != 0);
- }); // 点击发送按钮
- btnSend.setClickedListener(component -> { String content = tfContent.getText().trim();
- listData.add(new ChatDataBean(Tools.getDeviceId(mContext),picIndex,content)); // 存入数据库中
- singleKvStore.putString(KEY_DATA, ZSONObject.toZSonString(listData));
- // 清空输入框 tfContent.setText("");
- }); }
- private void initDatabase() { // 创建分布式数据库管理器
- kvManager = KvManagerFactory.getInstance().createKvManager(new KvManagerConfig(this));
- // 数据库配置 Options options = new Options();
- options.setCreateIfMissing(true) // 设置数据库不存在时是否创建 .setEncrypt(false) // 设置数据库是否加密
- .setKvStoreType(KvStoreType.SINGLE_VERSION); //数据库类型 // 创建分布式数据库
- singleKvStore = kvManager.getKvStore(options, STORE_NAME); // 监听数据库数据改变
- singleKvStore.subscribe(SubscribeType.SUBSCRIBE_TYPE_ALL, new KvStoreObserver() { @Override
- public void onChange(ChangeNotification changeNotification) { List
insertEntries = changeNotification.getInsertEntries(); - List
updateEntries = changeNotification.getUpdateEntries(); - // 第一次存入数据,获取insertEntries if(insertEntries.size()>0){
- for (Entry entry : insertEntries) { if (KEY_DATA.equals(entry.getKey())) {
- // 回调为非UI线程,需要在UI线程更新UI getUITaskDispatcher().syncDispatch(() -> {
- listData.clear(); listData.addAll(ZSONArray.stringToClassList(entry.getValue().getString(),ChatDataBean.class));
- chatProvider.notifyDataChanged(); lcList.scrollTo(listData.size() - 1);
- }); }
- } }else if(updateEntries.size()>0){
- for (Entry entry : updateEntries) { if (KEY_DATA.equals(entry.getKey())) {
- // 回调为非UI线程,需要在UI线程更新UI getUITaskDispatcher().syncDispatch(() -> {
- listData.clear(); listData.addAll(ZSONArray.stringToClassList(entry.getValue().getString(),ChatDataBean.class));
- chatProvider.notifyDataChanged(); lcList.scrollTo(listData.size() - 1);
- }); }
- } }
- } });
- try {
- picIndex = singleKvStore.getInt(KEY_PIC_INDEX); singleKvStore.putInt(KEY_PIC_INDEX, picIndex + 1);
- } catch (KvStoreException e) { e.printStackTrace();
- // 没有找到,首次进入 if (e.getKvStoreErrorCode() == KvStoreErrorCode.KEY_NOT_FOUND) {
- picIndex = 0; singleKvStore.putInt(KEY_PIC_INDEX, picIndex + 1);
- } }
- }
- @Override protected void onStop() {
- super.onStop(); kvManager.closeKvStore(singleKvStore);
- } }
2、布局页面
- "reqPermissions": [ {
- "reason": "多设备协同", "name": "ohos.permission.DISTRIBUTED_DATASYNC",
- "usedScene": { "ability": [
- "MainAbility" ],
- "when": "always" }
- }, {
- "name": "ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE" },
- { "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO"
- }, {
- "name": "ohos.permission.GET_BUNDLE_INFO" }
- ]
3、MainAbilitySlice代码
xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:height="match_parent" - ohos:width="match_parent" ohos:alignment="center"
- ohos:orientation="vertical">
ohos:height="match_content" ohos:width="match_content" - ohos:text="数据:0" ohos:text_size="15fp"/>
- import ohos.aafwk.ability.AbilitySlice; import ohos.aafwk.content.Intent;
- import ohos.agp.components.Button; import ohos.agp.components.ListContainer;
- import ohos.agp.components.Text; import ohos.agp.components.TextField;
- import ohos.bundle.IBundleManager; import ohos.data.distributed.common.*;
- import ohos.data.distributed.user.SingleKvStore; import ohos.utils.zson.ZSONArray;
- import java.util.List;
- import static ohos.security.SystemPermission.DISTRIBUTED_DATASYNC;
- public class MainAbilitySlice extends AbilitySlice {
- // 显示数据 private Text text;
- // 分布式数据库管理器 private KvManager kvManager;
- // 分布式数据库 private SingleKvStore singleKvStore;
- // 数据库名称 private static final String STORE_NAME = "MyStore";
- // 存入的数据key private static final String KEY_COUNT = "key_count";
- @Override
- public void onStart(Intent intent) { super.onStart(intent);
- super.setUIContent(ResourceTable.Layout_ability_main); requestPermission();
- initDatabase(); initComponent();
- }
- private void requestPermission() {
- if (verifySelfPermission(DISTRIBUTED_DATASYNC) != IBundleManager.PERMISSION_GRANTED) { if (canRequestPermission(DISTRIBUTED_DATASYNC)) {
- requestPermissionsFromUser(new String[]{DISTRIBUTED_DATASYNC}, 0); }
- } }
- private void initDatabase() { // 创建分布式数据库管理器
- kvManager = KvManagerFactory.getInstance().createKvManager(new KvManagerConfig(this));
- // 数据库配置 Options options = new Options();
- options.setCreateIfMissing(true) // 设置数据库不存在时是否创建 .setEncrypt(false) // 设置数据库是否加密
- .setKvStoreType(KvStoreType.SINGLE_VERSION); //数据库类型 // 创建分布式数据库
- singleKvStore = kvManager.getKvStore(options, STORE_NAME); // 监听数据库数据改变
- singleKvStore.subscribe(SubscribeType.SUBSCRIBE_TYPE_ALL, new KvStoreObserver() { @Override
- public void onChange(ChangeNotification changeNotification) { List
insertEntries = changeNotification.getInsertEntries(); - List
updateEntries = changeNotification.getUpdateEntries(); - // 第一次存入数据,获取insertEntries if (insertEntries.size() > 0) {
- for (Entry entry : insertEntries) { if (KEY_COUNT.equals(entry.getKey())) {
- // 回调为非UI线程,需要在UI线程更新UI getUITaskDispatcher().syncDispatch(() -> {
- int count = entry.getValue().getInt(); text.setText("数据:"+count);
- }); }
- } } else if (updateEntries.size() > 0) {
- for (Entry entry : updateEntries) { if (KEY_COUNT.equals(entry.getKey())) {
- // 回调为非UI线程,需要在UI线程更新UI getUITaskDispatcher().syncDispatch(() -> {
- int count = entry.getValue().getInt(); text.setText("数据:"+count);
- }); }
- } }
- } });
- }
- private void initComponent() { text = (Text) findComponentById(ResourceTable.Id_text);
- Button button = (Button) findComponentById(ResourceTable.Id_button);
- // 点击事件 button.setClickedListener(component -> {
- try { int count = singleKvStore.getInt(KEY_COUNT);
- singleKvStore.putInt(KEY_COUNT, count + 1); } catch (KvStoreException e) {
- e.printStackTrace(); // 没有找到,首次进入
- if (e.getKvStoreErrorCode() == KvStoreErrorCode.KEY_NOT_FOUND) { int count = 0;
- singleKvStore.putInt(KEY_COUNT, count + 1); }
- } });
- } }
注释比较详细,主要注意2个点:
- 获取数据时加入try catch块,处理key未找到的情况 数据库数据改变监听回调是非UI线程,如果更新UI必须切换到UI线程
以上简单案例就是让你快速掌握分布式数据服务:多个设备相同的应用之间使用同一个数据库。
想了解更多内容,请访问:
51CTO和华为官方合作共建的鸿蒙技术社区
https://harmonyos.51cto.com