From 2ed666e1cda44609a388dea9cc9ebf6a9e9c41a5 Mon Sep 17 00:00:00 2001 From: staz <3389605402@qq.com> Date: Sun, 15 Jun 2025 18:10:33 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/net/micode/notes/model/Note.java | 137 ++++++++--- .../net/micode/notes/model/WorkingNote.java | 225 ++++++++++++++---- 2 files changed, 286 insertions(+), 76 deletions(-) diff --git a/app/src/main/java/net/micode/notes/model/Note.java b/app/src/main/java/net/micode/notes/model/Note.java index 6706cf6..11dc88a 100644 --- a/app/src/main/java/net/micode/notes/model/Note.java +++ b/app/src/main/java/net/micode/notes/model/Note.java @@ -15,9 +15,9 @@ */ package net.micode.notes.model; + import android.content.ContentProviderOperation; import android.content.ContentProviderResult; -import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.OperationApplicationException; @@ -33,16 +33,23 @@ import net.micode.notes.data.Notes.TextNote; import java.util.ArrayList; - +/** + * 笔记数据模型类 + * 负责管理笔记的创建、更新和同步操作,封装与数据库交互的逻辑 + */ public class Note { - private ContentValues mNoteDiffValues; - private NoteData mNoteData; + private ContentValues mNoteDiffValues; // 笔记基本信息的变更值 + private NoteData mNoteData; // 笔记内容数据(文本/通话记录) private static final String TAG = "Note"; + /** - * Create a new note id for adding a new note to databases + * 创建新笔记ID并插入数据库 + * @param context 上下文 + * @param folderId 所属文件夹ID + * @return 新创建的笔记ID */ public static synchronized long getNewNoteId(Context context, long folderId) { - // Create a new note in the database + // 初始化笔记基本信息 ContentValues values = new ContentValues(); long createdTime = System.currentTimeMillis(); values.put(NoteColumns.CREATED_DATE, createdTime); @@ -50,8 +57,11 @@ public class Note { values.put(NoteColumns.TYPE, Notes.TYPE_NOTE); values.put(NoteColumns.LOCAL_MODIFIED, 1); values.put(NoteColumns.PARENT_ID, folderId); + + // 插入数据库获取URI Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values); + // 从URI中解析笔记ID long noteId = 0; try { noteId = Long.valueOf(uri.getPathSegments().get(1)); @@ -70,36 +80,73 @@ public class Note { mNoteData = new NoteData(); } + /** + * 设置笔记基本信息变更值 + * @param key 字段名 + * @param value 字段值 + */ public void setNoteValue(String key, String value) { mNoteDiffValues.put(key, value); mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); } + /** + * 设置文本内容数据 + * @param key 字段名 + * @param value 字段值 + */ public void setTextData(String key, String value) { mNoteData.setTextData(key, value); } + /** + * 设置文本内容数据ID + * @param id 数据ID + */ public void setTextDataId(long id) { mNoteData.setTextDataId(id); } + /** + * 获取文本内容数据ID + * @return 数据ID + */ public long getTextDataId() { return mNoteData.mTextDataId; } + /** + * 设置通话记录数据ID + * @param id 数据ID + */ public void setCallDataId(long id) { mNoteData.setCallDataId(id); } + /** + * 设置通话记录数据 + * @param key 字段名 + * @param value 字段值 + */ public void setCallData(String key, String value) { mNoteData.setCallData(key, value); } + /** + * 判断笔记是否有本地修改 + * @return 有修改返回true,否则返回false + */ public boolean isLocalModified() { return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified(); } + /** + * 同步笔记到数据库 + * @param context 上下文 + * @param noteId 笔记ID + * @return 同步成功返回true,失败返回false + */ public boolean syncNote(Context context, long noteId) { if (noteId <= 0) { throw new IllegalArgumentException("Wrong note id:" + noteId); @@ -109,19 +156,15 @@ public class Note { return true; } - /** - * In theory, once data changed, the note should be updated on {@link NoteColumns#LOCAL_MODIFIED} and - * {@link NoteColumns#MODIFIED_DATE}. For data safety, though update note fails, we also update the - * note data info - */ + // 更新笔记基本信息(即使失败也继续处理内容数据) if (context.getContentResolver().update( ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null, null) == 0) { Log.e(TAG, "Update note error, should not happen"); - // Do not return, fall through } mNoteDiffValues.clear(); + // 同步内容数据(文本/通话记录) if (mNoteData.isLocalModified() && (mNoteData.pushIntoContentResolver(context, noteId) == null)) { return false; @@ -130,15 +173,15 @@ public class Note { return true; } + /** + * 笔记内容数据内部类 + * 管理文本笔记和通话记录的具体内容数据 + */ private class NoteData { - private long mTextDataId; - - private ContentValues mTextDataValues; - - private long mCallDataId; - - private ContentValues mCallDataValues; - + private long mTextDataId; // 文本内容数据ID + private ContentValues mTextDataValues; // 文本内容变更值 + private long mCallDataId; // 通话记录数据ID + private ContentValues mCallDataValues; // 通话记录变更值 private static final String TAG = "NoteData"; public NoteData() { @@ -148,17 +191,29 @@ public class Note { mCallDataId = 0; } + /** + * 判断内容数据是否有本地修改 + * @return 有修改返回true,否则返回false + */ boolean isLocalModified() { return mTextDataValues.size() > 0 || mCallDataValues.size() > 0; } + /** + * 设置文本内容数据ID + * @param id 数据ID + */ void setTextDataId(long id) { - if(id <= 0) { + if (id <= 0) { throw new IllegalArgumentException("Text data id should larger than 0"); } mTextDataId = id; } + /** + * 设置通话记录数据ID + * @param id 数据ID + */ void setCallDataId(long id) { if (id <= 0) { throw new IllegalArgumentException("Call data id should larger than 0"); @@ -166,35 +221,49 @@ public class Note { mCallDataId = id; } + /** + * 设置通话记录数据变更值 + * @param key 字段名 + * @param value 字段值 + */ void setCallData(String key, String value) { mCallDataValues.put(key, value); mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); } + /** + * 设置文本内容数据变更值 + * @param key 字段名 + * @param value 字段值 + */ void setTextData(String key, String value) { mTextDataValues.put(key, value); mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); } + /** + * 将内容数据同步到数据库 + * @param context 上下文 + * @param noteId 笔记ID + * @return 同步成功返回笔记URI,失败返回null + */ Uri pushIntoContentResolver(Context context, long noteId) { - /** - * Check for safety - */ if (noteId <= 0) { throw new IllegalArgumentException("Wrong note id:" + noteId); } - ArrayList operationList = new ArrayList(); + ArrayList operationList = new ArrayList<>(); ContentProviderOperation.Builder builder = null; - if(mTextDataValues.size() > 0) { + // 处理文本内容数据 + if (mTextDataValues.size() > 0) { mTextDataValues.put(DataColumns.NOTE_ID, noteId); if (mTextDataId == 0) { + // 插入新文本数据 mTextDataValues.put(DataColumns.MIME_TYPE, TextNote.CONTENT_ITEM_TYPE); - Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, - mTextDataValues); + Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, mTextDataValues); try { setTextDataId(Long.valueOf(uri.getPathSegments().get(1))); } catch (NumberFormatException e) { @@ -203,6 +272,7 @@ public class Note { return null; } } else { + // 更新现有文本数据 builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId( Notes.CONTENT_DATA_URI, mTextDataId)); builder.withValues(mTextDataValues); @@ -211,12 +281,13 @@ public class Note { mTextDataValues.clear(); } - if(mCallDataValues.size() > 0) { + // 处理通话记录数据 + if (mCallDataValues.size() > 0) { mCallDataValues.put(DataColumns.NOTE_ID, noteId); if (mCallDataId == 0) { + // 插入新通话记录数据 mCallDataValues.put(DataColumns.MIME_TYPE, CallNote.CONTENT_ITEM_TYPE); - Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, - mCallDataValues); + Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, mCallDataValues); try { setCallDataId(Long.valueOf(uri.getPathSegments().get(1))); } catch (NumberFormatException e) { @@ -225,6 +296,7 @@ public class Note { return null; } } else { + // 更新现有通话记录数据 builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId( Notes.CONTENT_DATA_URI, mCallDataId)); builder.withValues(mCallDataValues); @@ -233,6 +305,7 @@ public class Note { mCallDataValues.clear(); } + // 批量执行数据库操作 if (operationList.size() > 0) { try { ContentProviderResult[] results = context.getContentResolver().applyBatch( @@ -250,4 +323,4 @@ public class Note { return null; } } -} +} \ No newline at end of file diff --git a/app/src/main/java/net/micode/notes/model/WorkingNote.java b/app/src/main/java/net/micode/notes/model/WorkingNote.java index 5f9734a..5bd85e4 100644 --- a/app/src/main/java/net/micode/notes/model/WorkingNote.java +++ b/app/src/main/java/net/micode/notes/model/WorkingNote.java @@ -15,40 +15,45 @@ import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.data.Notes.TextNote; import net.micode.notes.tool.ResourceParser.NoteBgResources; +/** + * 工作笔记模型类 + * 用于管理正在编辑的笔记,封装笔记的创建、加载、保存及各种属性设置功能 + */ public class WorkingNote { - // Note for the working note + // 笔记基础模型 private Note mNote; - // Note Id + // 笔记ID private long mNoteId; - // Note content + // 笔记内容 private String mContent; - // Note mode + // 笔记模式(普通/待办清单) private int mMode; - + // 提醒日期 private long mAlertDate; - + // 最后修改日期 private long mModifiedDate; - + // 背景色ID private int mBgColorId; - + // 小部件ID private int mWidgetId; - + // 小部件类型 private int mWidgetType; - + // 所属文件夹ID private long mFolderId; - + // 上下文 private Context mContext; - - private static final String TAG = "WorkingNote"; - + // 标记是否已删除 private boolean mIsDeleted; - + // 笔记设置变更监听器 private NoteSettingChangedListener mNoteSettingStatusListener; - - // 新增文件夹名称和父文件夹ID字段 + // 文件夹名称(新增字段) private String mFolderName; + // 父文件夹ID(新增字段) private long mParentFolderId; + private static final String TAG = "WorkingNote"; + + // 数据查询投影字段 public static final String[] DATA_PROJECTION = new String[] { DataColumns.ID, DataColumns.CONTENT, @@ -59,7 +64,7 @@ public class WorkingNote { DataColumns.DATA4, }; - // 更新查询投影,包含文件夹相关字段 + // 笔记查询投影字段(包含文件夹相关信息) public static final String[] NOTE_PROJECTION = new String[] { NoteColumns.PARENT_ID, NoteColumns.ALERTED_DATE, @@ -67,35 +72,31 @@ public class WorkingNote { NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE, NoteColumns.MODIFIED_DATE, - NoteColumns.FOLDER_NAME, - NoteColumns.PARENT_FOLDER_ID + NoteColumns.FOLDER_NAME, // 新增:文件夹名称 + NoteColumns.PARENT_FOLDER_ID // 新增:父文件夹ID }; + // 数据投影字段索引 private static final int DATA_ID_COLUMN = 0; - private static final int DATA_CONTENT_COLUMN = 1; - private static final int DATA_MIME_TYPE_COLUMN = 2; - private static final int DATA_MODE_COLUMN = 3; + // 笔记投影字段索引 private static final int NOTE_PARENT_ID_COLUMN = 0; - private static final int NOTE_ALERTED_DATE_COLUMN = 1; - private static final int NOTE_BG_COLOR_ID_COLUMN = 2; - private static final int NOTE_WIDGET_ID_COLUMN = 3; - private static final int NOTE_WIDGET_TYPE_COLUMN = 4; - private static final int NOTE_MODIFIED_DATE_COLUMN = 5; - - // 新增文件夹名称和父文件夹ID列索引 - private static final int NOTE_FOLDER_NAME_COLUMN = 6; - private static final int NOTE_PARENT_FOLDER_ID_COLUMN = 7; - - // New note construct + private static final int NOTE_FOLDER_NAME_COLUMN = 6; // 新增:文件夹名称索引 + private static final int NOTE_PARENT_FOLDER_ID_COLUMN = 7; // 新增:父文件夹ID索引 + + /** + * 创建新笔记的构造函数 + * @param context 上下文 + * @param folderId 所属文件夹ID + */ private WorkingNote(Context context, long folderId) { mContext = context; mAlertDate = 0; @@ -108,7 +109,12 @@ public class WorkingNote { mWidgetType = Notes.TYPE_WIDGET_INVALIDE; } - // Existing note construct + /** + * 加载现有笔记的构造函数 + * @param context 上下文 + * @param noteId 笔记ID + * @param folderId 所属文件夹ID + */ private WorkingNote(Context context, long noteId, long folderId) { mContext = context; mNoteId = noteId; @@ -118,6 +124,9 @@ public class WorkingNote { loadNote(); } + /** + * 加载笔记基本信息 + */ private void loadNote() { Cursor cursor = mContext.getContentResolver().query( ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mNoteId), NOTE_PROJECTION, null, @@ -131,7 +140,7 @@ public class WorkingNote { mWidgetType = cursor.getInt(NOTE_WIDGET_TYPE_COLUMN); mAlertDate = cursor.getLong(NOTE_ALERTED_DATE_COLUMN); mModifiedDate = cursor.getLong(NOTE_MODIFIED_DATE_COLUMN); - // 加载文件夹名称和父文件夹ID + // 加载文件夹相关信息(新增) mFolderName = cursor.getString(NOTE_FOLDER_NAME_COLUMN); mParentFolderId = cursor.getLong(NOTE_PARENT_FOLDER_ID_COLUMN); } @@ -143,6 +152,9 @@ public class WorkingNote { loadNoteData(); } + /** + * 加载笔记内容数据 + */ private void loadNoteData() { Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION, DataColumns.NOTE_ID + "=?", new String[] { @@ -171,6 +183,15 @@ public class WorkingNote { } } + /** + * 创建空笔记的静态方法 + * @param context 上下文 + * @param folderId 所属文件夹ID + * @param widgetId 小部件ID + * @param widgetType 小部件类型 + * @param defaultBgColorId 默认背景色ID + * @return 新创建的WorkingNote实例 + */ public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId, int widgetType, int defaultBgColorId) { WorkingNote note = new WorkingNote(context, folderId); @@ -180,10 +201,20 @@ public class WorkingNote { return note; } + /** + * 加载现有笔记的静态方法 + * @param context 上下文 + * @param id 笔记ID + * @return WorkingNote实例 + */ public static WorkingNote load(Context context, long id) { return new WorkingNote(context, id, 0); } + /** + * 保存笔记到数据库 + * @return 保存成功返回true,失败返回false + */ public synchronized boolean saveNote() { if (isWorthSaving()) { if (!existInDatabase()) { @@ -196,7 +227,7 @@ public class WorkingNote { mNote.syncNote(mContext, mNoteId); /** - * Update widget content if there exist any widget of this note + * 更新小部件内容(如果有相关小部件) */ if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID && mWidgetType != Notes.TYPE_WIDGET_INVALIDE @@ -209,10 +240,18 @@ public class WorkingNote { } } + /** + * 判断笔记是否已存在于数据库 + * @return 存在返回true,否则返回false + */ public boolean existInDatabase() { return mNoteId > 0; } + /** + * 判断笔记是否值得保存 + * @return 值得保存返回true,否则返回false + */ private boolean isWorthSaving() { if (mIsDeleted || (!existInDatabase() && TextUtils.isEmpty(mContent)) || (existInDatabase() && !mNote.isLocalModified())) { @@ -222,10 +261,19 @@ public class WorkingNote { } } + /** + * 设置笔记设置变更监听器 + * @param l 监听器实例 + */ public void setOnSettingStatusChangedListener(NoteSettingChangedListener l) { mNoteSettingStatusListener = l; } + /** + * 设置提醒日期 + * @param date 提醒日期 + * @param set 是否设置提醒 + */ public void setAlertDate(long date, boolean set) { if (date != mAlertDate) { mAlertDate = date; @@ -236,6 +284,10 @@ public class WorkingNote { } } + /** + * 标记笔记为已删除或取消删除 + * @param mark 是否标记为删除 + */ public void markDeleted(boolean mark) { mIsDeleted = mark; if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID @@ -244,6 +296,10 @@ public class WorkingNote { } } + /** + * 设置背景色 + * @param id 背景色ID + */ public void setBgColorId(int id) { if (id != mBgColorId) { mBgColorId = id; @@ -254,6 +310,10 @@ public class WorkingNote { } } + /** + * 设置待办清单模式 + * @param mode 模式(0:普通模式,1:待办清单模式) + */ public void setCheckListMode(int mode) { if (mMode != mode) { if (mNoteSettingStatusListener != null) { @@ -264,6 +324,10 @@ public class WorkingNote { } } + /** + * 设置小部件类型 + * @param type 小部件类型 + */ public void setWidgetType(int type) { if (type != mWidgetType) { mWidgetType = type; @@ -271,6 +335,10 @@ public class WorkingNote { } } + /** + * 设置小部件ID + * @param id 小部件ID + */ public void setWidgetId(int id) { if (id != mWidgetId) { mWidgetId = id; @@ -278,6 +346,10 @@ public class WorkingNote { } } + /** + * 设置笔记内容 + * @param text 笔记内容 + */ public void setWorkingText(String text) { if (!TextUtils.equals(mContent, text)) { mContent = text; @@ -285,89 +357,154 @@ public class WorkingNote { } } + /** + * 转换为通话记录笔记 + * @param phoneNumber 电话号码 + * @param callDate 通话日期 + */ public void convertToCallNote(String phoneNumber, long callDate) { mNote.setCallData(CallNote.CALL_DATE, String.valueOf(callDate)); mNote.setCallData(CallNote.PHONE_NUMBER, phoneNumber); mNote.setNoteValue(NoteColumns.PARENT_ID, String.valueOf(Notes.ID_CALL_RECORD_FOLDER)); } + /** + * 判断是否设置了提醒 + * @return 已设置提醒返回true,否则返回false + */ public boolean hasClockAlert() { return (mAlertDate > 0 ? true : false); } + /** + * 获取笔记内容 + * @return 笔记内容 + */ public String getContent() { return mContent; } + /** + * 获取提醒日期 + * @return 提醒日期 + */ public long getAlertDate() { return mAlertDate; } + /** + * 获取最后修改日期 + * @return 最后修改日期 + */ public long getModifiedDate() { return mModifiedDate; } + /** + * 获取背景色资源ID + * @return 背景色资源ID + */ public int getBgColorResId() { return NoteBgResources.getNoteBgResource(mBgColorId); } + /** + * 获取背景色ID + * @retur @return 背景色ID + */ public int getBgColorId() { return mBgColorId; } + /** + * 获取标题栏背景资源ID + * @return 标题栏背景资源ID + */ public int getTitleBgResId() { return NoteBgResources.getNoteTitleBgResource(mBgColorId); } + /** + * 获取待办清单模式 + * @return 模式(0:普通模式,1:待办清单模式) + */ public int getCheckListMode() { return mMode; } + /** + * 获取笔记ID + * @return 笔记ID + */ public long getNoteId() { return mNoteId; } + /** + * 获取所属文件夹ID + * @return 文件夹ID + */ public long getFolderId() { return mFolderId; } + /** + * 获取小部件ID + * @return 小部件ID + */ public int getWidgetId() { return mWidgetId; } + /** + * 获取小部件类型 + * @return 小部件类型 + */ public int getWidgetType() { return mWidgetType; } - // 新增获取文件夹名称和父文件夹ID的方法 + /** + * 获取文件夹名称(新增方法) + * @return 文件夹名称 + */ public String getFolderName() { return mFolderName; } + /** + * 获取父文件夹ID(新增方法) + * @return 父文件夹ID + */ public long getParentFolderId() { return mParentFolderId; } + /** + * 笔记设置变更监听器接口 + */ public interface NoteSettingChangedListener { /** - * Called when the background color of current note has just changed + * 背景色变更时回调 */ void onBackgroundColorChanged(); /** - * Called when user set clock + * 提醒设置变更时回调 + * @param date 提醒日期 + * @param set 是否已设置提醒 */ void onClockAlertChanged(long date, boolean set); /** - * Call when user create note from widget + * 小部件相关变更时回调 */ void onWidgetChanged(); /** - * Call when switch between check list mode and normal mode - * @param oldMode is previous mode before change - * @param newMode is new mode + * 待办清单模式变更时回调 + * @param oldMode 旧模式 + * @param newMode 新模式 */ void onCheckListModeChanged(int oldMode, int newMode); }