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.

269 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;
public class Note {
private ContentValues mNoteDiffValues;//声明了一个私有成员变量mNoteDiffValues用于存储笔记的差异数据
private NoteData mNoteData;
private static final String TAG = "Note";// 定义了一个静态常量TAG用于在日志输出时标记日志来源
/**
* Create a new note id for adding a new note to databases为添加新笔记到数据库中创建一个新的笔记id
*/
public static synchronized long getNewNoteId(Context context, long folderId) {
// Create a new note in the database在数据库中创建一个新笔记
ContentValues values = new ContentValues();// 创建一个ContentValues对象用于存储要添加的笔记数据
long createdTime = System.currentTimeMillis(); // 获取当前时间戳,作为笔记的创建时间和修改时间
values.put(NoteColumns.CREATED_DATE, createdTime);// 将笔记的创建时间存储到ContentValues对象中
values.put(NoteColumns.MODIFIED_DATE, createdTime);// 将笔记的修改时间存储到ContentValues对象中
values.put(NoteColumns.TYPE, Notes.TYPE_NOTE);// 将笔记的类型设置为“普通便签”
values.put(NoteColumns.LOCAL_MODIFIED, 1);// 将笔记的“本地修改”标志设置为“已修改”
values.put(NoteColumns.PARENT_ID, folderId);// 将笔记的父文件夹id存储到ContentValues对象中
Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values);// 将ContentValues对象插入到数据库中返回插入的笔记的Uri地址
long noteId = 0; // 定义一个变量用于存储新创建的笔记id
try {
noteId = Long.valueOf(uri.getPathSegments().get(1)); // 从Uri地址中提取新创建的笔记id
} catch (NumberFormatException e) { // 如果提取失败,记录错误日志
Log.e(TAG, "Get note id error :" + e.toString());
noteId = 0;
}
if (noteId == -1) {// 如果便签id异常抛出异常
throw new IllegalStateException("Wrong note id:" + noteId);
}
return noteId;// 返回新创建的便签id
}
public Note() {
mNoteDiffValues = new ContentValues();// 创建一个ContentValues对象用于存储便签的差异数据
mNoteData = new NoteData();// 创建一个NoteData对象用于存储便签的详细数据
}
public void setNoteValue(String key, String value) {
mNoteDiffValues.put(key, value);// 将便签的属性名和属性值存储到ContentValues对象中
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1);// 将便签的“本地修改”标志设置为“已修改”
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); // 将便签的修改时间设置为当前时间戳
}
public void setTextData(String key, String value) {
mNoteData.setTextData(key, value);
}//将便签的文本数据如标题、正文等存储到NoteData对象中
public void setTextDataId(long id) {
mNoteData.setTextDataId(id);
}// 将便签的文本数据的id存储到NoteData对象中
public long getTextDataId() {
return mNoteData.mTextDataId;
}// 返回便签的文本数据的id
public void setCallDataId(long id) {
mNoteData.setCallDataId(id);
}// 将便签的通讯数据的id存储到NoteData对象中
public void setCallData(String key, String value) {
mNoteData.setCallData(key, value);
}// 将便签的通讯数据如联系人、电话号码等存储到NoteData对象中
public boolean isLocalModified() {
return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified();
}// 检查便签是否被修改过如果便签的差异数据或详细数据被修改过则返回true否则返回false。
public boolean syncNote(Context context, long noteId) {
if (noteId <= 0) {
throw new IllegalArgumentException("Wrong note id:" + noteId);
}// 如果便签id异常抛出异常
if (!isLocalModified()) {
return true;
}// 如果便签没有被修改直接返回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理论上一旦数据发生更改应该更新{@link NoteColumns#LOCAL_MODIFIED}和{@link NoteColumns#MODIFIED_DATE}。
* 为了数据安全,虽然更新笔记失败,但仍然会更新笔记数据)
*/
if (context.getContentResolver().update(// 更新便签数据
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null,
null) == 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;// 如果更新失败返回false
}
return true;// 更新成功返回true
}
private class NoteData {// 定义私有字段
private long mTextDataId;// 文本数据的 ID
private ContentValues mTextDataValues;// 文本数据的 ContentValues 对象
private long mCallDataId;// 通话数据的 ID
private ContentValues mCallDataValues;// 通话数据的 ContentValues 对象
private static final String TAG = "NoteData";// 定义静态常量TAG
public NoteData() {// 定义构造函数
mTextDataValues = new ContentValues(); // 初始化文本数据的 ContentValues 对象
mCallDataValues = new ContentValues();// 初始化通话数据的 ContentValues 对象
mTextDataId = 0;// 初始化文本数据的 ID
mCallDataId = 0;// 初始化通话数据的 ID
}
boolean isLocalModified() {// 定义方法 isLocalModified判断数据是否被修改过
return mTextDataValues.size() > 0 || mCallDataValues.size() > 0;
}
void setTextDataId(long id) { // 定义方法 setTextDataId设置文本数据的 ID
if(id <= 0) {
throw new IllegalArgumentException("Text data id should larger than 0");
}
mTextDataId = id;
}
void setCallDataId(long id) {// 定义方法 setCallDataId设置通话数据的 ID
if (id <= 0) {
throw new IllegalArgumentException("Call data id should larger than 0");
}
mCallDataId = id;
}
void setCallData(String key, String value) {// 定义方法 setCallData用于设置通话数据的键值对
mCallDataValues.put(key, value);// 将键值对存储在 mCallDataValues 中
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1);// 标记数据已被修改
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); // 记录修改时间
}
void setTextData(String key, String value) {// 定义方法 setTextData用于设置文本数据的键值对
mTextDataValues.put(key, value);// 将键值对存储在 mTextDataValues 中
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); // 标记数据已被修改
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());// 记录修改时间
}
/**
* 这段代码定义了一个方法 pushIntoContentResolver用于将笔记数据保存到 ContentProvider 中。
* 该方法接受两个参数context 表示上下文noteId 表示笔记的 ID。
* 运行时首先会检查传入的参数是否合法,如果 noteId 小于等于 0则会抛出非法参数异常。
* 接下来,该方法会创建一个 ContentProviderOperation 列表,用于存储要执行的操作。
* 然后,该方法会检查 mTextDataValues 和 mCallDataValues 这两个成员变量中是否存储了文本数据和通话数据,
* 如果有,则会将它们保存到 ContentProvider 中。
* 如果 mTextDataId 或 mCallDataId 不为 0则会执行更新操作否则会执行插入操作。
* 最后,如果操作列表中有操作,则会通过 ContentResolver 将操作批量提交到 ContentProvider 中。
* 如果提交操作成功,则会返回笔记的 URI否则会返回 null。
* @param context
* @param noteId
* @return
*/
Uri pushIntoContentResolver(Context context, long noteId) {
/**
* Check for safety检查是否安全
*/
if (noteId <= 0) {
throw new IllegalArgumentException("Wrong note id:" + noteId);
}
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
ContentProviderOperation.Builder builder = null;// 创建一个ContentProviderOperation列表
if(mTextDataValues.size() > 0) {// 如果有文本数据需要更新或添加
mTextDataValues.put(DataColumns.NOTE_ID, noteId);// 设置文本数据的noteId
if (mTextDataId == 0) {
mTextDataValues.put(DataColumns.MIME_TYPE, TextNote.CONTENT_ITEM_TYPE);// 如果文本数据的id为0表示需要添加新的文本数据
Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI,
mTextDataValues);// 插入新的文本数据到数据表中
try {// 从插入结果中获取新插入数据的id
setTextDataId(Long.valueOf(uri.getPathSegments().get(1)));
} catch (NumberFormatException e) {
Log.e(TAG, "Insert new text data fail with noteId" + noteId);
mTextDataValues.clear();
return null;// 插入失败清空数据并返回null
}
} else {
builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mTextDataId));
builder.withValues(mTextDataValues);
operationList.add(builder.build());
} // 如果文本数据的id不为0表示需要更新已有的文本数据
mTextDataValues.clear();// 清空文本数据的值
}
if(mCallDataValues.size() > 0) {// 如果有电话数据需要更新或添加
mCallDataValues.put(DataColumns.NOTE_ID, noteId);// 设置电话数据的noteId
if (mCallDataId == 0) {// 如果电话数据的id为0表示需要添加新的电话数据
mCallDataValues.put(DataColumns.MIME_TYPE, CallNote.CONTENT_ITEM_TYPE);
Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI,
mCallDataValues);// 插入新的电话数据到数据表中
try { // 从插入结果中获取新插入数据的id
setCallDataId(Long.valueOf(uri.getPathSegments().get(1)));
} catch (NumberFormatException e) {
Log.e(TAG, "Insert new call data fail with noteId" + noteId);
mCallDataValues.clear();
return null;// 插入失败清空数据并返回null
}
} else {
builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mCallDataId));
builder.withValues(mCallDataValues);
operationList.add(builder.build());
} // 如果电话数据的id不为0表示需要更新已有的电话数据
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; // 操作失败返回null并记录日志
} catch (OperationApplicationException e) {
Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
return null;// 操作失败返回null并记录日志
}
}
return null;
}
}
}