You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
git-xiaomibianqian/lhy/NotesProvider.java

306 lines
15 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* 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.app.SearchManager;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Intent;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.text.TextUtils;
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;// SearchManager 的作用是提供对系统搜索服务的访问
public class NotesProvider extends ContentProvider {//为存储和获取数据提供接口。可以在不同的应用程序之间共享数据
private static final UriMatcher mMatcher;//UriMatcher是Android提供的用来操作Uri的工具类
private NotesDatabaseHelper mHelper;//数据库辅助类的实例化
private static final String TAG = "NotesProvider";
private static final int URI_NOTE = 1;
private static final int URI_NOTE_ITEM = 2;
private static final int URI_DATA = 3;
private static final int URI_DATA_ITEM = 4;
private static final int URI_SEARCH = 5;
private static final int URI_SEARCH_SUGGEST = 6;
static {//初始化mMatcher UriMatcher类
mMatcher = new UriMatcher(UriMatcher.NO_MATCH);//创建UriMatcher时调用UriMatcher。UriMatcher.NO_MATCH表示不匹配任何路径
mMatcher.addURI(Notes.AUTHORITY, "note", URI_NOTE);
mMatcher.addURI(Notes.AUTHORITY, "note/#", URI_NOTE_ITEM);
mMatcher.addURI(Notes.AUTHORITY, "data", URI_DATA);
mMatcher.addURI(Notes.AUTHORITY, "data/#", URI_DATA_ITEM);
mMatcher.addURI(Notes.AUTHORITY, "search", URI_SEARCH);
mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, URI_SEARCH_SUGGEST);//SUGGEST_URI_PATH_QUERY 并不属于URI的一部分而应是用于指向此路径的常量。
mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", URI_SEARCH_SUGGEST);
}//注册完需要匹配的Uri后就可以使用sMatcher.match(uri)方法对输入的Uri进行匹配
/**
* 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 + ","//声明 NOTES_SEARCH_PROJECTION
+ NoteColumns.ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA + ","//设置表明额外数据、推荐显示的文本、图标、操作、数据
+ "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_1 + ","//TEXT_1是将该字段作为安卓搜索框中建议显示的文本。如果每个建议想显示两行数据还有SearchManager.SUGGEST_COLUMN_TEXT_2
+ "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;
private static String NOTES_SNIPPET_SEARCH_QUERY = "SELECT " + NOTES_SEARCH_PROJECTION//构造数据库查询语句用于通过notes的片段查询notes
+ " FROM " + TABLE.NOTE//在特定表中某一字段检索特定子串
+ " WHERE " + NoteColumns.SNIPPET + " LIKE ?"
+ " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER
+ " AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE;
@Override
public boolean onCreate() {//创建一个便签数据库助手helper
mHelper = NotesDatabaseHelper.getInstance(getContext());//对mHelper进行实例化
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,//在数据库中查询uri然后返回uri的位置
String sortOrder) {
Cursor c = null;
SQLiteDatabase db = mHelper.getReadableDatabase();
String id = null;
switch (mMatcher.match(uri)) {
case URI_NOTE:
c = db.query(TABLE.NOTE, projection, selection, selectionArgs, null, null,
sortOrder);
break;
case URI_NOTE_ITEM://查询便签条目
id = uri.getPathSegments().get(1);//获取uri中1号描述符
c = db.query(TABLE.NOTE, projection, NoteColumns.ID + "=" + id
+ parseSelection(selection), selectionArgs, null, null, sortOrder);
break;
case URI_DATA://根据日期进行查询
c = db.query(TABLE.DATA, projection, selection, selectionArgs, null, null,
sortOrder);
break;
case URI_DATA_ITEM://查询id对应的具体数据
id = uri.getPathSegments().get(1);
c = db.query(TABLE.DATA, projection, DataColumns.ID + "=" + id
+ parseSelection(selection), selectionArgs, null, null, sortOrder);
break;
case URI_SEARCH://匹配到搜索
case URI_SEARCH_SUGGEST:
if (sortOrder != null || projection != null) {
throw new IllegalArgumentException(
"do not specify sortOrder, selection, selectionArgs, or projection" + "with this query");//在查询时不能指定排序参数sortOrder、查询条件selection、占位符(selectionArgs)、要查询的表projection
}
String searchString = null;//搜索所得的内容
if (mMatcher.match(uri) == URI_SEARCH_SUGGEST) {
if (uri.getPathSegments().size() > 1) {
searchString = uri.getPathSegments().get(1);
}
} else {//利用URI的getQueryParameter方法可以获取字符串参数
searchString = uri.getQueryParameter("pattern");
}
if (TextUtils.isEmpty(searchString)) {//格式化搜索的字符串
return null;
}
try {//非法状态异常
searchString = String.format("%%%s%%", searchString);
c = db.rawQuery(NOTES_SNIPPET_SEARCH_QUERY,
new String[] { searchString });
} catch (IllegalStateException ex) {
Log.e(TAG, "got exception: " + ex.toString());
}
break;
default://如果以上多个case均不命中则抛出未知uri的异常
throw new IllegalArgumentException("Unknown URI " + uri);
}
if (c != null) {//若getContentResolver发生变化就接收通知
c.setNotificationUri(getContext().getContentResolver(), uri);
}
return c;
}
@Override
public Uri insert(Uri uri, ContentValues values) {//插入一个uriuri是一个用于标识某一互联网资源名称的字符串
SQLiteDatabase db = mHelper.getWritableDatabase();//获得可写的数据库
long dataId = 0, noteId = 0, insertedId = 0;
switch (mMatcher.match(uri)) {//数据库的插入,用来存放数据
case URI_NOTE:
insertedId = noteId = db.insert(TABLE.NOTE, null, values);
break;
case URI_DATA://如果是数据类型且其id能对应于某个便签id则插入
if (values.containsKey(DataColumns.NOTE_ID)) {
noteId = values.getAsLong(DataColumns.NOTE_ID);
} else {//错误的数据格式没有note的id
Log.d(TAG, "Wrong data format without note id:" + values.toString());
}
insertedId = dataId = db.insert(TABLE.DATA, null, values);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);//未知uri异常
}
// Notify the note uri
if (noteId > 0) {
getContext().getContentResolver().notifyChange(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null);//把noteId加到URI的尾部连接成新的URI
}
// Notify the data uri
if (dataId > 0) {//更新data
getContext().getContentResolver().notifyChange(
ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), null);//返回插入的uri的路径
}
return ContentUris.withAppendedId(uri, insertedId);//返回插入的uri的路径
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {//从数据库中删除uri
int count = 0;
String id = null;
SQLiteDatabase db = mHelper.getWritableDatabase();
boolean deleteData = false;
switch (mMatcher.match(uri)) {
case URI_NOTE://查找到不同类型的相应的uri后在数据库中删除
selection = "(" + selection + ") AND " + NoteColumns.ID + ">0 ";
count = db.delete(TABLE.NOTE, selection, selectionArgs);
break;
case URI_NOTE_ITEM://如果是便签条目获取对应id且对应id非系统文件夹则删除
id = uri.getPathSegments().get(1);
/**
* ID that smaller than 0 is system folder which is not allowed to
* trash
*/
long noteId = Long.valueOf(id);//.语句将string类型转换为long类型
if (noteId <= 0) {
break;
}
count = db.delete(TABLE.NOTE,
NoteColumns.ID + "=" + id + parseSelection(selection), selectionArgs);
break;
case URI_DATA:
count = db.delete(TABLE.DATA, selection, selectionArgs);//删除数据
deleteData = true;
break;
case URI_DATA_ITEM://删除uri标识的指定数据
id = uri.getPathSegments().get(1);
count = db.delete(TABLE.DATA,
DataColumns.ID + "=" + id + parseSelection(selection), selectionArgs);
deleteData = true;
break;
default://匹配失败,则报错
throw new IllegalArgumentException("Unknown URI " + uri);
}
if (count > 0) {//对上述的操作进行判断上述更改发生count>0
if (deleteData) {
getContext().getContentResolver().notifyChange(Notes.CONTENT_NOTE_URI, null);
}
getContext().getContentResolver().notifyChange(uri, null);//对所有修改进行通知
}
return count;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {//数据库更新uri
int count = 0;
String id = null;
SQLiteDatabase db = mHelper.getWritableDatabase();
boolean updateData = false;
switch (mMatcher.match(uri)) {
case URI_NOTE:
increaseNoteVersion(-1, selection, selectionArgs);//升级note版本
count = db.update(TABLE.NOTE, values, selection, selectionArgs);
break;
case URI_NOTE_ITEM:
id = uri.getPathSegments().get(1);
increaseNoteVersion(Long.valueOf(id), selection, selectionArgs);
count = db.update(TABLE.NOTE, values, NoteColumns.ID + "=" + id//对notes item uri进行更新
+ parseSelection(selection), selectionArgs);
break;
case URI_DATA://对多个数据进行修改
count = db.update(TABLE.DATA, values, selection, selectionArgs);
updateData = true;
break;
case URI_DATA_ITEM:
id = uri.getPathSegments().get(1);//获取该项目id并将其uri更新
count = db.update(TABLE.DATA, values, DataColumns.ID + "=" + id
+ parseSelection(selection), selectionArgs);
updateData = true;
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
if (count > 0) {//代码段:通知观察者,数据更新
if (updateData) {
getContext().getContentResolver().notifyChange(Notes.CONTENT_NOTE_URI, null);
}
getContext().getContentResolver().notifyChange(uri, null);
}
return count;
}
//将字符串解析成规定格式
private String parseSelection(String selection) {
return (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : "");
}
private void increaseNoteVersion(long id, String selection, String[] selectionArgs) {
StringBuilder sql = new StringBuilder(120);
sql.append("UPDATE ");
sql.append(TABLE.NOTE);
sql.append(" SET ");
sql.append(NoteColumns.VERSION);
sql.append("=" + NoteColumns.VERSION + "+1 ");
if (id > 0 || !TextUtils.isEmpty(selection)) {//操作条件selection不为空或者ID>0增加WHERE语句
sql.append(" WHERE ");
}
if (id > 0) {//如果id为正更新id
sql.append(NoteColumns.ID + "=" + String.valueOf(id));
}
if (!TextUtils.isEmpty(selection)) {//输入的文本非空的条件下输入到数据库中
String selectString = id > 0 ? parseSelection(selection) : selection;
for (String args : selectionArgs) {
selectString = selectString.replaceFirst("\\?", args);//用args替换掉的占位符
}
sql.append(selectString);//增加selectString语句
}
mHelper.getWritableDatabase().execSQL(sql.toString());//execSQL()方法可以执行insert、delete、update和CREATE TABLE之类有更改行为的SQL语句
}
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;//初始化,返回一个空指针
}
}