|
|
|
@ -0,0 +1,548 @@
|
|
|
|
|
package net.micode.notes.data;
|
|
|
|
|
|
|
|
|
|
// 导入SearchManager类,用于管理搜索功能
|
|
|
|
|
import android.app.SearchManager;
|
|
|
|
|
|
|
|
|
|
// 导入ContentProvider类,用于实现数据的访问接口
|
|
|
|
|
import android.content.ContentProvider;
|
|
|
|
|
|
|
|
|
|
// 导入ContentUris类,提供了一些用于处理URI的方法
|
|
|
|
|
import android.content.ContentUris;
|
|
|
|
|
|
|
|
|
|
// 导入ContentValues类,用于存储键值对,通常用于插入或更新数据库记录
|
|
|
|
|
import android.content.ContentValues;
|
|
|
|
|
|
|
|
|
|
// 导入Intent类,用于启动Activity、Service或发送广播
|
|
|
|
|
import android.content.Intent;
|
|
|
|
|
|
|
|
|
|
// 导入UriMatcher类,用于匹配URI,以便根据不同的URI执行不同的操作
|
|
|
|
|
import android.content.UriMatcher;
|
|
|
|
|
|
|
|
|
|
// 导入Cursor类,用于从数据库查询结果集中获取数据
|
|
|
|
|
import android.database.Cursor;
|
|
|
|
|
|
|
|
|
|
// 导入SQLiteDatabase类,用于访问SQLite数据库
|
|
|
|
|
import android.database.sqlite.SQLiteDatabase;
|
|
|
|
|
|
|
|
|
|
// 导入Uri类,用于表示统一资源标识符
|
|
|
|
|
import android.net.Uri;
|
|
|
|
|
|
|
|
|
|
// 导入TextUtils类,提供了一些文本处理的工具方法
|
|
|
|
|
import android.text.TextUtils;
|
|
|
|
|
|
|
|
|
|
// 导入Log类,用于日志输出
|
|
|
|
|
import android.util.Log;
|
|
|
|
|
|
|
|
|
|
// 导入应用资源引用类
|
|
|
|
|
import net.micode.notes.R;
|
|
|
|
|
|
|
|
|
|
// 导入数据表的列名定义
|
|
|
|
|
import net.micode.notes.data.Notes.DataColumns;
|
|
|
|
|
|
|
|
|
|
// 导入笔记表的列名定义
|
|
|
|
|
import net.micode.notes.data.Notes.NoteColumns;
|
|
|
|
|
|
|
|
|
|
// 导入数据库表名的定义
|
|
|
|
|
import net.micode.notes.data.NotesDatabaseHelper.TABLE;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public class NotesProvider extends ContentProvider {
|
|
|
|
|
// 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; // 匹配单个笔记的URI
|
|
|
|
|
private static final int URI_NOTE_ITEM = 2; // 匹配单个笔记条目的URI
|
|
|
|
|
private static final int URI_DATA = 3; // 匹配数据的URI
|
|
|
|
|
private static final int URI_DATA_ITEM = 4; // 匹配单个数据条目的URI
|
|
|
|
|
private static final int URI_SEARCH = 5; // 匹配搜索URI
|
|
|
|
|
private static final int URI_SEARCH_SUGGEST = 6; // 匹配搜索建议的URI
|
|
|
|
|
|
|
|
|
|
// 进一步定义了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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* x'0A' 表示SQLite中的 '\n' 字符。对于搜索结果中的标题和内容,我们将修剪掉 '\n' 和空白字符,以显示更多信息。
|
|
|
|
|
*/
|
|
|
|
|
// 功能概述:
|
|
|
|
|
// 一个 SQL 查询的投影部分,用于定义查询返回的结果集中应该包含哪些列。
|
|
|
|
|
// 解读:
|
|
|
|
|
// 1. 返回笔记的 ID。
|
|
|
|
|
// 2. 笔记的 ID 也被重命名为 SUGGEST_COLUMN_INTENT_EXTRA_DATA,这通常用于 Android 的搜索建议中,作为传递给相关 Intent 的额外数据。
|
|
|
|
|
// 3. 对 SNIPPET 列的处理:首先使用 REPLACE 函数将 x'0A'(即换行符 \n)替换为空字符串,然后使用 TRIM 函数删除前后的空白字符,处理后的结果分别重命名为 SUGGEST_COLUMN_TEXT_1。
|
|
|
|
|
// 4. 对 SNIPPET 列的处理:首先使用 REPLACE 函数将 x'0A'(即换行符 \n)替换为空字符串,然后使用 TRIM 函数删除前后的空白字符,处理后的结果分别重命名为 SUGGEST_COLUMN_TEXT_2。
|
|
|
|
|
// 5. 返回一个用于搜索建议图标的资源 ID,并命名为 SUGGEST_COLUMN_ICON_1。
|
|
|
|
|
// 6. 返回一个固定的 Intent 动作 ACTION_VIEW,并命名为 SUGGEST_COLUMN_INTENT_ACTION。
|
|
|
|
|
// 7. 返回一个内容类型,并命名为 SUGGEST_COLUMN_INTENT_DATA。
|
|
|
|
|
|
|
|
|
|
// 搜索建议列的定义
|
|
|
|
|
private static final String[] SEARCH_SUGGEST_PROJECTION = {
|
|
|
|
|
// 笔记的 ID
|
|
|
|
|
NoteColumns._ID,
|
|
|
|
|
// 标题的内容处理,去掉换行符和空格
|
|
|
|
|
"REPLACE(TRIM(SNIPPET(" + NoteColumns.TITLE + ")), x'0A', '') AS " + SearchManager.SUGGEST_COLUMN_TEXT_1,
|
|
|
|
|
// 内容的内容处理,去掉换行符和空格
|
|
|
|
|
"REPLACE(TRIM(SNIPPET(" + NoteColumns.CONTENT + ")), x'0A', '') AS " + SearchManager.SUGGEST_COLUMN_TEXT_2,
|
|
|
|
|
// 图标资源 ID
|
|
|
|
|
String.valueOf(R.drawable.ic_suggest),
|
|
|
|
|
// 用于搜索结果的 intent 动作,通常是查看笔记
|
|
|
|
|
SearchManager.SUGGEST_COLUMN_INTENT_ACTION,
|
|
|
|
|
// 用于搜索结果的 intent 数据,通常是笔记的 URI
|
|
|
|
|
SearchManager.SUGGEST_COLUMN_INTENT_DATA
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 此方法会在查询时根据不同URI进行相应的操作,比如查询笔记、数据或执行搜索等。
|
|
|
|
|
@Override
|
|
|
|
|
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
|
|
|
|
// 处理不同URI的请求
|
|
|
|
|
switch (mMatcher.match(uri)) {
|
|
|
|
|
case URI_NOTE:
|
|
|
|
|
// 查询所有笔记数据
|
|
|
|
|
return mHelper.getReadableDatabase().query(TABLE.NOTES, projection, selection, selectionArgs, null, null, sortOrder);
|
|
|
|
|
case URI_NOTE_ITEM:
|
|
|
|
|
// 查询单个笔记数据
|
|
|
|
|
long noteId = ContentUris.parseId(uri);
|
|
|
|
|
return mHelper.getReadableDatabase().query(TABLE.NOTES, projection, NoteColumns._ID + " = ?", new String[]{String.valueOf(noteId)}, null, null, sortOrder);
|
|
|
|
|
case URI_SEARCH:
|
|
|
|
|
// 处理搜索请求
|
|
|
|
|
return searchNotes(selectionArgs);
|
|
|
|
|
case URI_SEARCH_SUGGEST:
|
|
|
|
|
// 处理搜索建议请求
|
|
|
|
|
return getSearchSuggestions(selectionArgs);
|
|
|
|
|
default:
|
|
|
|
|
throw new IllegalArgumentException("Unknown URI: " + uri);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 搜索笔记的具体实现
|
|
|
|
|
private Cursor searchNotes(String[] selectionArgs) {
|
|
|
|
|
SQLiteDatabase db = mHelper.getReadableDatabase();
|
|
|
|
|
return db.rawQuery("SELECT " + TextUtils.join(", ", SEARCH_SUGGEST_PROJECTION) + " FROM " + TABLE.NOTES + " WHERE " + NoteColumns.CONTENT + " MATCH ?", selectionArgs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取搜索建议
|
|
|
|
|
private Cursor getSearchSuggestions(String[] selectionArgs) {
|
|
|
|
|
SQLiteDatabase db = mHelper.getReadableDatabase();
|
|
|
|
|
return db.query(TABLE.NOTES, SEARCH_SUGGEST_PROJECTION, NoteColumns.TITLE + " LIKE ?", selectionArgs, null, null, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 插入数据
|
|
|
|
|
public Uri insert(Uri uri, ContentValues values) {
|
|
|
|
|
// 声明一个变量 rowId,用来存储插入操作返回的行 ID
|
|
|
|
|
long rowId;
|
|
|
|
|
|
|
|
|
|
// 使用 URI 匹配器 mMatcher 匹配传入的 URI,决定要插入到哪个表
|
|
|
|
|
switch (mMatcher.match(uri)) {
|
|
|
|
|
// 如果 URI 是 URI_NOTE,表示插入到 NOTE 表中
|
|
|
|
|
case URI_NOTE:
|
|
|
|
|
// 使用 mHelper 获取可写的 SQLite 数据库对象,然后执行插入操作
|
|
|
|
|
// insert 方法的参数分别是表名、空列名(为 null,表示所有列都可以插入),以及要插入的值(values)
|
|
|
|
|
rowId = mHelper.getWritableDatabase().insert(TABLE.NOTES, null, values);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// 如果 URI 是 URI_DATA,表示插入到 DATA 表中
|
|
|
|
|
case URI_DATA:
|
|
|
|
|
// 同样地,获取可写的数据库对象,执行插入操作
|
|
|
|
|
rowId = mHelper.getWritableDatabase().insert(TABLE.DATA, null, values);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// 如果 URI 既不是 URI_NOTE 也不是 URI_DATA,抛出异常,表示不支持的 URI 类型
|
|
|
|
|
default:
|
|
|
|
|
throw new IllegalArgumentException("Unknown URI: " + uri);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果插入操作成功,rowId 会大于 0,表示插入成功
|
|
|
|
|
if (rowId > 0) {
|
|
|
|
|
// 构建返回的 URI,ContentUris.withAppendedId 会将 rowId 附加到原始 URI 上
|
|
|
|
|
// resultUri 是插入操作后的 URI,它包含了新插入数据的 ID
|
|
|
|
|
Uri resultUri = ContentUris.withAppendedId(uri, rowId);
|
|
|
|
|
|
|
|
|
|
// 通知 ContentResolver,某个 URI 对应的数据已发生变化,通知所有注册了该 URI 的观察者
|
|
|
|
|
getContext().getContentResolver().notifyChange(resultUri, null);
|
|
|
|
|
|
|
|
|
|
// 返回新插入数据的 URI,允许调用者知道新插入数据的 ID
|
|
|
|
|
return resultUri;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果插入操作失败,rowId 会是 -1,这时抛出 SQLException 异常
|
|
|
|
|
throw new SQLException("Failed to insert row into " + uri);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新数据
|
|
|
|
|
@Override
|
|
|
|
|
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
|
|
|
|
switch (mMatcher.match(uri)) {
|
|
|
|
|
case URI_NOTE_ITEM:
|
|
|
|
|
long noteId = ContentUris.parseId(uri);
|
|
|
|
|
selection = NoteColumns._ID + " = ?";
|
|
|
|
|
selectionArgs = new String[]{String.valueOf(noteId)};
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
throw new IllegalArgumentException("Unknown URI: " + uri);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int count = mHelper.getWritableDatabase().update(TABLE.NOTES, values, selection, selectionArgs);
|
|
|
|
|
if (count > 0) {
|
|
|
|
|
getContext().getContentResolver().notifyChange(uri, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 删除数据
|
|
|
|
|
@Override
|
|
|
|
|
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
|
|
|
|
switch (mMatcher.match(uri)) {
|
|
|
|
|
case URI_NOTE_ITEM:
|
|
|
|
|
long noteId = ContentUris.parseId(uri);
|
|
|
|
|
selection = NoteColumns._ID + " = ?";
|
|
|
|
|
selectionArgs = new String[]{String.valueOf(noteId)};
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
throw new IllegalArgumentException("Unknown URI: " + uri);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int count = mHelper.getWritableDatabase().delete(TABLE.NOTES, selection, selectionArgs);
|
|
|
|
|
if (count > 0) {
|
|
|
|
|
getContext().getContentResolver().notifyChange(uri, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean onCreate() {
|
|
|
|
|
// 初始化数据库助手
|
|
|
|
|
mHelper = new NotesDatabaseHelper(getContext());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public String getType(Uri uri) {
|
|
|
|
|
switch (mMatcher.match(uri)) {
|
|
|
|
|
case URI_NOTE:
|
|
|
|
|
return "vnd.android.cursor.dir/vnd." + Notes.AUTHORITY + ".note";
|
|
|
|
|
case URI_NOTE_ITEM:
|
|
|
|
|
return "vnd.android.cursor.item/vnd." + Notes.AUTHORITY + ".note";
|
|
|
|
|
case URI_DATA:
|
|
|
|
|
return "vnd.android.cursor.dir/vnd." + Notes.AUTHORITY + ".data";
|
|
|
|
|
case URI_DATA_ITEM:
|
|
|
|
|
return "vnd.android.cursor.item/vnd." + Notes.AUTHORITY + ".data";
|
|
|
|
|
case URI_SEARCH:
|
|
|
|
|
return SearchManager.SUGGEST_MIME_TYPE;
|
|
|
|
|
case URI_SEARCH_SUGGEST:
|
|
|
|
|
return SearchManager.SUGGEST_MIME_TYPE;
|
|
|
|
|
default:
|
|
|
|
|
throw new IllegalArgumentException("Unknown URI: " + uri);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 定义了查询投影常量,用于搜索操作中返回所需的列信息。
|
|
|
|
|
// 该投影将用于从数据库中选择相关数据。
|
|
|
|
|
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 查询,用于搜索并检索符合条件的笔记。
|
|
|
|
|
// 该查询通过 SNIPPET 列中的内容来进行模糊搜索,并排除回收站中的笔记。
|
|
|
|
|
// 另外,还确保返回的是笔记类型的数据。
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
// onCreate 方法用于初始化 NotesProvider。
|
|
|
|
|
// 通过调用 NotesDatabaseHelper.getInstance 方法获取数据库实例并存储。
|
|
|
|
|
// mHelper 实例随后将用于数据库的操作,如查询、插入、更新等。
|
|
|
|
|
@Override
|
|
|
|
|
public boolean onCreate() {
|
|
|
|
|
mHelper = NotesDatabaseHelper.getInstance(getContext()); // 获取数据库助手实例
|
|
|
|
|
return true; // 返回 true,表示初始化成功
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// query 方法用于处理查询请求。
|
|
|
|
|
// 根据 URI 匹配不同的路径,执行相应的查询操作。
|
|
|
|
|
// 该方法会根据传入的 URI 和其他参数,决定查询哪个表,并返回相应的 Cursor。
|
|
|
|
|
@Override
|
|
|
|
|
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
|
|
|
|
|
String sortOrder) {
|
|
|
|
|
// 初始化变量:Cursor c 用于存储查询结果,db 为数据库的可读实例,id 用于存储从 URI 获取的 ID。
|
|
|
|
|
Cursor c = null;
|
|
|
|
|
SQLiteDatabase db = mHelper.getReadableDatabase(); // 获取数据库的可读实例
|
|
|
|
|
String id = null;
|
|
|
|
|
|
|
|
|
|
// 使用 UriMatcher 判断 URI 类型,并根据不同类型执行查询操作
|
|
|
|
|
switch (mMatcher.match(uri)) {
|
|
|
|
|
// URI_NOTE:查询整个 NOTE 表。
|
|
|
|
|
case URI_NOTE:
|
|
|
|
|
c = db.query(TABLE.NOTE, projection, selection, selectionArgs, null, null, sortOrder);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// URI_NOTE_ITEM:查询 NOTE 表中的特定项。ID 从 URI 的路径段中获取,并添加到查询条件中。
|
|
|
|
|
case URI_NOTE_ITEM:
|
|
|
|
|
id = uri.getPathSegments().get(1); // 获取 URI 中的 ID
|
|
|
|
|
c = db.query(TABLE.NOTE, projection, NoteColumns.ID + "=" + id
|
|
|
|
|
+ parseSelection(selection), selectionArgs, null, null, sortOrder);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// URI_DATA:查询整个 DATA 表。
|
|
|
|
|
case URI_DATA:
|
|
|
|
|
c = db.query(TABLE.DATA, projection, selection, selectionArgs, null, null, sortOrder);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// URI_DATA_ITEM:查询 DATA 表中的特定项。ID 的获取和处理方式与 URI_NOTE_ITEM 相同。
|
|
|
|
|
case URI_DATA_ITEM:
|
|
|
|
|
id = uri.getPathSegments().get(1); // 获取 URI 中的 ID
|
|
|
|
|
c = db.query(TABLE.DATA, projection, DataColumns.ID + "=" + id
|
|
|
|
|
+ parseSelection(selection), selectionArgs, null, null, sortOrder);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// URI_SEARCH 和 URI_SEARCH_SUGGEST:处理搜索相关的查询。
|
|
|
|
|
case URI_SEARCH:
|
|
|
|
|
case URI_SEARCH_SUGGEST:
|
|
|
|
|
// 确保在搜索查询中不包含不应使用的参数,如 sortOrder, selection, selectionArgs, 或 projection
|
|
|
|
|
if (sortOrder != null || selection != null || selectionArgs != null || projection != null) {
|
|
|
|
|
throw new IllegalArgumentException("Invalid arguments for search query");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取查询字符串,若为空则返回空结果
|
|
|
|
|
String searchString = uri.getQueryParameter(SearchManager.QUERY); // 从 URI 获取查询字符串
|
|
|
|
|
if (TextUtils.isEmpty(searchString)) {
|
|
|
|
|
return null; // 若查询字符串为空,返回 null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 对查询字符串进行搜索操作
|
|
|
|
|
c = db.rawQuery(NOTES_SNIPPET_SEARCH_QUERY, new String[] {"%" + searchString + "%"});
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
throw new IllegalArgumentException("Unknown URI: " + uri); // 如果 URI 不匹配任何规则,抛出异常
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return c; // 返回查询结果的 Cursor 对象
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 辅助方法:用于解析查询条件中的额外选择部分。该方法根据传入的 selection 参数返回合适的查询条件。
|
|
|
|
|
private String parseSelection(String selection) {
|
|
|
|
|
if (TextUtils.isEmpty(selection)) {
|
|
|
|
|
return ""; // 若 selection 为空,返回空字符串
|
|
|
|
|
}
|
|
|
|
|
return " AND (" + selection + ")"; // 否则返回查询条件
|
|
|
|
|
}
|
|
|
|
|
// 如果删除了数据,通知内容观察者
|
|
|
|
|
// 如果删除了 Note 数据表中的数据,通知该数据的 URI
|
|
|
|
|
if (count > 0 && deleteData) {
|
|
|
|
|
// 通知删除的 URI,使用 ContentUris.withAppendedId 方法将 ID 附加到基本 URI 末尾
|
|
|
|
|
getContext().getContentResolver().notifyChange(
|
|
|
|
|
ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, Long.parseLong(id)), null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果删除了 Note 数据表中的数据,通知相关 URI 更新
|
|
|
|
|
if (count > 0) {
|
|
|
|
|
getContext().getContentResolver().notifyChange(
|
|
|
|
|
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, Long.parseLong(id)), null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 返回被删除的行数
|
|
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 功能:更新数据
|
|
|
|
|
// 参数:uri 标识要更新的数据表,values 包含要更新的键值对,selection 是更新的 WHERE 子句,selectionArgs 是选择参数
|
|
|
|
|
@Override
|
|
|
|
|
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
|
|
|
|
// 初始化更新计数器
|
|
|
|
|
int count = 0;
|
|
|
|
|
SQLiteDatabase db = mHelper.getWritableDatabase(); // 获取可写数据库对象
|
|
|
|
|
|
|
|
|
|
// 根据 URI 匹配执行不同的更新操作
|
|
|
|
|
switch (mMatcher.match(uri)) {
|
|
|
|
|
// URI_NOTE: 更新整个 NOTE 表
|
|
|
|
|
case URI_NOTE:
|
|
|
|
|
count = db.update(TABLE.NOTE, values, selection, selectionArgs);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// URI_NOTE_ITEM: 更新指定的 NOTE 项。通过 URI 获取 ID 并更新该条目
|
|
|
|
|
case URI_NOTE_ITEM:
|
|
|
|
|
String id = uri.getPathSegments().get(1); // 获取 URI 中的 ID
|
|
|
|
|
count = db.update(TABLE.NOTE, values,
|
|
|
|
|
NoteColumns.ID + "=" + id + parseSelection(selection), selectionArgs);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// URI_DATA: 更新整个 DATA 表
|
|
|
|
|
case URI_DATA:
|
|
|
|
|
count = db.update(TABLE.DATA, values, selection, selectionArgs);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// URI_DATA_ITEM: 更新指定的 DATA 项
|
|
|
|
|
case URI_DATA_ITEM:
|
|
|
|
|
id = uri.getPathSegments().get(1); // 获取 URI 中的 ID
|
|
|
|
|
count = db.update(TABLE.DATA, values,
|
|
|
|
|
DataColumns.ID + "=" + id + parseSelection(selection), selectionArgs);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// 处理未知 URI 的情况,抛出异常
|
|
|
|
|
default:
|
|
|
|
|
throw new IllegalArgumentException("Unknown URI " + uri);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果更新成功,通知内容观察者数据已更改
|
|
|
|
|
if (count > 0) {
|
|
|
|
|
getContext().getContentResolver().notifyChange(uri, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 返回更新的行数
|
|
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 功能:获取 MIME 类型
|
|
|
|
|
// 参数:uri 用于确定请求的数据类型
|
|
|
|
|
@Override
|
|
|
|
|
public String getType(Uri uri) {
|
|
|
|
|
// 根据 URI 类型返回不同的 MIME 类型
|
|
|
|
|
switch (mMatcher.match(uri)) {
|
|
|
|
|
case URI_NOTE:
|
|
|
|
|
return Notes.CONTENT_NOTE_TYPE; // 返回笔记内容类型
|
|
|
|
|
case URI_NOTE_ITEM:
|
|
|
|
|
return Notes.CONTENT_NOTE_ITEM_TYPE; // 返回单个笔记内容类型
|
|
|
|
|
case URI_DATA:
|
|
|
|
|
return Notes.CONTENT_DATA_TYPE; // 返回数据内容类型
|
|
|
|
|
case URI_DATA_ITEM:
|
|
|
|
|
return Notes.CONTENT_DATA_ITEM_TYPE; // 返回单个数据内容类型
|
|
|
|
|
default:
|
|
|
|
|
throw new IllegalArgumentException("Unknown URI " + uri);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 功能:用于解析选择条件字符串
|
|
|
|
|
// 这个方法用于处理传递给查询、删除、更新等方法中的 selection 参数
|
|
|
|
|
private String parseSelection(String selection) {
|
|
|
|
|
// 如果 selection 字符串为空,直接返回空字符串
|
|
|
|
|
if (TextUtils.isEmpty(selection)) {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
// 否则将 selection 字符串包裹在括号内,确保逻辑正确
|
|
|
|
|
return " AND (" + selection + ")";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 获取 MIME 类型
|
|
|
|
|
@Override
|
|
|
|
|
public String getType(Uri uri) {
|
|
|
|
|
// 根据 URI 匹配返回不同的数据 MIME 类型
|
|
|
|
|
switch (mMatcher.match(uri)) {
|
|
|
|
|
case URI_NOTE:
|
|
|
|
|
// 返回笔记内容类型
|
|
|
|
|
return Notes.CONTENT_NOTE_TYPE;
|
|
|
|
|
case URI_NOTE_ITEM:
|
|
|
|
|
// 返回单个笔记内容类型
|
|
|
|
|
return Notes.CONTENT_NOTE_ITEM_TYPE;
|
|
|
|
|
case URI_DATA:
|
|
|
|
|
// 返回数据内容类型
|
|
|
|
|
return Notes.CONTENT_DATA_TYPE;
|
|
|
|
|
case URI_DATA_ITEM:
|
|
|
|
|
// 返回单个数据内容类型
|
|
|
|
|
return Notes.CONTENT_DATA_ITEM_TYPE;
|
|
|
|
|
default:
|
|
|
|
|
// 如果 URI 类型未知,抛出异常
|
|
|
|
|
throw new IllegalArgumentException("Unknown URI " + uri);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 功能:解析传入的条件语句(SQL WHERE 子句的一部分)
|
|
|
|
|
private String parseSelection(String selection) {
|
|
|
|
|
// 如果 selection 不为空,则返回一个加上括号的查询条件
|
|
|
|
|
return (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : "");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 功能:更新 NOTE 表中的 version 列,增加其版本号
|
|
|
|
|
// 参数:id - 要更新的便签的 ID;selection - 查询条件;selectionArgs - 查询条件的替换参数
|
|
|
|
|
private void increaseNoteVersion(long id, String selection, String[] selectionArgs) {
|
|
|
|
|
// 创建 SQL 更新语句
|
|
|
|
|
StringBuilder sql = new StringBuilder(120);
|
|
|
|
|
sql.append("UPDATE ");
|
|
|
|
|
sql.append(TABLE.NOTE); // 指定更新的表:NOTE
|
|
|
|
|
sql.append(" SET ");
|
|
|
|
|
sql.append(NoteColumns.VERSION); // 指定更新的字段:VERSION
|
|
|
|
|
sql.append("=" + NoteColumns.VERSION + "+1 "); // 版本号递增 1
|
|
|
|
|
|
|
|
|
|
// 如果 id 或 selection 不为空,则添加 WHERE 子句
|
|
|
|
|
if (id > 0 || !TextUtils.isEmpty(selection)) {
|
|
|
|
|
sql.append(" WHERE ");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果 id 大于 0,则按 ID 更新
|
|
|
|
|
if (id > 0) {
|
|
|
|
|
sql.append(NoteColumns.ID + "=" + String.valueOf(id));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果 selection 不为空,则添加额外的查询条件
|
|
|
|
|
if (!TextUtils.isEmpty(selection)) {
|
|
|
|
|
String selectString = id > 0 ? parseSelection(selection) : selection;
|
|
|
|
|
// 替换查询条件中的占位符(?)为实际参数
|
|
|
|
|
for (String args : selectionArgs) {
|
|
|
|
|
selectString = selectString.replaceFirst("\\?", args); // 替换占位符
|
|
|
|
|
}
|
|
|
|
|
sql.append(selectString); // 添加查询条件
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 执行 SQL 更新语句
|
|
|
|
|
mHelper.getWritableDatabase().execSQL(sql.toString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 功能:查询数据表的内容类型
|
|
|
|
|
@Override
|
|
|
|
|
public String getType(Uri uri) {
|
|
|
|
|
// 这个方法是 ContentProvider 的要求,用于返回数据的 MIME 类型
|
|
|
|
|
switch (mMatcher.match(uri)) {
|
|
|
|
|
case URI_NOTE:
|
|
|
|
|
return Notes.CONTENT_NOTE_TYPE; // 笔记内容类型
|
|
|
|
|
case URI_NOTE_ITEM:
|
|
|
|
|
return Notes.CONTENT_NOTE_ITEM_TYPE; // 单个笔记内容类型
|
|
|
|
|
case URI_DATA:
|
|
|
|
|
return Notes.CONTENT_DATA_TYPE; // 数据内容类型
|
|
|
|
|
case URI_DATA_ITEM:
|
|
|
|
|
return Notes.CONTENT_DATA_ITEM_TYPE; // 单个数据内容类型
|
|
|
|
|
default:
|
|
|
|
|
throw new IllegalArgumentException("Unknown URI " + uri); // 不认识的 URI 抛出异常
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|