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

313 lines
13 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;
// 导入所需的Android和内容提供者操作的类
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;
// 导入Java的ArrayList类
import java.util.ArrayList;
// 声明Note类
public class Note {
// 用于存储笔记差异值的ContentValues对象
private ContentValues mNoteDiffValues;
// 用于存储笔记数据的NoteData对象
private NoteData mNoteData;
// 用于日志记录的标签
private static final String TAG = "Note";
/**
* 创建一个新的笔记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); // 标记为本地已修改
values.put(NoteColumns.PARENT_ID, folderId); // 设置父文件夹ID
// 向内容提供者插入数据并获取返回的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;
}
// 如果noteId为-1则抛出异常
if (noteId == -1) {
throw new IllegalStateException("Wrong note id:" + noteId);
}
return noteId; // 返回新创建的笔记ID
}
// Note类的构造函数
public Note() {
mNoteDiffValues = new ContentValues(); // 初始化差异值对象
mNoteData = new NoteData(); // 初始化笔记数据对象
}
// 设置笔记的某个键值对,并标记为已修改
public void setNoteValue(String key, String value) {
mNoteDiffValues.put(key, value); // 存储键值对
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对象的方法设置文本数据
}
// 设置文本数据的ID
public void setTextDataId(long id) {
mNoteData.setTextDataId(id); // 调用NoteData对象的方法设置文本数据ID
}
// 获取文本数据的ID
public long getTextDataId() {
return mNoteData.mTextDataId; // 返回NoteData对象中的文本数据ID
}
// 设置通话数据的ID
public void setCallDataId(long id) {
mNoteData.setCallDataId(id); // 调用NoteData对象的方法设置通话数据ID
}
// 设置通话数据的某个键值对
public void setCallData(String key, String value) {
mNoteData.setCallData(key, value); // 调用NoteData对象的方法设置通话数据
}
// 判断笔记是否已本地修改
public boolean isLocalModified() {
return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified(); // 判断差异值对象或NoteData对象是否标记为已修改
}
// 同步笔记到数据库
public boolean syncNote(Context context, long noteId) {
if (noteId <= 0) {
throw new IllegalArgumentException("Wrong note id:" + noteId); // 如果笔记ID非法则抛出异常
}
if (!isLocalModified()) {
return true; // 如果笔记未修改则直接返回true
}
/**
* 理论上一旦数据改变就应该更新笔记的LOCAL_MODIFIED和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"); // 如果更新失败,则记录错误日志
// 不返回,继续执行后续代码
}
mNoteDiffValues.clear(); // 清空差异值对象
// 如果NoteData对象标记为已修改并且推送到内容提供者失败则返回false
if (mNoteData.isLocalModified()
&& (mNoteData.pushIntoContentResolver(context, noteId) == null)) {
return false;
}
return true; // 同步成功返回true
}
// 定义一个私有的内部类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() {
// 初始化文本数据和通话数据的ContentValues对象
mTextDataValues = new ContentValues();
mCallDataValues = new ContentValues();
// 初始化数据ID为0表示未设置
mTextDataId = 0;
mCallDataId = 0;
}
// 判断是否有本地数据被修改
boolean isLocalModified() {
// 如果文本数据或通话数据的ContentValues对象不为空则表示有数据被修改
return mTextDataValues.size() > 0 || mCallDataValues.size() > 0;
}
// 设置文本数据的ID
void setTextDataId(long id) {
// 如果传入的ID小于等于0则抛出异常
if(id <= 0) {
throw new IllegalArgumentException("Text data id should larger than 0");
}
// 设置文本数据的ID
mTextDataId = id;
}
// 设置通话数据的ID
void setCallDataId(long id) {
// 如果传入的ID小于等于0则抛出异常
if (id <= 0) {
throw new IllegalArgumentException("Call data id should larger than 0");
}
// 设置通话数据的ID
mCallDataId = id;
}
// 设置通话数据,并标记为已修改
void setCallData(String key, String value) {
// 将数据存入mCallDataValues
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
mTextDataValues.put(key, value);
// 标记为已修改注意同样mNoteDiffValues没有在类中定义
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1);
// 更新修改日期
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
}
// 将数据推送到ContentResolver中
Uri pushIntoContentResolver(Context context, long noteId) {
// 检查noteId的有效性
if (noteId <= 0) {
throw new IllegalArgumentException("Wrong note id:" + noteId);
}
// 创建一个操作列表,用于批量操作
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
ContentProviderOperation.Builder builder = null;
// 处理文本数据
if(mTextDataValues.size() > 0) {
// 添加noteId到文本数据中
mTextDataValues.put(DataColumns.NOTE_ID, noteId);
// 如果是新数据,则插入到数据库中
if (mTextDataId == 0) {
mTextDataValues.put(DataColumns.MIME_TYPE, TextNote.CONTENT_ITEM_TYPE);
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;
}
} else {
// 如果是已存在的数据,则更新
builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mTextDataId));
builder.withValues(mTextDataValues);
operationList.add(builder.build());
}
// 清理文本数据,为下一次操作做准备
mTextDataValues.clear();
}
// 处理通话数据,逻辑与文本数据处理相同
if(mCallDataValues.size() > 0) {
mCallDataValues.put(DataColumns.NOTE_ID, noteId);
if (mCallDataId == 0) {
mCallDataValues.put(DataColumns.MIME_TYPE, CallNote.CONTENT_ITEM_TYPE);
Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI,
mCallDataValues);
try {
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;
}
} else {
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);
// 返回操作结果的URI如果结果为空则返回null
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;
}
}
// 如果没有操作则返回null
return null;
}
}