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.
text123/Note.java

366 lines
14 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.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;
import android.net.Uri;
import android.os.RemoteException;
import android.util.Log;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.CallNote;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.Notes.TextNote;
import java.util.ArrayList;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
// 定义一个名为Note的类用于处理笔记相关的操作
public class Note {
// 用于存储笔记差异值的ContentValues对象
private ContentValues mNoteDiffValues;
// 用于存储笔记数据的NoteData对象
private NoteData mNoteData;
// 用于日志记录的标签
private static final String TAG = "Note";
/**
* 创建一个新的笔记ID用于将新笔记添加到数据库中
*
* @param context 应用上下文
* @param folderId 笔记所属文件夹的ID
* @return 新创建的笔记ID
*/
public static synchronized long getNewNoteId(Context context, long folderId) {
// 创建一个ContentValues对象用于存储新笔记的初始数据
ContentValues values = new ContentValues();
// 获取当前时间作为笔记的创建时间和修改时间
long createdTime = System.currentTimeMillis();
values.put(NoteColumns.CREATED_DATE, createdTime);
values.put(NoteColumns.MODIFIED_DATE, createdTime);
// 设置笔记类型为普通笔记
values.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
// 标记该笔记为本地修改过
values.put(NoteColumns.LOCAL_MODIFIED, 1);
// 设置笔记所属的文件夹ID
values.put(NoteColumns.PARENT_ID, folderId);
// 向笔记内容URI插入新笔记数据返回插入后的URI
Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values);
long noteId = 0;
try {
// 从插入后的URI中提取笔记ID
noteId = Long.valueOf(uri.getPathSegments().get(1));
} catch (NumberFormatException e) {
// 如果提取ID时发生数字格式异常记录错误日志并将noteId设为0
Log.e(TAG, "Get note id error :" + e.toString());
noteId = 0;
}
// 如果笔记ID为-1说明出现错误抛出异常
if (noteId == -1) {
throw new IllegalStateException("Wrong note id:" + noteId);
}
// 返回新创建的笔记ID
return noteId;
}
// Note类的构造函数初始化mNoteDiffValues和mNoteData
public Note() {
mNoteDiffValues = new ContentValues();
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) {
// 检查笔记ID是否合法
if (noteId <= 0) {
throw new IllegalArgumentException("Wrong note id:" + noteId);
}
// 如果笔记没有在本地被修改直接返回true
if (!isLocalModified()) {
return true;
}
/**
* 理论上,一旦数据发生变化,笔记的{@link NoteColumns#LOCAL_MODIFIED}和
* {@link NoteColumns#MODIFIED_DATE}应该被更新。为了数据安全,即使更新笔记失败,我们也会更新
* 笔记数据信息
*/
// 更新数据库中指定笔记ID的笔记数据
if (context.getContentResolver().update(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null,
null) == 0) {
// 如果更新失败,记录错误日志
Log.e(TAG, "Update note error, should not happen");
// 不返回,继续执行后续代码
}
// 清空mNoteDiffValues
mNoteDiffValues.clear();
// 如果笔记文本数据在本地被修改,将其推送到内容解析器
if (mNoteData.isLocalModified()
&& (mNoteData.pushIntoContentResolver(context, noteId) == null)) {
return false;
}
// 同步成功返回true
return true;
}
// Note类中的私有内部类NoteData用于处理笔记的具体数据
private class NoteData {
// 文本数据的ID
private long mTextDataId;
// 存储文本数据的ContentValues对象
private ContentValues mTextDataValues;
// 通话数据的ID
private long mCallDataId;
// 存储通话数据的ContentValues对象
private ContentValues mCallDataValues;
// 用于日志记录的标签
private static final String TAG = "NoteData";
// NoteData类的构造函数初始化成员变量
public NoteData() {
mTextDataValues = new ContentValues();
mCallDataValues = new ContentValues();
mTextDataId = 0;
mCallDataId = 0;
}
// 判断文本数据或通话数据是否在本地被修改过
boolean isLocalModified() {
return mTextDataValues.size() > 0 || mCallDataValues.size() > 0;
}
// 设置文本数据的IDID必须大于0
void setTextDataId(long id) {
if (id <= 0) {
throw new IllegalArgumentException("Text data id should larger than 0");
}
mTextDataId = id;
}
// 设置通话数据的IDID必须大于0
void setCallDataId(long id) {
if (id <= 0) {
throw new IllegalArgumentException("Call data id should larger than 0");
}
mCallDataId = id;
}
// 设置通话数据的某个属性值,并更新相关的修改标记和时间
void setCallData(String key, String value) {
mCallDataValues.put(key, value);
// 这里访问了外部类的mNoteDiffValues用于标记整个笔记的修改
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1);
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
}
// 设置文本数据的某个属性值,并更新相关的修改标记和时间
void setTextData(String key, String value) {
mTextDataValues.put(key, value);
// 这里访问了外部类的mNoteDiffValues用于标记整个笔记的修改
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1);
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
}
// 将本地修改的文本数据和通话数据推送到内容解析器
Uri pushIntoContentResolver(Context context, long noteId) {
// 检查笔记ID是否合法
if (noteId <= 0) {
throw new IllegalArgumentException("Wrong note id:" + noteId);
}
// 创建一个用于存储ContentProvider操作的列表
ArrayList<ContentProviderOperation> operationList = new ArrayList<>();
ContentProviderOperation.Builder builder = null;
// 如果有需要更新的文本数据
if (mTextDataValues.size() > 0) {
// 将笔记ID添加到文本数据中
mTextDataValues.put(DataColumns.NOTE_ID, noteId);
// 如果文本数据ID为0说明是新数据需要插入
if (mTextDataId == 0) {
// 设置文本数据的MIME类型
mTextDataValues.put(DataColumns.MIME_TYPE, TextNote.CONTENT_ITEM_TYPE);
// 向内容解析器插入文本数据
Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, mTextDataValues);
try {
// 从插入后的URI中提取文本数据ID并设置
setTextDataId(Long.valueOf(uri.getPathSegments().get(1)));
} catch (NumberFormatException e) {
// 如果提取ID失败记录错误日志并清空文本数据
Log.e(TAG, "Insert new text data fail with noteId" + noteId);
mTextDataValues.clear();
return null;
}
} else {
// 如果文本数据ID不为0说明是更新操作
builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mTextDataId));
// 设置要更新的内容
builder.withValues(mTextDataValues);
// 将操作添加到操作列表中
operationList.add(builder.build());
}
// 清空文本数据的ContentValues对象
mTextDataValues.clear();
}
// 如果有需要更新的通话数据
if (mCallDataValues.size() > 0) {
// 将笔记ID添加到通话数据中
mCallDataValues.put(DataColumns.NOTE_ID, noteId);
// 如果通话数据ID为0说明是新数据需要插入
if (mCallDataId == 0) {
// 设置通话数据的MIME类型
mCallDataValues.put(DataColumns.MIME_TYPE, CallNote.CONTENT_ITEM_TYPE);
// 向内容解析器插入通话数据
Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, mCallDataValues);
try {
// 从插入后的URI中提取通话数据ID并设置
setCallDataId(Long.valueOf(uri.getPathSegments().get(1)));
} catch (NumberFormatException e) {
// 如果提取ID失败记录错误日志并清空通话数据
Log.e(TAG, "Insert new call data fail with noteId" + noteId);
mCallDataValues.clear();
return null;
}
} else {
// 如果通话数据ID不为0说明是更新操作
builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mCallDataId));
// 设置要更新的内容
builder.withValues(mCallDataValues);
// 将操作添加到操作列表中
operationList.add(builder.build());
}
// 清空通话数据的ContentValues对象
mCallDataValues.clear();
}
// 如果操作列表中有操作
if (operationList.size() > 0) {
try {
// 批量执行操作列表中的操作
ContentProviderResult[] results = context.getContentResolver().applyBatch(
Notes.AUTHORITY, operationList);
// 根据操作结果返回相应的URI
return (results == null || results.length == 0 || results[0] == null)? null
: ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId);
} catch (RemoteException e) {
// 如果发生远程异常,记录错误日志
Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
return null;
} catch (OperationApplicationException e) {
// 如果发生操作应用异常,记录错误日志
Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
return null;
}
}
return null;
}
}
}