diff --git a/app/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java b/app/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java index 0f7b463..79f4ff4 100644 --- a/app/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java +++ b/app/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java @@ -218,6 +218,10 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { Log.d(TAG, "note table has been created"); } + /** + * 重新创建数据表的触发器 + * @param db + */ private void reCreateNoteTableTriggers(SQLiteDatabase db) { db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_update"); db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_update"); @@ -279,6 +283,10 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { Log.d(TAG, "data table has been created"); } + /** + * 重新创建笔记表的触发器 + * @param db + */ private void reCreateDataTableTriggers(SQLiteDatabase db) { db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_insert"); db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_update"); @@ -302,6 +310,12 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { createDataTable(db); } + /** + * 在数据库需要升级时被调用,根据不同的旧版本号执行相应的升级逻辑 + * @param db + * @param oldVersion + * @param newVersion + */ @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { boolean reCreateTriggers = false; @@ -335,6 +349,10 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { } } + /** + * 将数据库升级到版本 2 + * @param db + */ private void upgradeToV2(SQLiteDatabase db) { db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE); db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA); diff --git a/app/src/main/java/net/micode/notes/data/NotesProvider.java b/app/src/main/java/net/micode/notes/data/NotesProvider.java index edb0a60..7d66133 100644 --- a/app/src/main/java/net/micode/notes/data/NotesProvider.java +++ b/app/src/main/java/net/micode/notes/data/NotesProvider.java @@ -64,6 +64,8 @@ public class NotesProvider extends ContentProvider { /** * x'0A' represents the '\n' character in sqlite. For title and content in the search result, * we will trim '\n' and white space in order to show more information. + * NOTES_SEARCH_PROJECTION 是一个搜索结果的投影, + * 定义了搜索结果需要返回的列。其中包括笔记的ID、额外数据、文本1、文本2、图标和意图动作等。 */ private static final String NOTES_SEARCH_PROJECTION = NoteColumns.ID + "," + NoteColumns.ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA + "," @@ -73,6 +75,11 @@ public class NotesProvider extends ContentProvider { + "'" + Intent.ACTION_VIEW + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_ACTION + "," + "'" + Notes.TextNote.CONTENT_TYPE + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA; + /** + * NOTES_SNIPPET_SEARCH_QUERY 是一个搜索查询语句, + * 通过执行该查询语句可以获取匹配搜索关键字的笔记列表。 + * 查询条件包括笔记的片段内容、不是垃圾箱中的笔记以及类型为笔记的笔记。 + */ private static String NOTES_SNIPPET_SEARCH_QUERY = "SELECT " + NOTES_SEARCH_PROJECTION + " FROM " + TABLE.NOTE + " WHERE " + NoteColumns.SNIPPET + " LIKE ?" @@ -92,6 +99,14 @@ public class NotesProvider extends ContentProvider { SQLiteDatabase db = mHelper.getReadableDatabase(); String id = null; switch (mMatcher.match(uri)) { + //如果是 URI_NOTE,查询所有的笔记记录,并根据传入的投影、筛选条件和排序规则进行查询。 + //如果是 URI_NOTE_ITEM,根据传入的笔记ID查询对应的笔记记录。 + //如果是 URI_DATA,查询所有的数据记录,并根据传入的投影、筛选条件和排序规则进行查询。 + //如果是 URI_DATA_ITEM,根据传入的数据ID查询对应的数据记录。 + //如果是 URI_SEARCH 或 URI_SEARCH_SUGGEST,执行搜索操作,根据传入的搜索关键字查询匹配的笔记列表。 + // 如果是 URI_SEARCH_SUGGEST,可以从 Uri 中获取搜索关键字; + // 否则,从查询参数中获取搜索关键字。如果搜索关键字为空,返回空的游标对象; + // 否则,执行搜索查询语句 NOTES_SNIPPET_SEARCH_QUERY 并将搜索关键字作为查询参数。 case URI_NOTE: c = db.query(TABLE.NOTE, projection, selection, selectionArgs, null, null, sortOrder); @@ -147,6 +162,16 @@ public class NotesProvider extends ContentProvider { return c; } + /** + * 如果是 URI_NOTE,将数据插入到笔记表,并返回插入记录的ID。 + * 如果是 URI_DATA,判断是否包含笔记ID,如果包含则获取该笔记ID,否则输出错误日志。然后将数据插入到数据表,并返回插入记录的ID。 + * 如果是其他类型的 Uri,抛出异常并提示未知的 Uri。 + * 接着,如果成功插入数据,通过 ContentResolver.notifyChange() 方法通知对应的笔记和数据的 URI 发生了变化,以便更新界面。 + * 最后,将插入记录的ID追加到传入的 Uri 后面,并返回。 + * @param uri + * @param values + * @return + */ @Override public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase db = mHelper.getWritableDatabase(); @@ -181,6 +206,18 @@ public class NotesProvider extends ContentProvider { return ContentUris.withAppendedId(uri, insertedId); } + /** + * 如果是 URI_NOTE,根据传入的筛选条件和参数删除符合条件的笔记记录,并返回受影响的行数。 + * 如果是 URI_NOTE_ITEM,从 Uri 中获取笔记的ID,然后根据该ID和传入的筛选条件和参数删除对应的笔记记录,并返回受影响的行数。 + * 如果是 URI_DATA,根据传入的筛选条件和参数删除符合条件的数据记录,并返回受影响的行数。删除数据时同时删除关联的笔记记录。 + * 如果是 URI_DATA_ITEM,从 Uri 中获取数据的ID,然后根据该ID和传入的筛选条件和参数删除对应的数据记录,并返回受影响的行数。删除数据时同时删除关联的笔记记录。 + * 接着,如果成功删除记录,通过 ContentResolver.notifyChange() 方法通知对应的笔记和数据的 URI 发生了变化,以便更新界面。 + * 最后,返回受影响的行数。 + * @param uri + * @param selection + * @param selectionArgs + * @return + */ @Override public int delete(Uri uri, String selection, String[] selectionArgs) { int count = 0; @@ -227,6 +264,19 @@ public class NotesProvider extends ContentProvider { return count; } + /** + *如果是 URI_NOTE,根据传入的筛选条件和参数更新符合条件的笔记记录,并返回受影响的行数。在更新之前,调用 increaseNoteVersion() 方法更新笔记的版本号。 + * 如果是 URI_NOTE_ITEM,从 Uri 中获取笔记的ID,然后根据该ID和传入的筛选条件和参数更新对应的笔记记录,并返回受影响的行数。在更新之前,调用 increaseNoteVersion() 方法更新笔记的版本号。 + * 如果是 URI_DATA,根据传入的筛选条件和参数更新符合条件的数据记录,并返回受影响的行数。 + * 如果是 URI_DATA_ITEM,从 Uri 中获取数据的ID,然后根据该ID和传入的筛选条件和参数更新对应的数据记录,并返回受影响的行数。 + * 接着,如果成功更新记录,通过 ContentResolver.notifyChange() 方法通知对应的笔记和数据的 URI 发生了变化,以便更新界面。 + * 最后,返回受影响的行数。 + * @param uri + * @param values + * @param selection + * @param selectionArgs + * @return + */ @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int count = 0; @@ -267,10 +317,28 @@ public class NotesProvider extends ContentProvider { return count; } + /** + * 用于解析传入的筛选条件 selection, + * 并返回符合条件的 SQL 语句片段。如果 selection 不为空, + * 则在原有的筛选条件前加上 " AND ",拼接成最终的 SQL 语句。 + * @param selection + * @return + */ private String parseSelection(String selection) { return (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""); } + /** + * 用于增加笔记的版本号。它接收一个笔记的ID id、筛选条件 selection 和参数 selectionArgs。 + * 首先构建一个 StringBuilder 对象 sql,拼接更新语句的 SQL 字符串。 + * 然后根据传入的参数判断是否需要添加 WHERE 子句。 + * 如果 id 大于0或者 selection 不为空,则在 WHERE 前面添加空格和关键字。 + * 接着判断 id,如果大于0,则将 NoteColumns.ID 和 id 拼接到 SQL 语句中。 + * 最后,如果 selection 不为空,则将其解析为 SQL 语句片段,并替换其中的占位符 "?"。 + * @param id + * @param selection + * @param selectionArgs + */ private void increaseNoteVersion(long id, String selection, String[] selectionArgs) { StringBuilder sql = new StringBuilder(120); sql.append("UPDATE "); @@ -296,6 +364,13 @@ public class NotesProvider extends ContentProvider { mHelper.getWritableDatabase().execSQL(sql.toString()); } + /** + * getType() 方法是必须实现的抽象方法, + * 用于返回给定 Uri 的 MIME 类型。 + * 在这里,返回值为 null,表示没有指定 MIME 类型。 + * @param uri + * @return + */ @Override public String getType(Uri uri) { // TODO Auto-generated method stub diff --git a/app/src/main/java/net/micode/notes/gtask/data/MetaData.java b/app/src/main/java/net/micode/notes/gtask/data/MetaData.java index 3a2050b..0f77f5f 100644 --- a/app/src/main/java/net/micode/notes/gtask/data/MetaData.java +++ b/app/src/main/java/net/micode/notes/gtask/data/MetaData.java @@ -30,6 +30,12 @@ public class MetaData extends Task { private String mRelatedGid = null; + /** + * 设置元数据对象。它接收一个参数 gid,代表相关的任务ID,以及一个 JSONObject 类型的参数 metaInfo,代表元数据信息。 + * 方法会将 gid 添加到 metaInfo 中,并以字符串形式保存到元数据的笔记中。 + * @param gid + * @param metaInfo + */ public void setMeta(String gid, JSONObject metaInfo) { try { metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid); @@ -40,15 +46,29 @@ public class MetaData extends Task { setName(GTaskStringUtils.META_NOTE_NAME); } + /** + * 获取与元数据相关的任务ID + * @return + */ public String getRelatedGid() { return mRelatedGid; } + /** + * 判断元数据是否值得保存 + * @return + */ @Override public boolean isWorthSaving() { return getNotes() != null; } + /** + * 根据远程传入的 JSON 对象设置元数据的内容。 + * 首先调用父类的 setContentByRemoteJSON() 方法, + * 然后从元数据的笔记中解析出相关的任务ID。 + * @param js + */ @Override public void setContentByRemoteJSON(JSONObject js) { super.setContentByRemoteJSON(js); @@ -63,6 +83,11 @@ public class MetaData extends Task { } } + /** + * 此方法不应被调用。 + * 抛出一个 IllegalAccessError 异常,提示该方法不应该被调用。 + * @param js + */ @Override public void setContentByLocalJSON(JSONObject js) { // this function should not be called