鴻蒙OS 創(chuàng)建Data

2020-09-18 10:10 更新

使用 Data 模板的 Ability 形式仍然是 Ability,因此,開(kāi)發(fā)者需要為應(yīng)用添加一個(gè)或多個(gè) Ability 的子類(lèi),來(lái)提供程序與其他應(yīng)用之間的接口。Data 為結(jié)構(gòu)化數(shù)據(jù)和文件提供了不同 API 接口供用戶使用,因此,開(kāi)發(fā)者需要首先確定好使用何種類(lèi)型的數(shù)據(jù)。本章節(jié)主要講述了創(chuàng)建 Data 的基本步驟和需要使用的接口。

確定數(shù)據(jù)存儲(chǔ)方式

確定數(shù)據(jù)的存儲(chǔ)方式,Data 支持以下兩種數(shù)據(jù)形式:

  • 文件數(shù)據(jù):如文本、圖片、音樂(lè)等。
  • 結(jié)構(gòu)化數(shù)據(jù):如數(shù)據(jù)庫(kù)等。

實(shí)現(xiàn) UserDataAbility

UserDataAbility 接收其他應(yīng)用發(fā)送的請(qǐng)求,提供外部程序訪問(wèn)的入口,從而實(shí)現(xiàn)應(yīng)用間的數(shù)據(jù)訪問(wèn)。Data 提供了文件存儲(chǔ)和數(shù)據(jù)庫(kù)存儲(chǔ)兩組接口供用戶使用。

文件存儲(chǔ)

開(kāi)發(fā)者需要在 Data 中重寫(xiě) FileDescriptor openFile (Uri uri, String mode)方法來(lái)操作文件:uri 為客戶端傳入的請(qǐng)求目標(biāo)路徑;mode 為開(kāi)發(fā)者對(duì)文件的操作選項(xiàng),可選方式包含“r”(讀), “w”(寫(xiě)), “rw”(讀寫(xiě))等。

MessageParcel 類(lèi)提供了一個(gè)靜態(tài)方法,用于獲取 MessageParcel 實(shí)例。通過(guò)dupFileDescriptor() 函數(shù)復(fù)制待操作文件流的文件描述符,并將其返回,供遠(yuǎn)端應(yīng)用使用。

示例:根據(jù)傳入的 uri 打開(kāi)對(duì)應(yīng)的文件

// 創(chuàng)建 messageParcel
MessageParcel messageParcel = MessageParcel.obtain();
File file = new File(uri.getDecodedPathList().get(1));
if (mode == null || !"rw".equals(mode)) {
    file.setReadOnly();
}
FileInputStream fileIs = new FileInputStream(file);
FileDescriptor fd = fileIs.getFD();

 
// 綁定文件描述符
return messageParcel.dupFileDescriptor(fd);

數(shù)據(jù)庫(kù)存儲(chǔ)

  1. 初始化數(shù)據(jù)庫(kù)連接。

系統(tǒng)會(huì)在應(yīng)用啟動(dòng)時(shí)調(diào)用 onStart()方法創(chuàng)建 Data 實(shí)例。在此方法中,開(kāi)發(fā)者應(yīng)該創(chuàng)建數(shù)據(jù)庫(kù)連接,并獲取連接對(duì)象,以便后續(xù)和數(shù)據(jù)庫(kù)進(jìn)行操作。為了避免影響應(yīng)用啟動(dòng)速度,開(kāi)發(fā)者應(yīng)當(dāng)盡可能將非必要的耗時(shí)任務(wù)推遲到使用時(shí)執(zhí)行,而不是在此方法中執(zhí)行所有初始化。

示例:初始化的時(shí)候連接數(shù)據(jù)庫(kù)

   private static final String DATABASE_NAME ="UserDataAbility.db";
   private static final String DATABASE_NAME_ALIAS = "UserDataAbility";
   private OrmContext ormContext = null;

    
   @Override
   public void onStart(Intent intent) {
       super.onStart(intent);
       DatabaseHelper manager = new DatabaseHelper(this);
       ormContext = manager.getOrmContext(DATABASE_NAME_ALIAS, DATABASE_NAME, BookStore.class);
   }

  1. 編寫(xiě)數(shù)據(jù)庫(kù)操作方法。

Ability 定義了 6 個(gè)方法供用戶處理對(duì)數(shù)據(jù)庫(kù)表數(shù)據(jù)的增刪改查。這 6 個(gè)方法在 Ability 中已默認(rèn)實(shí)現(xiàn),開(kāi)發(fā)者可按需重寫(xiě)。

方法 描述
ResultSet query(Uri uri, String[] columns, DataAbilityPredicates predicates) 查詢(xún)數(shù)據(jù)庫(kù)
int insert(Uri uri, ValuesBucket value) 向數(shù)據(jù)庫(kù)中插入單條數(shù)據(jù)
int batchInsert(Uri uri, ValuesBucket[] values) 向數(shù)據(jù)庫(kù)中插入多條數(shù)據(jù)
int delete(Uri uri, DataAbilityPredicates predicates) 刪除一條或多條數(shù)據(jù)
int update(Uri uri, ValuesBucket value, DataAbilityPredicates predicates) 更新數(shù)據(jù)庫(kù)
DataAbilityResult[] executeBatch(ArrayList<DataAbilityOperation> operations) 批量操作數(shù)據(jù)庫(kù)

這些方法的使用說(shuō)明如下:

  • query()

該方法接收三個(gè)參數(shù),分別是查詢(xún)的目標(biāo)路徑,查詢(xún)的列名,以及查詢(xún)條件,查詢(xún)條件由類(lèi) DataAbilityPredicates 構(gòu)建。根據(jù)傳入的列名和查詢(xún)條件查詢(xún)用戶表的代碼示例如下:

     public ResultSet query(Uri uri, String[] columns, DataAbilityPredicates predicates) {
         if (ormContext == null) {
             HiLog.error(this.getClass().getSimpleName(), "failed to query, ormContext is null");
             return null;
         }

      
         // 查詢(xún)數(shù)據(jù)庫(kù)
         OrmPredicates ormPredicates = DataAbilityUtils.createOrmPredicates(predicates,User.class);
         ResultSet resultSet = ormContext.query(ormPredicates, columns);
         if (resultSet == null) {
             HiLog.info(this.getClass(), "resultSet is null");
         }

      
         // 返回結(jié)果
         return resultSet;
     }

  • insert()

該方法接收兩個(gè)參數(shù),分別是插入的目標(biāo)路徑和插入的數(shù)據(jù)值。其中,插入的數(shù)據(jù)由 ValuesBucket 封裝,服務(wù)端可以從該參數(shù)中解析出對(duì)應(yīng)的屬性,然后插入到數(shù)據(jù)庫(kù)中。此方法返回一個(gè) int 類(lèi)型的值用于標(biāo)識(shí)結(jié)果。接收到傳過(guò)來(lái)的用戶信息并把它保存到數(shù)據(jù)庫(kù)中的代碼示例如下:

     public int insert(Uri uri, ValuesBucket value) {
         // 參數(shù)校驗(yàn)
         if (ormContext == null) {
             HiLog.error(this.getClass().getSimpleName(), "failed to insert, ormContext is null");
             return -1;
         }
         String path = uri.getPath();

      
         if (buildPathMatcher().getPathId(path) != PathId) {
             HiLog.info(this.getClass(), "UserDataAbility insert path is not matched");
             return -1;
         }

      
         // 構(gòu)造插入數(shù)據(jù)
         User user = new User();
         user.setUserId(value.getInteger("userId"));
         user.setFirstName(value.getString("firstName"));
         user.setLastName(value.getString("lastName"));
         user.setAge(value.getInteger("age"));
         user.setBalance(value.getDouble("balance"));

      
         // 插入數(shù)據(jù)庫(kù)
         boolean isSuccessed = true;
         try {
             isSuccessed = ormContext.insert(user);
         } catch (DataAbilityRemoteException e) {
             HiLog.error(TAG, "insert fail: " + e.getMessage());            
             throw new RuntimeException(e);        
         }
         if (!isSuccessed) {
             HiLog.error(this.getClass().getSimpleName(), "failed to insert");
             return -1;
         }
         isSuccessed = ormContext.flush();
         if (!isSuccessed) {
             HiLog.error(this.getClass().getSimpleName(), "failed to insert flush");
             return -1;
         }
         DataAbilityHelper.creator(this, uri).notifyChange(uri);
         int id = Math.toIntExact(user.getRowId());
         return id;
     }

  • batchInsert()

該方法為批量插入方法,接收一個(gè) ValuesBucket 數(shù)組用于單次插入一組對(duì)象。它的作用是提高插入多條重復(fù)數(shù)據(jù)的效率。該方法系統(tǒng)已實(shí)現(xiàn),開(kāi)發(fā)者可以直接調(diào)用。

  • delete()

該方法用來(lái)執(zhí)行刪除操作。刪除條件由類(lèi) DataAbilityPredicates 構(gòu)建,服務(wù)端在接收到該參數(shù)之后可以從中解析出要?jiǎng)h除的數(shù)據(jù),然后到數(shù)據(jù)庫(kù)中執(zhí)行。根據(jù)傳入的條件刪除用戶表數(shù)據(jù)的代碼示例如下:

     public int delete(Uri uri, DataAbilityPredicates predicates) {
         if (ormContext == null) {
             HiLog.error(this.getClass().getSimpleName(), "failed to delete, ormContext is null");
             return -1;
         }

      
         OrmPredicates ormPredicates = DataAbilityUtils.createOrmPredicates(predicates,User.class);
         int value = ormContext.delete(ormPredicates);
         DataAbilityHelper.creator(this, uri).notifyChange(uri);
         return value;
     }

  • update()

此方法用來(lái)執(zhí)行更新操作。用戶可以在 ValuesBucket 參數(shù)中指定要更新的數(shù)據(jù),在 DataAbilityPredicates 中構(gòu)建更新的條件等。更新用戶表的數(shù)據(jù)的代碼示例如下:

     public int update(Uri uri, ValuesBucket value, DataAbilityPredicates predicates) {
         if (ormContext == null) {
            HiLog.error(this.getClass().getSimpleName(), "failed to update, ormContext is null");
            return -1;
        }

      
        OrmPredicates ormPredicates = DataAbilityUtils.createOrmPredicates(predicates,User.class);
        int index = ormContext.update(ormPredicates, value);
        HiLog.info(this.getClass(), "UserDataAbility update value:" + index);
        DataAbilityHelper.creator(this, uri).notifyChange(uri);
        return index;
     }

  • executeBatch()

此方法用來(lái)批量執(zhí)行操作。DataAbilityOperation 中提供了設(shè)置操作類(lèi)型、數(shù)據(jù)和操作條件的方法,用戶可自行設(shè)置自己要執(zhí)行的數(shù)據(jù)庫(kù)操作。該方法系統(tǒng)已實(shí)現(xiàn),開(kāi)發(fā)者可以直接調(diào)用。

注冊(cè)UserDataAbility

和 Service 類(lèi)似,開(kāi)發(fā)者必須在配置配置文件中注冊(cè) Data。并且配置以下屬性:

  • type: 類(lèi)型設(shè)置為 data
  • uri: 對(duì)外提供的訪問(wèn)路徑,全局唯一
  • permissions: 訪問(wèn)該 data ability 時(shí)需要申請(qǐng)的訪問(wèn)權(quán)限

{
    "name": ".UserDataAbility",
     "type": "data",
     "visible": true,
     "uri": "dataability://com.example.myapplication5.DataAbilityTest",
     "permissions": [
        "com.example.myapplication5.DataAbility.DATA"
     ]
}
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)