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

324 lines
17 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;
public class Note {
// 用于存储笔记发生变化的相关数据,例如修改日期、是否本地修改等信息
private ContentValues mNoteDiffValues;
// 存储笔记具体的数据像文本数据、通话数据等相关内容通过内部类NoteData来管理
private NoteData mNoteData;
// 用于日志记录时标识当前类的标签
private static final String TAG = "Note";
/**
* Create a new note id for adding a new note to databases
* 创建一个新的笔记ID用于向数据库中添加新笔记
*/
public static synchronized long getNewNoteId(Context context, long folderId) {
// 创建一个新的ContentValues对象用于存放要插入数据库的键值对数据
ContentValues values = new ContentValues();
// 获取当前系统时间的毫秒数,作为创建时间和初始修改时间
long createdTime = System.currentTimeMillis();
// 将创建时间放入ContentValues中对应数据库表中的CREATED_DATE字段
values.put(NoteColumns.CREATED_DATE, createdTime);
// 将修改时间放入ContentValues中对应数据库表中的MODIFIED_DATE字段初始与创建时间相同
values.put(NoteColumns.MODIFIED_DATE, createdTime);
// 设置笔记的类型这里假定Notes.TYPE_NOTE是定义好的表示笔记类型的常量
values.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
// 设置本地修改标识为1表示有本地修改可能后续会根据实际情况改变这个值
values.put(NoteColumns.LOCAL_MODIFIED, 1);
// 设置父文件夹的ID用于在数据库中关联笔记所属的文件夹
values.put(NoteColumns.PARENT_ID, folderId);
// 通过内容解析器向指定的笔记内容URINotes.CONTENT_NOTE_URI应该是预定义的常量插入数据并获取返回的Uri
Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values);
long noteId = 0;
try {
// 尝试从返回的Uri的路径片段中获取第二个元素通常是新插入笔记的ID并转换为long类型
noteId = Long.valueOf(uri.getPathSegments().get(1));
} catch (NumberFormatException e) {
// 如果在转换过程中出现数字格式异常记录错误日志并将noteId设置为0
Log.e(TAG, "Get note id error :" + e.toString());
noteId = 0;
}
if (noteId == -1) {
// 如果获取到的笔记ID为 -1抛出非法状态异常提示错误的笔记ID
throw new IllegalStateException("Wrong note id:" + noteId);
}
return noteId;
}
public Note() {
// 初始化用于存储笔记变化数据的ContentValues对象
mNoteDiffValues = new ContentValues();
// 初始化管理笔记具体数据的NoteData对象
mNoteData = new NoteData();
}
public void setNoteValue(String key, String value) {
// 将传入的键值对放入mNoteDiffValues中用于记录笔记的某个属性值变化
mNoteDiffValues.put(key, value);
// 更新本地修改标识为1表示有本地修改
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1);
// 更新修改日期为当前系统时间的毫秒数
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
}
public void setTextData(String key, String value) {
// 调用内部类NoteData的setTextData方法传递键值对用于设置笔记的文本数据相关内容
mNoteData.setTextData(key, value);
}
public void setTextDataId(long id) {
// 调用内部类NoteData的setTextDataId方法传递ID值用于设置笔记文本数据的ID
mNoteData.setTextDataId(id);
}
public long getTextDataId() {
// 返回内部类NoteData中存储的文本数据的ID
return mNoteData.mTextDataId;
}
public void setCallDataId(long id) {
// 调用内部类NoteData的setCallDataId方法传递ID值用于设置笔记通话数据的ID
mNoteData.setCallDataId(id);
}
public void setCallData(String key, String value) {
// 调用内部类NoteData的setCallData方法传递键值对用于设置笔记的通话数据相关内容
mNoteData.setCallData(key, value);
}
public boolean isLocalModified() {
// 判断笔记是否有本地修改通过检查mNoteDiffValues的大小即是否有属性变化记录以及mNoteData对象是否有本地修改来综合判断
return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified();
}
public boolean syncNote(Context context, long noteId) {
if (noteId <= 0) {
// 如果传入的笔记ID小于等于0抛出非法参数异常提示错误的笔记ID
throw new IllegalArgumentException("Wrong note id:" + noteId);
}
if (!isLocalModified()) {
// 如果笔记没有本地修改直接返回true表示无需同步操作
return true;
}
/**
* In theory, once data changed, the note should be updated on {@link NoteColumns#LOCAL_MODIFIED} and
* {@link NoteColumns#MODIFIED_DATE}. For data safety, though update note fails, we also update the
* note data info
* 理论上一旦数据发生变化笔记应该在NoteColumns.LOCAL_MODIFIED和NoteColumns.MODIFIED_DATE字段上进行更新。为了数据安全即使更新笔记失败我们也要更新笔记数据信息
*/
if (context.getContentResolver().update(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null,
null) == 0) {
// 如果通过内容解析器更新笔记数据失败返回0表示影响的行数为0即更新失败记录错误日志但不直接返回继续往下执行
Log.e(TAG, "Update note error, should not happen");
// Do not return, fall through
}
// 清除已经同步过的笔记变化数据(可能是为了下次记录新的变化)
mNoteDiffValues.clear();
if (mNoteData.isLocalModified()
&& (mNoteData.pushIntoContentResolver(context, noteId) == null)) {
return false;
}
return true;
}
private class NoteData {
// 存储笔记文本数据的ID
private long mTextDataId;
// 用于存储笔记文本数据的相关属性值的ContentValues对象
private ContentValues mTextDataValues;
// 存储笔记通话数据的ID
private long mCallDataId;
// 用于存储笔记通话数据的相关属性值的ContentValues对象
private ContentValues mCallDataValues;
// 用于日志记录时标识内部类NoteData的标签
private static final String TAG = "NoteData";
public NoteData() {
// 初始化用于存储笔记文本数据属性值的ContentValues对象
mTextDataValues = new ContentValues();
// 初始化用于存储笔记通话数据属性值的ContentValues对象
mCallDataValues = new ContentValues();
// 初始文本数据的ID设置为0
mTextDataId = 0;
// 初始通话数据的ID设置为0
mCallDataId = 0;
}
boolean isLocalModified() {
// 判断笔记的文本数据或通话数据是否有本地修改通过检查对应的ContentValues对象的大小来判断即是否有属性变化记录
return mTextDataValues.size() > 0 || mCallDataValues.size() > 0;
}
void setTextDataId(long id) {
if (id <= 0) {
// 如果传入的文本数据ID小于等于0抛出非法参数异常要求ID应该大于0
throw new IllegalArgumentException("Text data id should larger than 0");
}
mTextDataId = id;
}
void setCallDataId(long id) {
if (id <= 0) {
// 如果传入的通话数据ID小于等于0抛出非法参数异常要求ID应该大于0
throw new IllegalArgumentException("Call data id should larger than 0");
}
mCallDataId = id;
}
void setCallData(String key, String value) {
// 将传入的键值对放入mCallDataValues中用于记录笔记通话数据的某个属性值变化
mCallDataValues.put(key, value);
// 更新外部类Note中的本地修改标识为1表示有本地修改
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1);
// 更新外部类Note中的修改日期为当前系统时间的毫秒数
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
}
void setTextData(String key, String value) {
// 将传入的键值对放入mTextDataValues中用于记录笔记文本数据的某个属性值变化
mTextDataValues.put(key, value);
// 更新外部类Note中的本地修改标识为1表示有本地修改
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1);
// 更新外部类Note中的修改日期为当前系统时间的毫秒数
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
}
Uri pushIntoContentResolver(Context context, long noteId) {
/**
* Check for safety
* 进行安全性检查确保传入的笔记ID是合法的大于0
*/
if (noteId <= 0) {
throw new IllegalArgumentException("Wrong note id:" + noteId);
}
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
ContentProviderOperation.Builder builder = null;
if (mTextDataValues.size() > 0) {
// 将笔记ID放入文本数据的属性值中用于关联对应的笔记
mTextDataValues.put(DataColumns.NOTE_ID, noteId);
if (mTextDataId == 0) {
// 如果文本数据的ID为0表示是新插入的数据设置对应的MIME_TYPE类型TextNote.CONTENT_ITEM_TYPE应该是预定义的常量
mTextDataValues.put(DataColumns.MIME_TYPE, TextNote.CONTENT_ITEM_TYPE);
// 通过内容解析器向指定的笔记数据内容URINotes.CONTENT_DATA_URI应该是预定义的常量插入数据并获取返回的Uri
Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI,
mTextDataValues);
try {
// 尝试从返回的Uri的路径片段中获取第二个元素通常是新插入文本数据的ID并转换为long类型设置为文本数据的ID
setTextDataId(Long.valueOf(uri.getPathSegments().get(1)));
} catch (NumberFormatException e) {
// 如果在转换过程中出现数字格式异常记录错误日志清除文本数据的属性值并返回null表示插入失败
Log.e(TAG, "Insert new text data fail with noteId" + noteId);
mTextDataValues.clear();
return null;
}
} else {
// 如果文本数据的ID不为0表示是更新操作创建一个ContentProviderOperation的更新构建器
builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mTextDataId));
// 设置要更新的值为当前的文本数据属性值
builder.withValues(mTextDataValues);
// 将构建好的更新操作添加到操作列表中
operationList.add(builder.build());
}
// 清除文本数据的属性值(可能是为了下次重新记录新变化)
mTextDataValues.clear();
}
if (mCallDataValues.size() > 0) {
// 将笔记ID放入通话数据的属性值中用于关联对应的笔记
mCallDataValues.put(DataColumns.NOTE_ID, noteId);
if (mCallDataId == 0) {
// 如果通话数据的ID为0表示是新插入的数据设置对应的MIME_TYPE类型CallNote.CONTENT_ITEM_TYPE应该是预定义的常量
mCallDataValues.put(DataColumns.MIME_TYPE, CallNote.CONTENT_ITEM_TYPE);
// 通过内容解析器向指定的笔记数据内容URINotes.CONTENT_DATA_URI应该是预定义的常量插入数据并获取返回的Uri
Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI,
mCallDataValues);
try {
// 尝试从返回的Uri的路径片段中获取第二个元素通常是新插入通话数据的ID并转换为long类型设置为通话数据的ID
setCallDataId(Long.valueOf(uri.getPathSegments().get(1)));
} catch (NumberFormatException e) {
// 如果在转换过程中出现数字格式异常记录错误日志清除通话数据的属性值并返回null表示插入失败
Log.e(TAG, "Insert new call data fail with noteId" + noteId);
mCallDataValues.clear();
return null;
}
} else {
// 如果通话数据的ID不为0表示是更新操作创建一个ContentProviderOperation的更新构建器
builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mCallDataId));
// 设置要更新的值为当前的通话数据属性值
builder.withValues(mCallDataValues);
// 将构建好的更新操作添加到操作列表中
operationList.add(builder.build());
}
// 清除通话数据的属性值(可能是为了下次重新记录新变化)
mCallDataValues.clear();
}
if (operationList.size() > 0) {
try {
// 通过内容解析器批量执行操作列表中的所有内容提供器操作,并获取操作结果数组
ContentProviderResult[] results = context.getContentResolver().applyBatch(
Notes.AUTHORITY, operationList);
// 如果结果数组为空、长度为0或者第一个元素为null返回null否则返回关联了笔记ID的对应笔记内容的Uri
return (results == null || results.length == 0 || results[0] == null)? null
: ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId);
} catch (RemoteException e) {
// 如果出现远程异常记录错误日志并返回null
Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
return null;
} catch (OperationApplicationException e) {
// 如果出现操作应用异常记录错误日志并返回null
Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
return null;
}
}
return null;
}
}
}