介紹
本篇Codelab基于用戶首選項,實現了備忘錄新增、更新、刪除以及查找等功能。效果如圖所示:
相關概念
- [用戶首選項]:提供Key-Value鍵值型的數據處理能力,應用持久化輕量級數據,并對其修改和查詢。
- [Navigator]:路由容器組件,支持路由跳轉以及子組件嵌入。
環境搭建
軟件要求
- [DevEco Studio]版本:DevEco Studio 3.1 Release。
- OpenHarmony SDK版本:API version 9。
硬件要求
- 開發板類型:[潤和RK3568開發板]。
- OpenHarmony系統:3.2 Release。
環境搭建
完成本篇Codelab我們首先要完成開發環境的搭建,本示例以RK3568開發板為例,參照以下步驟進行:
- [獲取OpenHarmony系統版本]:標準系統解決方案(二進制)。以3.2 Release版本為例:
- 搭建燒錄環境。
- 搭建開發環境。
- 開始前請參考[工具準備],完成DevEco Studio的安裝和開發環境配置。
- 開發環境配置完成后,請參考[使用工程向導]創建工程(模板選擇“Empty Ability”)。
- 工程創建完成后,選擇使用[真機進行調測]。
代碼結構解讀
本篇Codelab只對核心代碼進行講解,對于完整代碼,我們會在gitee中提供。
├──entry/src/main/ets // 代碼區
│ ├──common
│ │ ├──constants
│ │ │ ├──CommonConstants.ets // 常量類
│ │ │ └──StyleConstants.ets // 樣式常量類
│ │ └──utils
│ │ ├──Format.ets // 日期格式化函數
│ │ └──Logger.ets // 日志打印類
│ ├──entryability
│ │ └──EntryAbility.ts // 程序入口類
│ ├──model
│ │ └──NotesDataModel.ets // 備忘錄方法類
│ ├──pages
│ │ ├──NoteHomePage.ets // 備忘錄主頁面(列表頁)
│ │ └──NotesDetail.ets // 備忘錄詳情頁
│ ├──view
│ │ ├──BottomBar.ets // 備忘錄編輯頁底部欄
│ │ ├──ConfirmDialog.ets // 自定義彈窗
│ │ └──MemoItem.ets // 自定義備忘錄列表組件
│ └──viewmodel
│ └──NotesInfoViewModel.ets // 備忘錄默認數據實體
└──entry/src/main/resources // 資源文件目錄
備忘錄初始化
在這個章節中,需要實現備忘錄數據的初始化,并且通過List組件將其渲染出來。效果如圖所示:
在saveDefaultData方法中先通過getPreferences方法獲取preferences實例,然后調用has方法查找數據庫中是否存在“noteIdArr”這個key值,如果不存在調用實例的put方法將noteIdArr以及備忘錄數據寫入,最后通過flush方法進行數據持久化。
// NotesDataModel.ets
import dataStorage from '@ohos.data.preferences';
...
class NotesDataModel {
private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
/**
* 寫入備忘錄數據.
*/
async saveDefaultData() {
try {
let preferences = await dataStorage.getPreferences(this.context, CommonConstants.PREFERENCE_INSTANCE_NAME);
let isExist = await preferences.has(CommonConstants.PREFERENCE_NOTE_KEY);
if (!isExist) {
preferences.put(CommonConstants.PREFERENCE_NOTE_KEY, JSON.stringify(noteIdArray));
preferences.flush();
notesItemArr.forEach((item: NotesInfoBean) = > {
let notes: NotesInfoBean = item;
let res = preferences.put(item.noteId, JSON.stringify(notes));
preferences.flush();
res.then(() = > {
Logger.info('Put the value successfully.' + item.noteId);
}).catch((err: Error) = > {
Logger.error(`Put the value failed with err: ${err}`);
})
})
}
} catch (err) {
Logger.error(`Failed to get preferences. Error = ${err}`);
}
}
/**
* 基于筆記類型獲取對應備忘錄數據.
*
* @param flag the folder type.
* @param allNotes all of notes.
* @returns subNotes.
*/
getSelectNotes(flag: FolderType, allNotes: Array< NotesInfoBean >): Array< NotesInfoBean > {
return allNotes.filter((item: NotesInfoBean) = > item.folder === flag);
}
}
在NoteHomePage.ets文件中調用saveDefaultData函數先將本地數據寫入數據庫,再調用實例的get方法進行查詢操作。
// NoteHomePage.ets
import dataStorage from '@ohos.data.preferences';
...
@Entry
@Component
struct NoteHomePage {
@State folderType: Resource = $r('app.string.notes_all');
@State allNotes: Array< NotesInfoBean > = [];
@State selectNotes: Array< NotesInfoBean > = this.allNotes.sort();
private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
...
build() {
Column() {
...
List({ space: StyleConstants.MEMO_LIST_SPACE }) {
ForEach(this.selectNotes, (item: NotesInfoBean) = > {
ListItem() {
MemoItem({ noteItem: item })
}
}, (item: NotesInfoBean) = > JSON.stringify(item))
}
.margin({ top: $r('app.float.list_container_margin') })
.height(StyleConstants.NOTE_CONTENT_HEIGHT)
.width(StyleConstants.FULL_WIDTH)
}
.backgroundColor($r('app.color.page_background'))
.height(StyleConstants.FULL_HEIGHT)
}
onPageShow() {
this.getAllNotes();
}
async getAllNotes() {
await NotesDataModel.saveDefaultData();
try {
let preferences = await dataStorage.getPreferences(this.context, CommonConstants.PREFERENCE_INSTANCE_NAME);
let noteIds = await preferences.get(CommonConstants.PREFERENCE_NOTE_KEY, '');
while (this.allNotes.length >= 1) {
this.allNotes.pop();
}
JSON.parse(noteIds.toString()).forEach(async (item: NotesInfoBean) = > {
let note = await preferences.get(item.noteId, '');
this.allNotes.push(JSON.parse(note.toString()));
})
} catch (err) {
Logger.error('Get the value of noteIdArr failed with err:', err);
}
}
}
新增備忘錄
此章節介紹新增備忘錄功能,點擊列表頁右上角加號進入編輯頁,支持輸入標題、備忘錄內容以及添加圖片。效果如圖所示:
首先在列表頁NoteHomePage.ets中添加跳轉邏輯,設置路由參數params,其中operationType字段代表此次操作是新增還是修改。
// NoteHomePage.ets
Navigator({ target: 'pages/NotesDetail', type: NavigationType.Replace }) {
Row() {
Image($rawfile('ic_title_add.svg'))
...
}
.margin({ right: $r('app.float.note_add_margin') })
}
.params({
notesInfo: {
'noteId': new Date().getTime().toString(),
'title': '',
'folder': FolderType.Personal,
'content': '',
'imageArr': [],
'time': new Date().toTimeString().split(' ')[0],
'isFavorite': false
},
operationType: CommonConstants.ADD_NOTE
})
進入編輯頁NotesDetail.ets后可以輸入標題、內容以及選擇對應的筆記類型等,確認保存后備忘錄數據實時更新。
// NotesDetail.ets
build() {
...
TextInput({
text: this.notesInfo.title != '' ? this.notesInfo.title : '',
placeholder: this.notesInfo.title != '' ? '' : $r('app.string.note_title_placeholder')
})
...
.onChange((value: string) = > {
if (value !== this.notesInfo.title) {
this.notesInfo.title = value;
this.isDataChanged = true;
}
})
...
TextArea({
text: this.notesInfo.content !== '' ? this.notesInfo.content : '',
placeholder: this.notesInfo.content !== '' ? '' : $r('app.string.note_content_placeholder')
})
.onChange((value: string) = > {
if (value !== this.notesInfo.content) {
this.notesInfo.content = value;
this.isDataChanged = true;
}
})
...
}
onBackPress() {
if (this.isDataChanged || this.notesFolder !== this.notesInfo.folder || this.isCollectChange) {
this.saveDialogController.open();
} else {
router.replaceUrl({
url: 'pages/NoteHomePage'
});
}
return true;
}
// ConfirmDialog.ets
if (this.type === CommonConstants.SAVE_DIALOG) {
this.confirm = async () = > {
let preferences = await dataStorage.getPreferences(this.context, CommonConstants.PREFERENCE_INSTANCE_NAME);
// 保存備忘錄數據實時更新
if (this.operationType === CommonConstants.ADD_NOTE) {
this.noteIdArray.push(new NoteIdBean(this.notesInfo.noteId));
preferences.put(CommonConstants.PREFERENCE_NOTE_KEY, JSON.stringify(this.noteIdArray));
preferences.flush();
}
let newNotes = this.notesInfo;
await preferences.put(this.notesInfo.noteId, JSON.stringify(newNotes));
await preferences.flush();
router.replaceUrl({
url: 'pages/NoteHomePage'
});
}
}
更新備忘錄
此章節介紹更新數據庫操作,與新增備忘錄邏輯類似。效果如圖所示:
首先在NotesDetail.ets中設置isDataChange和isCollectChange屬性,來表示對應noteId的備忘錄數據是否已更改。如果isDataChange或者isCollectChange為true表示已更改,在返回列表頁時會拉起確認彈窗,確認保存后執行put方法去更改備忘錄數據。
// NotesDetail.ets
build() {
Column() {
...
Stack({ alignContent: Alignment.Bottom }) {
Scroll(this.scroller) {
Column() {
TextInput({
text: this.notesInfo.title != '' ? this.notesInfo.title : '',
placeholder: this.notesInfo.title != '' ? '' : $r('app.string.note_title_placeholder')
})
...
.onChange((value: string) = > {
if (value !== this.notesInfo.title) {
this.notesInfo.title = value;
this.isDataChanged = true;
}
})
...
TextArea({
text: this.notesInfo.content !== '' ? this.notesInfo.content : '',
placeholder: this.notesInfo.content !== '' ? '' : $r('app.string.note_content_placeholder')
})
.onChange((value: string) = > {
if (value !== this.notesInfo.content) {
this.notesInfo.content = value;
this.isDataChanged = true;
}
})
...
}
}
...
BottomBar({
imageArr: $imageArr,
notesInfo: $notesInfo,
operationType: $operationType,
noteIdArray: $noteIdArray,
isDataChanged: $isDataChanged
})
}
...
}
.height(StyleConstants.FULL_HEIGHT)
.backgroundColor($r('app.color.white_color'))
}
...
onBackPress() {
if (this.isDataChanged || this.notesFolder !== this.notesInfo.folder || this.isCollectChange) {
this.saveDialogController.open();
} else {
router.replaceUrl({
url: 'pages/NoteHomePage'
});
}
return true;
}
// BottomBar.ets
// 點擊收藏
this.clickCollect = () = > {
this.notesInfo.isFavorite = !this.notesInfo.isFavorite;
this.isFavorite = !this.isFavorite;
this.collectImgSrc = this.notesInfo.isFavorite ?
'ic_bottom_star_selected.svg' : 'ic_bottom_star_normal.svg';
}
...
// 點擊插入圖片
this.clickAddPicture = () = > {
this.imageSrc = this.chooseImage();
if (this.imageSrc === '') {
prompt.showToast({
message: 'Not anymore pictures'
});
} else {
this.imageArr = this.notesInfo.imageArr;
this.imageArr.push(this.imageSrc);
this.isDataChanged = true;
}
}
// ConfirmDialog.ets
if (this.type === CommonConstants.SAVE_DIALOG) {
this.confirm = async () = > {
let preferences = await dataStorage.getPreferences(this.context, CommonConstants.PREFERENCE_INSTANCE_NAME);
if (this.operationType === CommonConstants.ADD_NOTE) {
this.noteIdArray.push(new NoteIdBean(this.notesInfo.noteId));
preferences.put(CommonConstants.PREFERENCE_NOTE_KEY, JSON.stringify(this.noteIdArray));
preferences.flush();
}
// 保存備忘錄數據實時更新
let newNotes = this.notesInfo;
await preferences.put(this.notesInfo.noteId, JSON.stringify(newNotes));
await preferences.flush();
router.replaceUrl({
url: 'pages/NoteHomePage'
});
}
}
刪除備忘錄
上述章節介紹了數據庫的新增與更新,此章節來介紹刪除操作。效果如圖所示:
在BottomBar.ets中點擊刪除按鈕,彈出自定義彈窗選擇“是否刪除”。在ConfirmDialog.ets中添加刪除邏輯,刪除操作會調用preferences實例的delete方法,將對應noteId的備忘錄數據從數據庫中刪除,最后執行實例的flush方法實現持久化。
// BottomBar.ets
export default struct BottomBar {
...
deleteDialogController: CustomDialogController = new CustomDialogController({
builder: ConfirmDialog({
notesInfo: $notesInfo,
operationType: $operationType,
noteIdArray: $noteIdArray,
type: CommonConstants.DELETE_DIALOG
}),
autoCancel: true,
alignment: DialogAlignment.Bottom,
offset: { dx: $r('app.float.dialog_offset_x'), dy: $r('app.float.dialog_margin_bottom') }
});
...
build() {
...
Column() {
Image($r('app.media.ic_bottom_delete'))
.width($r('app.float.ic_bottom_picture_size'))
.aspectRatio(1)
Text($r('app.string.delete_note'))
.fontSize($r('app.float.font_size_smallest'))
.margin({ top: $r('app.float.bottom_txt_margin') })
}
.onClick(() = > {
this.clickDelete = () = > {
if (this.operationType === CommonConstants.MODIFY_NOTE) {
this.deleteDialogController.open();
} else {
prompt.showToast({
message: 'The addition operation cannot be deleted'
});
}
}
this.clickDelete();
})
...
}
...
}
// ConfirmDialog.ets
if (this.type === CommonConstants.SAVE_DIALOG) {
...
} else {
// 刪除備忘錄數據
this.confirm = async () = > {
let preferences = await dataStorage.getPreferences(this.context, CommonConstants.PREFERENCE_INSTANCE_NAME);
await preferences.delete(this.notesInfo.noteId);
await preferences.flush();
router.replaceUrl({
url: 'pages/NoteHomePage'
});
}
}
this.confirm();
})
審核編輯 黃宇
-
鴻蒙
+關注
關注
57文章
2395瀏覽量
43091 -
HarmonyOS
+關注
關注
79文章
1983瀏覽量
30630 -
OpenHarmony
+關注
關注
25文章
3753瀏覽量
16661
發布評論請先 登錄
相關推薦
評論