HarmonyOS Sample之DataAbility RDB数据库操作

发布时间:2025-05-15 16:35:21 作者:益华网络 来源:undefined 浏览量(4) 点赞(3)
摘要:想了解更多内容,请访问: 和华为官方合作共建的鸿蒙技术社区 https://harmonyos.51cto.com DataAbility RDB数据库操作 介绍 使用Data模板的Ability(以下简称“Data”)有助于应用管理其自身和其他应用存储数据的访问,并

想了解更多内容,请访问:

和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

DataAbility RDB数据库操作

介绍

使用Data模板的Ability(以下简称“Data”)有助于应用管理其自身和其他应用存储数据的访问,并提供与其他应用共享数据的方法。Data既可用于同设备不同应用的数据共享,也支持跨设备不同应用的数据共享。

数据的存放形式多样,可以是数据库,也可以是磁盘上的文件。Data对外提供对数据的增、删、改、查,以及打开文件等接口,这些接口的具体实现由开发者提供。

本示例演示了如何使用Data Ability对RDB数据库进行增、删、改、查,以及读取文本文件。

模仿手机的备忘录,实现了简单的操作。

搭建环境

安装DevEco Studio,详情请参考DevEco Studio下载。

设置DevEco Studio开发环境,DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:

如果可以直接访问Internet,只需进行下载HarmonyOS SDK操作。

如果网络不能直接访问Internet,需要通过代理服务器才可以访问,请参考配置开发环境。

步骤

1.创建一个DataAbility和数据库常量类

a.创建一个Empty DataAbility

entity右键,New- Ability-Empty Data Ability,然后输入名称 NoteDataAbility

b.创建一个数据库常量类 Const.java

存放数据库名称、表名称、字段列名称、存储路径等

需要注意的是,

BASE_URI 3个杠后面的部分要和config.json Data Ability 声明的uri完全一致,否则应用无法启动

/**  * Const  */ public class Const {     /**      * DataAbility base uri      * scheme:协议方案名,固定为“dataability”,代表Data Ability所使用的协议类型。      * authority:设备ID。如果为跨设备场景,则为目标设备的ID;如果为本地设备场景,则不需要填写。      * path:资源的路径信息,代表特定资源的位置信息。      * query:查询参数。      * fragment:可以用于指示要访问的子资源。      * 本地设备的“device_id”字段为空,因此在“dataability:”后面有三个“/”      *      * BASE_URI 3个杠后面的部分要和config.json  Data Ability 声明的uri完全一致,否则应用无法启动      *      */     public static final String BASE_URI = "dataability:///ohos.samples.dataability.NoteDataAbility";     /**      * Database name      */     public static final String DB_NAME = "note.db";     /**      * Database table name      */     public static final String DB_TAB_NAME = "note";     /**      * Database column name:Id      */     public static final String DB_COLUMN_ID = "Id";     /**      * Database column name:noteTitle      */     public static final String DB_COLUMN_TITLE = "noteTitle";     /**      * Database column name:writeTime      */     public static final String DB_COLUMN_TIME = "writeTime";     /**      * Database column name:noteCategory      */     public static final String DB_COLUMN_CATEGORY = "noteCategory";     /**      * Database column name:noteContent      */     public static final String DB_COLUMN_CONTENT = "noteContent";     /**      * Database data path      */     public static final String DATA_PATH = "/note";     /**      * 文件名称      */     public static final String FILE_NAME = "userdataability.txt"; }

c.config.json相关配置

config.json涉及NoteDataAbility.java 的地方有3处,

第1处在module对象下,

第2处是abilities对象下,

permissions表示其他应用的能力调用当前能力所需的权限。

默认情况下隐藏"visible"字段(值为false),表示仅本应用可访问该Data,开发人员可根据需求修改permissions、visible值、uri等内容。当外部应用需要访问/控制此数据库字段时,在该Data Ability配置中增加"visible": true,并在外面应用的配置文件config.json中申请permissions权限。

第3处是reqPermissions对象下,

说明:如果待访问的Data Ability是由本应用创建,则可以不声明该权限。

2.声明数据库存储对象和数据库配置

在NoteDataAbility.java 添加如下代码

//声明数据库存储对象 private RdbStore rdbStore; //数据库配置,指定数据库名称 private StoreConfig storeConfig = StoreConfig.newDefaultConfig(Const.DB_NAME);

3.实现打开RDB数据库回调函数

在NoteDataAbility.java 添加如下代码

// 管理数据库创建、升级和降级。 // 您可以创建一个子类来实现 #onCreate、#onUpgrade 或 #onOpen 方法。  // 如果一个数据库已经存在,它将被打开; 如果不存在数据库,则将创建一个数据库。  // 在数据库升级过程中,也会调用该类的方法。 private RdbOpenCallback rdbOpenCallback = new RdbOpenCallback() {     @Override     public void onCreate(RdbStore rdbStore) {         //创建表         rdbStore.executeSql(                 "create table if not exists " + Const.DB_TAB_NAME + "2 (" +                         Const.DB_COLUMN_ID + " integer primary key autoincrement ," +                         Const.DB_COLUMN_TITLE + " text not null," +                         Const.DB_COLUMN_CONTENT + " text not null," +                         Const.DB_COLUMN_TIME + " text not null," +                         Const.DB_COLUMN_CATEGORY + " text not null" +                         ")"         );     }     @Override     public void onUpgrade(RdbStore rdbStore, int i, int i1) {         //数据库升级     } };

4.初始化RDB数据库存储对象

在NoteDataAbility.java 添加如下代码

@Override public void onStart(Intent intent) {     super.onStart(intent);     HiLog.info(LABEL_LOG, "NoteDataAbility onStart");     //数据库帮助类     DatabaseHelper databaseHelper = new DatabaseHelper(this);     //初始化RDB数据库存储对象     rdbStore = databaseHelper.getRdbStore(storeConfig, 1, rdbOpenCallback); }

5.实现对数据库的基本操作函数

NoteDataAbility.java操作数据库的方法都需要自己实现,包括:添加、修改、查询、删除,还有打开文件,主要使用rdbStore对象。

@Override public ResultSet query(Uri uri, String[] columns, DataAbilityPredicates predicates) {     HiLog.info(LABEL_LOG, "NoteDataAbility query");     RdbPredicates rdbPredicates = DataAbilityUtils.createRdbPredicates(predicates, Const.DB_TAB_NAME);     return rdbStore.query(rdbPredicates, columns); } @Override public int insert(Uri uri, ValuesBucket value) {     HiLog.info(LABEL_LOG, "NoteDataAbility insert");     //long to int     int rowId = (int) rdbStore.insert(Const.DB_TAB_NAME, value);     //通知观察者数据发生变化     DataAbilityHelper.creator(this).notifyChange(uri);     return rowId; } @Override public int delete(Uri uri, DataAbilityPredicates predicates) {     //rdb 条件,通过DataAbilityUtils将DataAbilityPredicates转成 RdbPredicates     RdbPredicates rdbPredicates = DataAbilityUtils.createRdbPredicates(predicates, Const.DB_TAB_NAME);     //执行删除     int rowId = rdbStore.delete(rdbPredicates);     HiLog.info(LABEL_LOG, "%{public}s", "delete");     //通知观察者数据发生变化     DataAbilityHelper.creator(this).notifyChange(uri);     return rowId; } @Override public int update(Uri uri, ValuesBucket value, DataAbilityPredicates predicates) {     //rdb 条件,通过DataAbilityUtils将DataAbilityPredicates转成 RdbPredicates     RdbPredicates rdbPredicates = DataAbilityUtils.createRdbPredicates(predicates, Const.DB_TAB_NAME);     int rowId =rdbStore.update(value, rdbPredicates);     //通知观察者数据发生变化     DataAbilityHelper.creator(this).notifyChange(uri);     return rowId; } @Override public FileDescriptor openFile(Uri uri, String mode) {     //获取应用程序在设备内部存储器上存放文件的目录     File file = new File(getFilesDir(), uri.getDecodedQuery());     FileDescriptor fileDescriptor = null;     try {         FileInputStream fis = new FileInputStream(file);         //获取FD         fileDescriptor = fis.getFD();         //获取一个新的文件描述符,它是现有文件描述符的副本         return MessageParcel.dupFileDescriptor(fileDescriptor);     } catch (IOException e) {         e.printStackTrace();     }     return fileDescriptor; }

6.数据的订阅和通知

在NoteDataAbility.java 中, 我们看到insert/update/delete方法都有一行。

DataAbilityHelper.creator(this).notifyChange(uri); 

目的是在数据库数据发生变化时,通知数据的订阅者。

而在MainAbilitySlice.java 类中有如下方法,在OnStart()中被调用,实现了数据变化的订阅。

private void initDatabaseHelper() {     //创建实例     dataAbilityHelper = DataAbilityHelper.creator(this);     //注册一个观察者来观察给定 Uri 指定的数据,dataObserver表示 IDataAbilityObserver 对象     dataAbilityHelper.registerObserver(Uri.parse(Const.BASE_URI), dataAbilityObserver); }

同时,数据变化订阅方还需要实现IDataAbilityObserver接口,在数据变化时会自动回调,完成对应的逻辑处理。

//观察者模式,数据变化时回调 private final IDataAbilityObserver dataAbilityObserver=() -> {     HiLog.info(LABEL, "%{public}s", "database changed");     //筛选数据     initLists(this); }; 

当数据订阅者不再需要订阅Data变化时,则调用unregisterObserver​(Uri uri, IDataAbilityObserver dataObserver)方法取消。

@Override protected void onStop() {     super.onStop();     dataAbilityHelper.unregisterObserver(Uri.parse(Const.BASE_URI), dataAbilityObserver); }

观察者模式的作用在于当数据库表格的内容产生变化时,可以主动通知与该表格数据相关联的进程或者应用,从而使得相关进程或者应用接收到数据变化后完成相应的处理。

7.访问Data Ability,新建AddNoteAbility,在AddNoteAbilitySlice实现数据的添加和修改

开发者可以通过DataAbilityHelper类来访问当前应用或其他应用提供的共享数据。

DataAbilityHelper作为客户端,与提供方的Data进行通信。DataAbilityHelper提供了一系列与Data Ability通信的方法。

a.数据的添加

/**  * 保存数据  *  * @param component component  */ private void saveNote(Component component) {     ValuesBucket valuesBucket = new ValuesBucket();     TextField noteTitle = (TextField) findComponentById(ResourceTable.Id_add_note_title);     if (noteTitle.getText().isEmpty()) {         DialLogUtils dialog = new DialLogUtils(this, "标题不能为空!");         dialog.showDialog();         return;     }     TextField noteContent = (TextField) findComponentById(ResourceTable.Id_add_note_content);     if (noteContent.getText().isEmpty()) {         DialLogUtils dialog = new DialLogUtils(this, "内容不能为空!");         dialog.showDialog();         return;     }     Text noteCategory = (Text) findComponentById(ResourceTable.Id_add_note_category);     Text noteTime = (Text) findComponentById(ResourceTable.Id_add_note_time);     HiLog.debug(LABEL, "%{public}s", "saveNote, noteId:[" + noteId + "],noteCategory:" + noteCategory.getText());     int rowId;     //放入键值     valuesBucket.putString(Const.DB_COLUMN_TITLE, noteTitle.getText());     valuesBucket.putString(Const.DB_COLUMN_CATEGORY, noteCategory.getText());     valuesBucket.putString(Const.DB_COLUMN_CONTENT, noteContent.getText());     valuesBucket.putString(Const.DB_COLUMN_TIME, noteTime.getText());     try {         if (noteId.isEmpty()) {             HiLog.debug(LABEL, "%{public}s", "saveNote, insert");             //插入数据             rowId = dataAbilityHelper.insert(Uri.parse(Const.BASE_URI + Const.DATA_PATH), valuesBucket);             HiLog.debug(LABEL, "%{public}s", "insert,rowId:" + rowId);         } else {             HiLog.debug(LABEL, "%{public}s", "saveNote, update");             //指定修改谓语             DataAbilityPredicates predicates = new DataAbilityPredicates();             predicates.equalTo(Const.DB_COLUMN_ID, noteId);             //修改数据             rowId = dataAbilityHelper.update(Uri.parse(Const.BASE_URI + Const.DATA_PATH), valuesBucket, predicates);             HiLog.debug(LABEL, "%{public}s", "update,rowId:" + rowId);         }         //返回列表页         backListPage();     } catch (DataAbilityRemoteException | IllegalStateException exception) {         HiLog.error(LABEL, "%{public}s", "insert: dataRemote exception|illegalStateException");     } }

b.修改和删除数据

@Override public void onStart(Intent intent) {     super.onStart(intent);     //设置UI布局资源     super.setUIContent(ResourceTable.Layout_ability_add_note);     //     initDatabaseHelper();     //返回按钮     Component backButton = findComponentById(ResourceTable.Id_back_image);     backButton.setClickedListener(component -> terminateAbility());     TextField noteContent = (TextField) findComponentById(ResourceTable.Id_add_note_content);     //修改笔记     if (intent.hasParameter("Id")) {         HiLog.info(LABEL, "%{public}s", "change data coming");         noteId = intent.getStringParam("Id");         HiLog.info(LABEL, "%{public}s", "noteId:" + noteId);         if (noteId != null) {             DataAbilityPredicates predicates = new DataAbilityPredicates();             predicates.equalTo(Const.DB_COLUMN_ID, noteId);             //查询数据             NoteListItemInfo itemInfo = queryOne(predicates);             HiLog.info(LABEL, "%{public}s", "noteTitle:" + itemInfo.getNoteTitle() + ",category:" + itemInfo.getNoteCategory());             //设置显示             TextField noteTitle = (TextField) findComponentById(ResourceTable.Id_add_note_title);             noteTitle.setText(itemInfo.getNoteTitle());             noteContent.setText(itemInfo.getNoteContent());             Text category = (Text) findComponentById(ResourceTable.Id_add_note_category);             category.setText(itemInfo.getNoteCategory());             Text noteTime = (Text) findComponentById(ResourceTable.Id_add_note_time);             noteTime.setText(itemInfo.getNoteTime());             Component deleteButton = findComponentById(ResourceTable.Id_delete_image);             //设置删除按钮可用,只有修改笔记才能删除             deleteButton.setClickable(true);             //添加事件             deleteButton.setClickedListener(component -> {                 try {                     int rowId = dataAbilityHelper.delete(Uri.parse(Const.BASE_URI + Const.DATA_PATH), predicates);                     HiLog.info(LABEL, "%{public}s", "deleteNote,rowId:" + rowId);                     //返回列表页                     backListPage();                 } catch (DataAbilityRemoteException e) {                     HiLog.error(LABEL, "%{public}s", "delete: exception|DataAbilityRemoteException");                 }             });         }     } else {         Text timeText = (Text) findComponentById(ResourceTable.Id_add_note_time);         String time24 = sdf.format(new Date());         timeText.setText(time24);     }     //保存笔记     Component insertButton = findComponentById(ResourceTable.Id_finish_image);     insertButton.setClickedListener(this::saveNote); }

c.查询数据

private NoteListItemInfo queryOne(DataAbilityPredicates predicates) {     HiLog.info(LABEL, "%{public}s", "database query");     String[] columns = new String[]{             Const.DB_COLUMN_ID,             Const.DB_COLUMN_TITLE, Const.DB_COLUMN_TIME,             Const.DB_COLUMN_CATEGORY, Const.DB_COLUMN_CONTENT};     try {         ResultSet resultSet = dataAbilityHelper.query(                 Uri.parse(Const.BASE_URI + Const.DATA_PATH), columns, predicates);         //无数据         if (resultSet.getRowCount() == 0) {             HiLog.info(LABEL, "%{public}s", "query:No result found");             return null;         }         //         resultSet.goToFirstRow();         //根据列索引获取列值         String noteId = resultSet.getString(resultSet.getColumnIndexForName(Const.DB_COLUMN_ID));         String noteTitle = resultSet.getString(resultSet.getColumnIndexForName(Const.DB_COLUMN_TITLE));         String noteTime = resultSet.getString(resultSet.getColumnIndexForName(Const.DB_COLUMN_TIME));         String noteCategory = resultSet.getString(resultSet.getColumnIndexForName(Const.DB_COLUMN_CATEGORY));         String noteContent = resultSet.getString(resultSet.getColumnIndexForName(Const.DB_COLUMN_CONTENT));         Element image = ElementScatter.getInstance(getContext()).parse(ResourceTable.Graphic_icon_nodata);         HiLog.info(LABEL, "%{public}s", "set  show:" + noteCategory);         //         return new NoteListItemInfo(noteId, noteTitle, noteContent, noteTime, noteCategory, image);     } catch (DataAbilityRemoteException | IllegalStateException exception) {         HiLog.error(LABEL, "%{public}s", "query: dataRemote exception|illegalStateException");     }     return null; }

实践中遇到的小知识点记录一下

1. 如何监听 TextField 文本变更事件

/**  * 监听TextFiled 文本变化  */ private void initSearchBtnEvent(AbilitySlice slice) {     TextField searchTF = (TextField) findComponentById(ResourceTable.Id_tf_note_search);     //添加文本观察器 TextObserver 以检测文本是否发生更改。     searchTF.addTextObserver(new Text.TextObserver() {         @Override         public void onTextUpdated(String s, int i, int i1, int i2) {             HiLog.info(LABEL, "addTextObserver 按键事件触发.....");             //筛选数据             initLists(slice);         }     }); }

2. ListContainer 组件添加点击事件

在 Provider 中 getComponent添加,在初始化Provider时传递AbilitySlice对象过来

public ListItemProvider(List<ItemInfo> itemList, AbilityContext context,AbilitySlice slice) {     this.itemList = itemList;     this.context = context;     this.typeFactory = new ListTypeFactory();     this.slice=slice; } @Override public Component getComponent(int index, Component component, ComponentContainer componentContainer) {     Component itemComponent = component;     ViewHolder viewHolder;     if (itemComponent == null) {         itemComponent = LayoutScatter.getInstance(componentContainer.getContext())                 .parse(getItemComponentType(index), componentContainer, false);     }     viewHolder = typeFactory.getViewHolder(getItemComponentType(index), itemComponent);     viewHolder.setUpComponent(getItem(index), context);     //设置点击事件     itemComponent.setClickedListener(component1 -> {         //获取noteId         String noteId="";         if(getItem(index) instanceof NoteListItemInfo){             //HiLog.debug(LABEL, "%{public}s", "ItemInfo instanceof SingleButtonDoubleLineListItemInfo");             noteId=((NoteListItemInfo)getItem(index)).getNoteId();         }         HiLog.debug(LABEL, "%{public}s", "noteId:" + noteId);         //1.携带笔记ID参数,跳转到AddNoteAbilitySlice         Intent intent = new Intent();         if(noteId!=null){             //保存要传递的参数             intent.setParam("Id", noteId);             Operation operation = new Intent.OperationBuilder()                     .withDeviceId("")                     .withBundleName("com.buty.samples")                     .withAbilityName(AddNoteAbility.class).build();             intent.setOperation(operation);             slice.startAbility(intent);         }else {             HiLog.error(LABEL, "%{public}s", "noteId is null");         }     });     return itemComponent; }

效果展示

文章相关附件可以点击下面的原文链接前往下载。

原文链接:https://harmonyos.51cto.com/posts/7386

想了解更多内容,请访问:

和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

二维码

扫一扫,关注我们

声明:本文由【益华网络】编辑上传发布,转载此文章须经作者同意,并请附上出处【益华网络】及本页链接。如内容、图片有任何版权问题,请联系我们进行处理。

感兴趣吗?

欢迎联系我们,我们愿意为您解答任何有关网站疑难问题!

您身边的【网站建设专家】

搜索千万次不如咨询1次

主营项目:网站建设,手机网站,响应式网站,SEO优化,小程序开发,公众号系统,软件开发等

立即咨询 15368564009
在线客服
嘿,我来帮您!