diff --git a/Notesmaster/app/src/main/java/net/micode/notes/data/Contact.java b/Notesmaster/app/src/main/java/net/micode/notes/data/Contact.java index d97ac5d..9cf5aae 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/data/Contact.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/data/Contact.java @@ -1,19 +1,3 @@ -/* - * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package net.micode.notes.data; import android.content.Context; @@ -26,17 +10,26 @@ import android.util.Log; import java.util.HashMap; public class Contact { +// 用于处理联系人信息 +// 实现了从联系人数据库中获取指定电话号码对应的联系人姓名的功能 + + //sContactCache:用于缓存电话号码和对应的联系人姓名 + //TAG:用于日志输出的标识 private static HashMap sContactCache; private static final String TAG = "Contact"; + //SQL查询条件( WHERE 后面的语句),用于从联系人数据库中筛选出与给定电话号码匹配的联系人。 private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL(" + Phone.NUMBER - + ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'" - + " AND " + Data.RAW_CONTACT_ID + " IN " + + ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'" + + " AND " + Data.RAW_CONTACT_ID + " IN " + "(SELECT raw_contact_id " + " FROM phone_lookup" + " WHERE min_match = '+')"; + //功能简介:用于从Android设备的联系人数据库中获取与给定电话号码对应的联系人姓名。 + //参数:Context对象:用于访问系统服务和应用资源 phoneNumber:需要查询的联系人电话号码 public static String getContact(Context context, String phoneNumber) { + // 没映射表就建表,有就查缓存中有没有这个联系人 if(sContactCache == null) { sContactCache = new HashMap(); } @@ -45,6 +38,9 @@ public class Contact { return sContactCache.get(phoneNumber); } + //缓存没有,就查询数据库 + //构造一个SQL查询条件:CALLER_ID_SELECTION中的"+"被替换为电话号码的最小匹配值 + //然后执行查询语句 String selection = CALLER_ID_SELECTION.replace("+", PhoneNumberUtils.toCallerIDMinMatch(phoneNumber)); Cursor cursor = context.getContentResolver().query( @@ -54,6 +50,13 @@ public class Contact { new String[] { phoneNumber }, null); + //判断查询结果: + //查询结果不为空,且能够移动到第一条记录: + // 那么就尝试从Cursor中获取联系人姓名,并将其存入缓存sContactCache。然后返回联系人姓名。 + // 异常情况:如果在获取字符串时发生数组越界异常,则记录一个错误日志并返回null。 + // 最后都要确保关闭Cursor对象,以避免内存泄漏。 + //如果查询结果为空或者没有记录可以移动到(即没有找到匹配的联系人): + // 则记录一条调试日志并返回null if (cursor != null && cursor.moveToFirst()) { try { String name = cursor.getString(0); @@ -71,3 +74,4 @@ public class Contact { } } } + diff --git a/Notesmaster/app/src/main/java/net/micode/notes/data/Notes.java b/Notesmaster/app/src/main/java/net/micode/notes/data/Notes.java index f240604..f6c52d6 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/data/Notes.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/data/Notes.java @@ -17,13 +17,21 @@ package net.micode.notes.data; import android.net.Uri; + +import org.apache.http.client.fluent.Content; + +import java.net.URI; + +//Notes类是最底层的数据类,它定义了一堆常量,用来表示标签和文件的各种属性,以及Intent的额外数据(如布局、小组件ID)。 +// 它还通过接口以及其实现类定义了数据库表的列名(两个表:note表和data表)。 public class Notes { public static final String AUTHORITY = "micode_notes"; public static final String TAG = "Notes"; + //基本的信息,即认证信息和日志输出时的标志 public static final int TYPE_NOTE = 0; public static final int TYPE_FOLDER = 1; public static final int TYPE_SYSTEM = 2; - + //类型行的3种取值 /** * Following IDs are system folders' identifiers * {@link Notes#ID_ROOT_FOLDER } is default folder @@ -34,6 +42,12 @@ public class Notes { public static final int ID_TEMPARAY_FOLDER = -1; public static final int ID_CALL_RECORD_FOLDER = -2; public static final int ID_TRASH_FOLER = -3; + //这里定义了4种文件夹类型: + + //ID_ROOT_FOLDER:默认文件夹 + //ID_TEMPARAY_FOLDER:不属于文件夹的笔记 + //ID_CALL_RECORD_FOLDER:用于存储通话记录,以便返回 + //ID_TRASH_FOLER:垃圾回收站 public static final String INTENT_EXTRA_ALERT_DATE = "net.micode.notes.alert_date"; public static final String INTENT_EXTRA_BACKGROUND_ID = "net.micode.notes.background_color_id"; @@ -46,10 +60,13 @@ public class Notes { public static final int TYPE_WIDGET_2X = 0; public static final int TYPE_WIDGET_4X = 1; + //定义一些布局的ID,这部分就是用于设置UI界面的一些布局或小组件的id。 + public static class DataConstants { public static final String NOTE = TextNote.CONTENT_ITEM_TYPE; public static final String CALL_NOTE = CallNote.CONTENT_ITEM_TYPE; } + //这里定义了两种数据类型:文本便签和通话记录 /** * Uri to query all notes and folders @@ -61,6 +78,9 @@ public class Notes { */ public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data"); + //Android开发中常见的用于定义内容提供者( + //Content Provider)URI,内容提供者是一种Android组件,它允许应用程序共享和存储数据。这里定义了一个URI来查询数据 + public interface NoteColumns { /** * The unique ID for a row @@ -167,6 +187,11 @@ public class Notes { public static final String VERSION = "version"; } + //这个接口定义了一系列静态的、最终的字符串常量,这些常量代表数据库表中的列名。 + + //属性有:ID、父级ID、创建日期、修改日期、提醒日期、文件(标签)名(摘要?)、小部件ID、小部件类型、背景颜色ID、 + // 附件、文件中的标签数量、 文件(标签)类型、最后一个同步ID、本地修改标签、移动前的ID、谷歌任务ID、代码版本信息。 + public interface DataColumns { /** * The unique ID for a row @@ -179,101 +204,93 @@ public class Notes { *

Type: Text

*/ public static final String MIME_TYPE = "mime_type"; - + //MIME类型是一种标准,用于标识文档、文件或字节流的性质和格式。在数据库中,这个字段可以用来识别不同类型的数据,例如文本、图片、音频或视频等。 /** * The reference id to note that this data belongs to *

Type: INTEGER (long)

*/ public static final String NOTE_ID = "note_id"; - + //归属的Note的ID /** * Created data for note or folder *

Type: INTEGER (long)

*/ public static final String CREATED_DATE = "created_date"; - + //创建日期 /** * Latest modified date *

Type: INTEGER (long)

*/ public static final String MODIFIED_DATE = "modified_date"; - + //最近修改日期 /** * Data's content *

Type: TEXT

*/ public static final String CONTENT = "content"; - + //数据内容 /** - * Generic data column, the meaning is {@link #MIMETYPE} specific, used for + * Generic data column, the meaning is specific, used for * integer data type *

Type: INTEGER

*/ public static final String DATA1 = "data1"; /** - * Generic data column, the meaning is {@link #MIMETYPE} specific, used for + * Generic data column, the meaning is specific, used for * integer data type *

Type: INTEGER

*/ public static final String DATA2 = "data2"; /** - * Generic data column, the meaning is {@link #MIMETYPE} specific, used for + * Generic data column, the meaning is specific, used for * TEXT data type *

Type: TEXT

*/ public static final String DATA3 = "data3"; /** - * Generic data column, the meaning is {@link #MIMETYPE} specific, used for + * Generic data column, the meaning is specific, used for * TEXT data type *

Type: TEXT

*/ public static final String DATA4 = "data4"; /** - * Generic data column, the meaning is {@link #MIMETYPE} specific, used for + * Generic data column, the meaning is specific, used for * TEXT data type *

Type: TEXT

*/ public static final String DATA5 = "data5"; + // 以上5个是通用数据列,它们的具体意义取决于MIME类型(由MIME_TYPE字段指定)。 + // 不同的MIME类型可能需要存储不同类型的数据,这5个字段提供了灵活性,允许根据MIME类型来存储相应的数据。 } - + //以下这两个类是上述的DataColumns接口的实现类,分别是文本标签和通话记录实体。 + // 定义了实体之后,应用的其他部分或其他应用可以通过内容提供者访问和操作文本标签和通话记录 public static final class TextNote implements DataColumns { - /** - * Mode to indicate the text in check list mode or not - *

Type: Integer 1:check list mode 0: normal mode

- */ + //模式这个被存在DATA1列中 public static final String MODE = DATA1; - + //所处检查列表模式 public static final int MODE_CHECK_LIST = 1; - + // 定义了MIME类型,用于标识文本标签的目录 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/text_note"; - + // 定义了MIME类型,用于标识文本标签的单个项 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/text_note"; - - public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/text_note"); - } + //文本标签内容提供者(Content Provider)的URI,用于访问文本标签数据 + public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/text_note");} public static final class CallNote implements DataColumns { - /** - * Call date for this record - *

Type: INTEGER (long)

- */ + //一个字符串常量,表示通话记录的日期 public static final String CALL_DATE = DATA1; - - /** - * Phone number for this record - *

Type: TEXT

- */ + //意味着在数据库表中,这个电话号码信息将被存储在DATA3列中 public static final String PHONE_NUMBER = DATA3; - + // 同样定义了MIME类型,是用于标识通话记录的目录。 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/call_note"; - + // 同样定义了MIME类型,是用于标识通话记录的单个项。 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/call_note"; - + //定义了通话记录内容提供者的URI,用于访问通话记录数据。 public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/call_note"); } } diff --git a/Notesmaster/app/src/main/java/net/micode/notes/data/NotesProvider.java b/Notesmaster/app/src/main/java/net/micode/notes/data/NotesProvider.java index edb0a60..e688aa2 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/data/NotesProvider.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/data/NotesProvider.java @@ -1,19 +1,3 @@ -/* - * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package net.micode.notes.data; @@ -36,12 +20,24 @@ import net.micode.notes.data.NotesDatabaseHelper.TABLE; public class NotesProvider extends ContentProvider { +// Android 应用程序中的一部分:内容提供者(ContentProvider)。 +// 内容提供者是 Android 四大组件之一,它允许应用程序之间共享数据。 + + //概述: + //NotesProvider的主要功能是作为一个内容提供者,为其他应用程序或组件提供对“Notes”数据的访问。 + //它允许其他应用程序查询、插入、更新或删除标签数据。 + //通过URI匹配,NotesProvider能够区分对哪种数据类型的请求(例如,单独的标签、标签的数据、文件夹操作等),并执行相应的操作。 + + //用于匹配不同URI的UriMatcher对象,通常用于解析传入的URI,并确定应该执行哪种操作。 private static final UriMatcher mMatcher; + //NotesDatabaseHelper实类,用来操作SQLite数据库,负责创建、更新和查询数据库。 private NotesDatabaseHelper mHelper; + //标签,输出日志时用来表示是该类发出的消息 private static final String TAG = "NotesProvider"; + //6个URI的匹配码,用于区分不同的URI类型 private static final int URI_NOTE = 1; private static final int URI_NOTE_ITEM = 2; private static final int URI_DATA = 3; @@ -50,13 +46,23 @@ public class NotesProvider extends ContentProvider { private static final int URI_SEARCH = 5; private static final int URI_SEARCH_SUGGEST = 6; + //进一步定义了URI匹配规则和搜索查询的投影 + //功能概述: + //初始化了一个UriMatcher对象mMatcher,并添加了一系列的URI匹配规则。 + //解读: static { + //创建了一个UriMatcher实例,并设置默认匹配码为NO_MATCH,表示如果没有任何URI匹配,则返回这个码。 mMatcher = new UriMatcher(UriMatcher.NO_MATCH); + //添加规则,当URI的authority为Notes.AUTHORITY,路径为note时,返回匹配码URI_NOTE。 mMatcher.addURI(Notes.AUTHORITY, "note", URI_NOTE); + //添加规则,当URI的authority为Notes.AUTHORITY,路径为note/后跟一个数字(#代表数字)时,返回匹配码URI_NOTE_ITEM。 mMatcher.addURI(Notes.AUTHORITY, "note/#", URI_NOTE_ITEM); + //和上面两句同理,但用于匹配数据相关的URI mMatcher.addURI(Notes.AUTHORITY, "data", URI_DATA); mMatcher.addURI(Notes.AUTHORITY, "data/#", URI_DATA_ITEM); + //用于匹配搜索相关的URI mMatcher.addURI(Notes.AUTHORITY, "search", URI_SEARCH); + //这两行用于匹配搜索建议相关的URI mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, URI_SEARCH_SUGGEST); mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", URI_SEARCH_SUGGEST); } @@ -65,33 +71,66 @@ 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. */ - private static final String NOTES_SEARCH_PROJECTION = NoteColumns.ID + "," - + NoteColumns.ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA + "," - + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_1 + "," - + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_2 + "," - + R.drawable.search_result + " AS " + SearchManager.SUGGEST_COLUMN_ICON_1 + "," - + "'" + Intent.ACTION_VIEW + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_ACTION + "," - + "'" + Notes.TextNote.CONTENT_TYPE + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA; + //功能概述: + //一个 SQL 查询的投影部分,用于定义查询返回的结果集中应该包含哪些列。 + //解读:(每行对应) + //返回笔记的 ID。 + //笔记的 ID 也被重命名为 SUGGEST_COLUMN_INTENT_EXTRA_DATA,这通常用于 Android 的搜索建议中,作为传递给相关 Intent 的额外数据。 + //对 SNIPPET 列的处理:首先使用 REPLACE 函数将 x'0A'(即换行符 \n)替换为空字符串,然后使用 TRIM 函数删除前后的空白字符,处理后的结果分别重命名为 SUGGEST_COLUMN_TEXT_1 + //对 SNIPPET 列的处理:首先使用 REPLACE 函数将 x'0A'(即换行符 \n)替换为空字符串,然后使用 TRIM 函数删除前后的空白字符,处理后的结果分别重命名为 SUGGEST_COLUMN_TEXT_2 + //返回一个用于搜索建议图标的资源 ID,并命名为 SUGGEST_COLUMN_ICON_1。 + //返回一个固定的 Intent 动作 ACTION_VIEW,并命名为 SUGGEST_COLUMN_INTENT_ACTION。 + //返回一个内容类型,并命名为 SUGGEST_COLUMN_INTENT_DATA。 + private static final String NOTES_SEARCH_PROJECTION = NoteColumns.ID + "," //返回笔记的 ID + + NoteColumns.ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA + "," + + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_1 + "," + + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_2 + "," + + R.drawable.search_result + " AS " + SearchManager.SUGGEST_COLUMN_ICON_1 + "," + + "'" + Intent.ACTION_VIEW + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_ACTION + "," + + "'" + Notes.TextNote.CONTENT_TYPE + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA; + //功能概述: + //完整的 SQL 查询语句,用于从 TABLE.NOTE 表中检索信息 + //解读: + // 使用上面定义的投影来选择数据。 + // 并指定从哪个表中选择数据。 + //WHERE子句包含三个条件: + // ①搜索 SNIPPET 列中包含特定模式的行(? 是一个占位符,实际查询时会用具体的值替换)。 + // ②父ID不为回收站的ID:排除那些父 ID 为回收站的行。 + // ③只选择类型为note(标签)的行。 private static String NOTES_SNIPPET_SEARCH_QUERY = "SELECT " + NOTES_SEARCH_PROJECTION - + " FROM " + TABLE.NOTE - + " WHERE " + NoteColumns.SNIPPET + " LIKE ?" - + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER - + " AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE; + + " FROM " + TABLE.NOTE + + " WHERE " + NoteColumns.SNIPPET + " LIKE ?" + + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + + " AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE; + //重写onCreate方法: + //getContext() 方法被调用以获取当前组件的上下文(Context),以便 NotesDatabaseHelper 能够访问应用程序的资源和其他功能 + //mHelper用于存储从 NotesDatabaseHelper.getInstance 方法返回的实例。这样,该实例就可以在整个组件的其他方法中被访问和使用。 @Override public boolean onCreate() { mHelper = NotesDatabaseHelper.getInstance(getContext()); return true; } + //功能:查询数据 @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { + String sortOrder) { + //初始化变量: + //Cursor对象 c,用来存储查询结果 + //使用 NotesDatabaseHelper 的实例 mHelper来获取一个可读的数据库实例 + //定义一个字符串id,用来存储从URI中解析出的ID Cursor c = null; SQLiteDatabase db = mHelper.getReadableDatabase(); String id = null; + + //根据匹配不同的URI来进行不同的查询 switch (mMatcher.match(uri)) { + // URI_NOTE:查询整个 NOTE 表。 + // URI_NOTE_ITEM:查询 NOTE 表中的特定项。ID 从 URI 的路径段中获取,并添加到查询条件中。 + // URI_DATA:查询整个 DATA 表。 + // URI_DATA_ITEM:查询 DATA 表中的特定项。ID 的获取和处理方式与 URI_NOTE_ITEM 相同。 case URI_NOTE: c = db.query(TABLE.NOTE, projection, selection, selectionArgs, null, null, sortOrder); @@ -110,6 +149,12 @@ public class NotesProvider extends ContentProvider { c = db.query(TABLE.DATA, projection, DataColumns.ID + "=" + id + parseSelection(selection), selectionArgs, null, null, sortOrder); break; + + //URI_SEARCH 和 URI_SEARCH_SUGGEST:处理搜索查询。 + // 代码首先检查是否提供了不应与搜索查询一起使用的参数(如 sortOrder, selection, selectionArgs, 或 projection)。 + // 如果提供了这些参数,则抛出一个 IllegalArgumentException。 + // 根据 URI 类型,从 URI 的路径段或查询参数中获取搜索字符串 searchString。 + // 如果 searchString 为空或无效,则返回 null,表示没有搜索结果。 case URI_SEARCH: case URI_SEARCH_SUGGEST: if (sortOrder != null || projection != null) { @@ -130,6 +175,8 @@ public class NotesProvider extends ContentProvider { return null; } + //字符串格式化:格式化后的字符串就会是 "%s%",即包含s是任何文本 + //然后执行原始SQL查询 try { searchString = String.format("%%%s%%", searchString); c = db.rawQuery(NOTES_SNIPPET_SEARCH_QUERY, @@ -138,19 +185,31 @@ public class NotesProvider extends ContentProvider { Log.e(TAG, "got exception: " + ex.toString()); } break; + + //未知URI处理: default: throw new IllegalArgumentException("Unknown URI " + uri); } + //如果查询结果不为空(即 Cursor 对象 c 不是 null),则为其设置一个通知 URI。 + //这意味着当与这个 URI 关联的数据发生变化时,任何注册了监听这个 URI 的 ContentObserver 都会被通知。 if (c != null) { c.setNotificationUri(getContext().getContentResolver(), uri); } return c; } + //功能:插入数据 + //参数:Uri 用来标识要插入数据的表,ContentValues对象包含要插入的键值对 @Override public Uri insert(Uri uri, ContentValues values) { + //获取数据库 + //三个长整型变量,分别用来存储数据项ID、便签ID 和插入行的ID SQLiteDatabase db = mHelper.getWritableDatabase(); long dataId = 0, noteId = 0, insertedId = 0; + + //对于 URI_NOTE,将values插入到 TABLE.NOTE 表中,并返回插入行的 ID。 + //对于 URI_DATA,首先检查values是否包含 DataColumns.NOTE_ID,如果包含,则获取其值。如果不包含,记录一条日志信息。然后,将 values 插入到 TABLE.DATA 表中,并返回插入行的 ID。 + //如果 uri 不是已知的 URI 类型,则抛出一个 IllegalArgumentException。 switch (mMatcher.match(uri)) { case URI_NOTE: insertedId = noteId = db.insert(TABLE.NOTE, null, values); @@ -166,6 +225,10 @@ public class NotesProvider extends ContentProvider { default: throw new IllegalArgumentException("Unknown URI " + uri); } + + //功能:通知变化 + //如果noteId 或 dataId 大于 0(即成功插入了数据),则使用 ContentResolver 的 notifyChange 方法通知监听这些 URI 的观察者,告知数据已经改变。 + //ContentUris.withAppendedId 方法用于在基本 URI 后面追加一个 ID,形成完整的 URI。 // Notify the note uri if (noteId > 0) { getContext().getContentResolver().notifyChange( @@ -178,16 +241,28 @@ public class NotesProvider extends ContentProvider { ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), null); } + //返回包含新插入数据项ID 的 Uri。允许调用者知道新插入的数据项的位置 return ContentUris.withAppendedId(uri, insertedId); } + //功能:删除数据项 + //参数:uri:标识要删除数据的表或数据项。 selection:一个可选的 WHERE 子句,用于指定删除条件。 selectionArgs:一个可选的字符串数组,用于替换 selection 中的占位符 @Override public int delete(Uri uri, String selection, String[] selectionArgs) { + //count:记录被删除的行数。 + //id:用于存储从 URI 中解析出的数据项 ID。 + //db:可写的数据库对象,用于执行删除操作。 + //deleteData:一个布尔值,用于标记是否删除了 DATA 表中的数据。 int count = 0; String id = null; SQLiteDatabase db = mHelper.getWritableDatabase(); boolean deleteData = false; + switch (mMatcher.match(uri)) { + //URI_NOTE: 修改 selection 语句:确保只删除 ID 大于 0 的笔记。然后执行删除操作并返回被删除的行数。 + //URI_NOTE_ITEM: 从 URI 中解析出 ID。检查 ID 是否小于等于 0,如果是,则不执行删除操作;否则执行删除操作并返回被删除的行数 + //URI_DATA: 执行删除操作并返回被删除的行数。设置 deleteData 为 true,表示删除了 DATA 表中的数据。 + //URI_DATA_ITEM: 先从 URI 中解析出 ID,然后执行删除操作并返回被删除的行数,并设置 deleteData 为 true,表示删除了 DATA 表中的数据。 case URI_NOTE: selection = "(" + selection + ") AND " + NoteColumns.ID + ">0 "; count = db.delete(TABLE.NOTE, selection, selectionArgs); @@ -218,22 +293,39 @@ public class NotesProvider extends ContentProvider { default: throw new IllegalArgumentException("Unknown URI " + uri); } + + //如果 count 大于 0,说明有数据被删除。 + //如果 deleteData 为 true,则通知监听 Notes.CONTENT_NOTE_URI 的观察者,数据已改变。 + //通知监听传入 uri 的观察者数据已改变。 if (count > 0) { if (deleteData) { getContext().getContentResolver().notifyChange(Notes.CONTENT_NOTE_URI, null); } getContext().getContentResolver().notifyChange(uri, null); } + return count; } + //功能:更新数据库的数据 + //参数:uri:标识要更新数据的表或数据项。 values:一个包含新值的键值对集合。 + // selection:一个可选的 WHERE 子句,用于指定更新条件。 selectionArgs:一个可选的字符串数组,用于替换 selection 中的占位符。 @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + //count:记录被更新的行数。 + //id:用于存储从 URI 中解析出的数据项 ID。 + //db:可写的 SQLite 数据库对象,用于执行更新操作。 + //updateData:用于标记是否更新了 data 表中的数据。 int count = 0; String id = null; SQLiteDatabase db = mHelper.getWritableDatabase(); boolean updateData = false; + switch (mMatcher.match(uri)) { + //URI_NOTE:调用 increaseNoteVersion 方法(用于增加便签版本),然后在note表执行更新操作并返回被更新的行数。 + //URI_NOTE_ITEM:从 URI 中解析出 ID,并调用 increaseNoteVersion 方法,传入解析出的 ID,最后在note表执行更新操作并返回被更新的行数。 + //URI_DATA:在data表执行更新操作并返回被更新的行数。设置 updateData 为 true,表示更新了 DATA 表中的数据。 + //URI_DATA_ITEM:从 URI 中解析出 ID。执行更新操作并返回被更新的行数。置 updateData 为 true,表示更新了 DATA 表中的数据。 case URI_NOTE: increaseNoteVersion(-1, selection, selectionArgs); count = db.update(TABLE.NOTE, values, selection, selectionArgs); @@ -258,6 +350,9 @@ public class NotesProvider extends ContentProvider { throw new IllegalArgumentException("Unknown URI " + uri); } + //如果 count 大于 0,说明有数据被更新。 + //如果 updateData 为 true,则通知监听 Notes.CONTENT_NOTE_URI 的观察者数据已改变。 + //通知监听传入 uri 的观察者数据已改变。 if (count > 0) { if (updateData) { getContext().getContentResolver().notifyChange(Notes.CONTENT_NOTE_URI, null); @@ -267,10 +362,12 @@ public class NotesProvider extends ContentProvider { return count; } + //解析传入的条件语句:一个 SQL WHERE 子句的一部分 private String parseSelection(String selection) { return (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""); } + //更新note表的version列,将其值增加 1。 private void increaseNoteVersion(long id, String selection, String[] selectionArgs) { StringBuilder sql = new StringBuilder(120); sql.append("UPDATE "); @@ -302,4 +399,4 @@ public class NotesProvider extends ContentProvider { return null; } -} +} \ No newline at end of file