【木棉花】分布式数据库 原创 精华

木棉花沈泳鑫
发布于 2021-8-25 18:48
1.3w浏览
5收藏

前言

继上一篇轻量级偏好数据库的学习,为了让大伙更好的了解学习数据库的类型,我今天就推出分布式数据库的学习,如果还不清楚轻量级偏好数据库的童鞋,建议查看我的上一篇学习笔记:【木棉花】:轻量级偏好数据库学习笔记–沈泳鑫,因为分布式数据库和轻量级数据库之间是有很多相识之处的。
为了更好地熟练掌握鸿蒙手机应用开发,为了供大家更方便的学习鸿蒙手机的应用开发,我会将所有的笔记都整理到Awesome-HarmonyOS_木棉花中,更多详细学习资料请查看Awesome-HarmonyOS_木棉花


正文

基本概念

相信大家看完我的 “轻量级偏好数据库” 的学习笔记之后,已经是清楚什么是键值对了吧。那轻量级偏好数据库是以键值对的形式在存储数据,同样的,分布式数据库也是以键值对的形式在存储数据的。那有童鞋就会问了,没事整那么多数据库干什么呢,轻量级偏好数据库和分布式数据库之间的差异在哪呢,官网上对分布式数据库的解释是这样的:“通过结合帐号、应用和数据库三元组,分布式数据服务对属于不同的应用的数据进行隔离,保证不同应用之间的数据不能通过分布式数据服务互相访问。在通过可信认证的设备间,分布式数据服务支持应用数据相互同步,为用户提供在多种终端设备上一致的数据访问体验。” 那通俗易懂的来讲就是分布式数据库除了可以存储数据,还是可以让多台设备共用一个数据库,它和轻量级偏好数据的区别就在于它可以实现设备间数据的同步。这也是分布式数据库的优势所在,那根据这一功能,我们就可以实现出双人小游戏了。

创建工程

打开DevEco Studio,点击左上角的File,点击New,再选择New Project,选择Empty Ability(java) ,点击Next。
【木棉花】分布式数据库-鸿蒙开发者社区
将工程命名为DistributeDataBase,在Project Type中选择Application,选择API 5,并且在Device Type中选择Phone选项,点击Finish。,工程就创建完成了。
【木棉花】分布式数据库-鸿蒙开发者社区

设计UI界面

那我就把UI界面设计得与轻量级偏好数据库的界面是一样的,这就便于我们来对比学习分布式数据库的功能还有加深对轻量级偏好数据库的印象。

效果界面:

【木棉花】分布式数据库-鸿蒙开发者社区
与轻量级偏好数据库相同,需要在entry>src>main>java>resources>base>graphic增加两个名字分别为background_button和background_text的文件(具体操作请参考上一篇文章)。
background_button文件代码如下:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
       ohos:shape="rectangle">
    <corners
        ohos:radius="100vp"/>
    <solid
        ohos:color="#007DFF"/>
</shape>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

background_text文件代码如下:

<?xml version="1.0" encoding="UTF-8" ?>
<shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
       ohos:shape="rectangle">
    <solid
        ohos:color="#FFFFFF"/>
</shape>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

那接下来就可以在ability_main.xml文件中设置UI界面了。

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_parent"
    ohos:width="match_parent"
    ohos:orientation="vertical">

    <Text
        ohos:id="$+id:text_fruit_tag"
        ohos:height="35vp"
        ohos:width="match_parent"
        ohos:background_element="$graphic:background_text"
        ohos:layout_alignment="left"
        ohos:text="Fruit"
        ohos:text_size="85"
        ohos:right_margin="20vp"
        ohos:left_margin="20vp"
        ohos:text_color="#000000"
        ohos:top_margin="25vp"
        />

    <TextField
        ohos:id="$+id:text_fruit"
        ohos:height="35vp"
        ohos:width="match_parent"
        ohos:background_element="$graphic:background_text"
        ohos:layout_alignment="left"
        ohos:hint="请输入水果名称..."
        ohos:text_size="50"
        ohos:right_margin="20vp"
        ohos:left_margin="20vp"
        ohos:text_color="#000000"
        ohos:top_margin="25vp"
        ohos:basement="#000099"
        />

    <Text
        ohos:id="$+id:text_number_tag"
        ohos:height="35vp"
        ohos:width="match_parent"
        ohos:background_element="$graphic:background_text"
        ohos:layout_alignment="left"
        ohos:text="Number"
        ohos:text_size="85"
        ohos:right_margin="20vp"
        ohos:left_margin="20vp"
        ohos:text_color="#000000"
        ohos:top_margin="25vp"
        />

    <TextField
        ohos:id="$+id:text_number"
        ohos:height="35vp"
        ohos:width="match_parent"
        ohos:background_element="$graphic:background_text"
        ohos:layout_alignment="left"
        ohos:hint="请输入数字..."
        ohos:text_size="50"
        ohos:right_margin="20vp"
        ohos:left_margin="20vp"
        ohos:text_color="#000000"
        ohos:top_margin="25vp"
        ohos:basement="#000099"
        />

    <Button
        ohos:id="$+id:write_btn"
        ohos:width="match_parent"
        ohos:height="35vp"
        ohos:text="Write DB"
        ohos:background_element="$graphic:background_button"
        ohos:text_size="50"
        ohos:text_color="#FFFFFF"
        ohos:top_margin="25vp"
        ohos:right_margin="20vp"
        ohos:left_margin="20vp"
        />

    <Button
        ohos:id="$+id:read_btn"
        ohos:width="match_parent"
        ohos:height="35vp"
        ohos:text="Read DB"
        ohos:background_element="$graphic:background_button"
        ohos:text_size="50"
        ohos:text_color="#FFFFFF"
        ohos:top_margin="25vp"
        ohos:right_margin="20vp"
        ohos:left_margin="20vp"
        />

    <Button
        ohos:id="$+id:delete_btn"
        ohos:width="match_parent"
        ohos:height="35vp"
        ohos:text="Delete DB File"
        ohos:background_element="$graphic:background_button"
        ohos:text_size="50"
        ohos:text_color="#FFFFFF"
        ohos:top_margin="25vp"
        ohos:right_margin="20vp"
        ohos:left_margin="20vp"
        />
</DirectionalLayout>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.

代码解读:

ohos:orientation=“vertical” 为排列方式为垂直排布。
ohos:background_element=“$graphic:background_text” 为背景引用为graphic文件下background_text的内容。
ohos:layout_alignment=“left” 对齐方式为左对齐
ohos:right_margin=“20vp” 为与右边组件的距离为20vp
ohos:hint=“请输入水果名称…” 为在输入框提示输入“请输入水果名称…”

申请权限

相比于轻量级偏好数据库,分布式数据库还需要添加相关的权限。
在config.json的abilities之前添加非敏感权限

"reqPermissions": [
      {
        "name": "ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE"
      },
      {
        "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO"
      },
      {
        "name": "ohos.permission.GET_BUNDLE_INFO"
      },
      {
        "name": "ohos.permission.DISTRIBUTED_DATASYNC"
      }
    ],
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

同时我们还需要在java>com.example.mydistributedatabase>slice>MainAbility中通过弹窗的形式动态申请数据交互的敏感权限,在onStart中添加

        requestPermissionsFromUser(new String[]{"ohos.permission.DISTRIBUTED_DATASYNC"},0);
  • 1.

创建分布式数据库

那我们接下来就可以在java>com.example.mydistributedatabase>slice>MainAbilitySlice中实现出数据库了。
首先还是先定义数据:

    private static final int SHOW_TIME = 1500; //提示框展示时间
    private Button buttonWrite;
    private Button buttonRead;
    private Button buttonDelete;
    private TextField textFieldFruit;
    private TextField textFieldNumber;
    private static final HiLogLabel TAG = new HiLogLabel(HiLog.LOG_APP,0x12345,"signal"); //输出控制台,用于输出调试
    private static final String STROE_ID = "mydistributedatabase"; //分布式数据库的名称
    private static KvManager kvManager; //定义一个数据库管理类,用建立数据库之前必须先定义和实例化数据库管理类对象
    private static SingleKvStore singleKvStore; // 定义一个分布式数据库对象
    private static String Fruit = null; //用于读取我们写入数据库中对应“fruit”的值
    private static String Number = null; //用于读取我们写入数据库中对应“number”的值
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

写一个名为createManager的函数用于创建数据库管理类

private KvManager createManager() { //创建分布式数据库管理器实例KvManager
        KvManager kvManager = null;
        try {
            KvManagerConfig kvManagerConfig = new KvManagerConfig(this);
            kvManager = KvManagerFactory.getInstance().createKvManager(kvManagerConfig); //实例化kvManager
        } catch (KvStoreException exception) {
            HiLog.info(TAG, "some exception happen!"); //如果出现错误就输出“some exception happen!”
        }
        return kvManager;
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

再写一个函数用于创建数据库

private SingleKvStore createDb(KvManager kvManager) { //借助KvManager创建SINGLE_VERSION分布式数据库
        SingleKvStore singleKvStore = null;
        try {
            Options options = new Options();
            options.setCreateIfMissing(true).setEncrypt(false).setKvStoreType(KvStoreType.SINGLE_VERSION);
            singleKvStore = kvManager.getKvStore(options,STROE_ID);
        } catch (KvStoreException exception) {
            HiLog.info(TAG,"some exception happen!");
        }
        return singleKvStore;
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

写一个函数用于订阅数据库中数据的变化

private void subscribeDb(SingleKvStore singleKvStore) { //订阅分布式数据库中数据变化,如果分布式数据库中有数据的变化,会自动调用onChange函数
        class KvStoreObserveClient implements KvStoreObserver {
            @Override
            public void onChange(ChangeNotification notification) {
                Fruit = queryContact("fruit");
                Number = queryContact("number");
            }
        }
        KvStoreObserver kvStoreObserver = new KvStoreObserveClient();
        singleKvStore.subscribe(SubscribeType.SUBSCRIBE_TYPE_ALL,kvStoreObserver);
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

分别写一个函数用于实现写入操作还有读操作

private void writeData(String key,String value) { //往数据库中写入的函数
        if (key == null || key.isEmpty()|| value == null|| value.isEmpty()) {
            return;
        }
        singleKvStore.putString(key,value); //写入的操作
    }
    private String queryContact(String key) { //查询的函数
        try {
            return singleKvStore.getString(key); //返回数据库中key对应的值
        } catch (KvStoreException exception) {
            return null;
        }
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

写一个函数调用创建管理类还有数据库的函数用于初始化数据库

private void initDbManager() { //用于初始化数据库
        kvManager = createManager(); //实例化kvManager
        singleKvStore = createDb(kvManager);  //借助KvManager创建SINGLE_VERSION分布式数据库
        subscribeDb(singleKvStore); //订阅分布式数据库中数据变化
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

写一个函数可以用于弹出提示窗口

    private void showTip(String message) { //展示一个弹出窗口
        new ToastDialog(this)
                .setText(message).setDuration(SHOW_TIME).show();
    }
  • 1.
  • 2.
  • 3.
  • 4.

再写三个按钮对应的点击事件

    private void Write() {
        buttonWrite.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                Fruit = textFieldFruit.getText();
                Number = textFieldNumber.getText();
                if (Fruit != null && Number != null && !Fruit.isEmpty() && !Number.isEmpty()){
                    writeData("fruit",Fruit);
                    writeData("number",Number);
                    showTip("Write to DB file success");
                } else {
                    showTip("Please input number");
                }
            }
        });
    }
    private void Read() {
        buttonRead.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                if (Fruit == null || Number == null)
                    showTip("Please input number");
                else
                    showTip("fruit: " + Fruit + ",number: " + Number);
            }
        });
    }
    private void Delete() {
        buttonDelete.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                try {
                    Fruit = null;
                    Number = null;
                    kvManager.closeKvStore(singleKvStore);
                    kvManager.deleteKvStore(STROE_ID); //删除数据库
                    showTip("数据库删除成功");
                } catch (Exception exception) {
                    showTip("请先建立数据库再删除");
                }
            }
        });
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.

最后在onStart中调用刚刚实现的函数

buttonWrite = (Button) findComponentById(ResourceTable.Id_write_btn); // 让定义的按钮获取在xml布局中定义的按钮的id,与xml布局中的输入按钮进行绑定
        buttonRead = (Button) findComponentById(ResourceTable.Id_read_btn);// 与xml布局中的读取按钮进行绑定
        buttonDelete = (Button)findComponentById(ResourceTable.Id_delete_btn);
        textFieldFruit = (TextField) findComponentById(ResourceTable.Id_text_fruit);
        textFieldNumber = (TextField) findComponentById(ResourceTable.Id_text_number);
        initDbManager(); //用于初始化数据库,也就是实例化kvManager和singleKvStore
        Write(); //对应Write DB的点击事件
        Read(); //对应Read DB的点击事件
        Delete();
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

那么一个简单的分布式数据库就完成了。那接下来我们就需要调用两个模拟器来查看效果了。
【木棉花】分布式数据库-鸿蒙开发者社区
【木棉花】分布式数据库-鸿蒙开发者社区
那这样两台模拟器就调用出来了,那现在我们让这两台模拟器可以同时运行
【木棉花】分布式数据库-鸿蒙开发者社区
然后在点击运行就可以了。
在其中一台设备输入水果的名称再输入一个数字,再点击“Wrtie DB”
【木棉花】分布式数据库-鸿蒙开发者社区
在另外一台设备点击读取按钮,就可以读取数据库中的数据
【木棉花】分布式数据库-鸿蒙开发者社区
点击删除按钮就可以删除数据库了
【木棉花】分布式数据库-鸿蒙开发者社区

结语

源码就放在附件中了,可以供大家下载之后跑一下试试看效果,感兴趣的可以一步接一步跟着编写。再不要脸的重申一遍更多学习资料学习笔记,请关注Awesome-HarmonyOS_木棉花,这份学习笔记也会写入其中。如果有遇到什么问题,或者查找出其中的错误之处,或者能够优化代码和界面,也欢迎各位在评论区留言讨论,让我们一起学习进步!
【木棉花】分布式数据库-鸿蒙开发者社区
【木棉花】分布式数据库-鸿蒙开发者社区

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
MyDistributeDataBase.rar 1.1M 37次下载
已于2021-8-25 18:48:02修改
11
收藏 5
回复
举报
11
3
5
3条回复
按时间正序
/
按时间倒序
红叶亦知秋
红叶亦知秋

感谢分享。(文末表情包过于魔性)

回复
2021-8-26 10:35:33
深开鸿
深开鸿

你这个也太魔性了吧

回复
2021-8-26 11:18:51
爱吃土豆丝的打工人
爱吃土豆丝的打工人

瞅一瞅,看一看  学习中、~

1
回复
2021-8-26 14:02:31


回复
    相关推荐