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.
xiaomi-Notes/SqlNote.java

865 lines
34 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.
*/
// 包含了处理与Google任务GTask相关的数据操作的类通常涉及数据的增、删、改、查等操作。
package net.micode.notes.gtask.data;
// 引入Android应用开发中所需的类库和工具
// 用于管理应用小部件
import android.appwidget.AppWidgetManager;
// 用于通过内容提供者与数据库交互
import android.content.ContentResolver;
// 存储数据行的值
import android.content.ContentValues;
// 用于获取应用的上下文
import android.content.Context;
// 用于操作数据库查询结果
import android.database.Cursor;
// 用于操作数据的URI
import android.net.Uri;
// 用于记录日志
import android.util.Log;
// 引入与笔记数据相关的类
// 笔记相关数据操作
import net.micode.notes.data.Notes;
// 用于标识笔记数据列
import net.micode.notes.data.Notes.DataColumns;
// 用于标识笔记属性列
import net.micode.notes.data.Notes.NoteColumns;
// 引入异常类,用于处理操作失败的情况
import net.micode.notes.gtask.exception.ActionFailureException;
// 引入工具类
// 用于处理GTask字符串的工具类
import net.micode.notes.tool.GTaskStringUtils;
// 用于解析资源文件的工具类
import net.micode.notes.tool.ResourceParser;
// 引入JSON处理相关的类
// 处理JSON数组
import org.json.JSONArray;
// 异常处理
import org.json.JSONException;
// 处理JSON对象
import org.json.JSONObject;
// 引入一个常用的集合类
// 用于操作动态数组
import java.util.ArrayList;
public class SqlNote {
// 定义一个静态常量 TAG用于记录日志时标识当前类通常是类名
private static final String TAG = SqlNote.class.getSimpleName();
// 定义一个静态常量 INVALID_ID通常表示一个无效的ID值
private static final int INVALID_ID = -99999;
// 定义一个静态常量 PROJECTION_NOTE这是一个字符串数组包含了多个列名
// 这些列名通常用于查询数据库时作为SELECT语句中所需的数据列
// 在这个例子中列名可能与一个笔记Note相关的数据库表字段对应
public static final String[] PROJECTION_NOTE = new String[] {
// 每个字符串代表数据库表中的一列,以下列举了相关列名
// 笔记的ID
NoteColumns.ID,
// 提醒时间
NoteColumns.ALERTED_DATE,
// 背景颜色ID
NoteColumns.BG_COLOR_ID,
// 创建时间
NoteColumns.CREATED_DATE,
// 是否有附件
NoteColumns.HAS_ATTACHMENT,
// 修改时间
NoteColumns.MODIFIED_DATE,
// 笔记数量
NoteColumns.NOTES_COUNT,
// 父级ID
NoteColumns.PARENT_ID,
// 摘要/片段内容
NoteColumns.SNIPPET,
// 笔记类型
NoteColumns.TYPE,
// 小部件ID
NoteColumns.WIDGET_ID,
// 小部件类型
NoteColumns.WIDGET_TYPE,
// 同步ID
NoteColumns.SYNC_ID,
// 本地修改标志
NoteColumns.LOCAL_MODIFIED,
// 原始父级ID
NoteColumns.ORIGIN_PARENT_ID,
// 与Google任务关联的ID
NoteColumns.GTASK_ID,
// 笔记的版本
NoteColumns.VERSION
}
// 定义各个列的索引值,表示每个列在数据库查询结果中的位置
// 笔记的ID列位置
public static final int ID_COLUMN = 0;
// 提醒日期列位置
public static final int ALERTED_DATE_COLUMN = 1;
// 背景颜色ID列位置
public static final int BG_COLOR_ID_COLUMN = 2;
// 创建日期列位置
public static final int CREATED_DATE_COLUMN = 3;
// 是否有附件列位置
public static final int HAS_ATTACHMENT_COLUMN = 4;
// 修改日期列位置
public static final int MODIFIED_DATE_COLUMN = 5;
// 笔记数量列位置
public static final int NOTES_COUNT_COLUMN = 6;
// 父级ID列位置
public static final int PARENT_ID_COLUMN = 7;
// 笔记摘要列位置
public static final int SNIPPET_COLUMN = 8;
// 笔记类型列位置
public static final int TYPE_COLUMN = 9;
// 小部件ID列位置
public static final int WIDGET_ID_COLUMN = 10;
// 小部件类型列位置
public static final int WIDGET_TYPE_COLUMN = 11;
// 同步ID列位置
public static final int SYNC_ID_COLUMN = 12;
// 本地修改标志列位置
public static final int LOCAL_MODIFIED_COLUMN = 13;
// 原始父级ID列位置
public static final int ORIGIN_PARENT_ID_COLUMN = 14;
// Google任务ID列位置
public static final int GTASK_ID_COLUMN = 15;
// 笔记版本列位置
public static final int VERSION_COLUMN = 16;
// 定义该类的成员变量
// 应用程序的上下文,通常用来访问系统服务和资源
private Context mContext;
// 内容解析器,用于与系统或应用程序的数据库进行交互
private ContentResolver mContentResolver;
// 标识该笔记是否是新创建的,布尔值标识
private boolean mIsCreate;
// 笔记的唯一标识符ID
private long mId;
// 笔记的提醒日期时间戳,表示笔记的提醒时间
private long mAlertDate;
// 笔记的背景颜色ID用于设置笔记的视觉背景颜色
private int mBgColorId;
// 笔记的创建日期时间戳,表示笔记被创建的时间
private long mCreatedDate;
// 一个整数值表示该笔记是否包含附件通常0表示没有附件1表示有附件
private int mHasAttachment;
// 笔记的最后修改日期时间戳,表示笔记被修改的时间
private long mModifiedDate;
// 父级笔记的ID通常用于表示该笔记所属的父级笔记如果存在的话
private long mParentId;
// 笔记的摘要或片段内容,通常是笔记的简短描述
private String mSnippet;
// 笔记的类型,通常是一个整数,表示笔记的类型(例如文本、图片等)
private int mType;
// 小部件的ID表示与笔记相关联的小部件的唯一标识符
private int mWidgetId;
// 小部件的类型,表示小部件的种类或用途
private int mWidgetType;
// 原始父级笔记的ID用于记录笔记的初始父级ID如果有父级笔记
private long mOriginParent;
// 笔记的版本号,用于表示笔记的版本,通常用于版本控制
private long mVersion;
// 存储笔记的差异值,通常用于记录笔记的变化(例如修改后的字段值)
private ContentValues mDiffNoteValues;
// 一个 `SqlData` 对象的列表,通常用于存储与该笔记相关的多条数据(例如附加数据、历史记录等)
private ArrayList<SqlData> mDataList;
public SqlNote(Context context) {
// 初始化应用程序上下文
mContext = context;
// 获取内容解析器,用于与应用程序的数据库交互
mContentResolver = context.getContentResolver();
// 将该笔记标识为新创建的笔记
mIsCreate = true;
// 设置该笔记的唯一标识符ID。通常初始为一个无效 ID用于数据库插入之前的标识符占位
mId = INVALID_ID;
// 默认的提醒日期时间戳为 0表示没有设置提醒
mAlertDate = 0;
// 从资源中获取默认的背景颜色ID
mBgColorId = ResourceParser.getDefaultBgId(context);
// 设置笔记的创建日期时间戳,使用当前系统时间的毫秒数
mCreatedDate = System.currentTimeMillis();
// 默认没有附件
mHasAttachment = 0;
// 设置笔记的最后修改日期时间戳,使用当前系统时间的毫秒数
mModifiedDate = System.currentTimeMillis();
// 默认的父级ID为 0表示该笔记没有父级笔记
mParentId = 0;
// 笔记的摘要部分,初始化为空字符串
mSnippet = "";
// 笔记类型,默认为普通笔记
mType = Notes.TYPE_NOTE;
// 小部件ID默认无效值
mWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
// 小部件类型,默认为无效值
mWidgetType = Notes.TYPE_WIDGET_INVALIDE;
// 原始父级ID默认为 0
mOriginParent = 0;
// 笔记的版本,初始版本为 0
mVersion = 0;
// 创建一个新的 `ContentValues` 实例,用于存储笔记数据的差异
mDiffNoteValues = new ContentValues();
// 初始化一个 `ArrayList`,用于存储与该笔记相关的其他数据(如附件数据、笔记历史记录等)
mDataList = new ArrayList<SqlData>();
}
public SqlNote(Context context, Cursor c) {
// 初始化上下文和内容解析器
mContext = context;
mContentResolver = context.getContentResolver();
// 标记当前笔记对象不是新创建的,通常从数据库查询出来的笔记对象
mIsCreate = false;
// 从 Cursor 中加载数据填充 SqlNote 对象
loadFromCursor(c);
// 初始化一个 ArrayList用于存储笔记相关的其他数据如附件、历史记录等
mDataList = new ArrayList<SqlData>();
// 如果笔记类型是普通笔记(非小部件或其他类型),则加载笔记的内容
if (mType == Notes.TYPE_NOTE)
loadDataContent();
// 初始化 ContentValues用于存储笔记的变化数据
mDiffNoteValues = new ContentValues();
}
public SqlNote(Context context, long id) {
// 初始化上下文和内容解析器
mContext = context;
mContentResolver = context.getContentResolver();
// 标记当前笔记对象不是新创建的
mIsCreate = false;
// 根据 id 从数据库中加载笔记数据
loadFromCursor(id);
// 初始化一个 ArrayList用于存储笔记相关的其他数据如附件、历史记录等
mDataList = new ArrayList<SqlData>();
// 如果笔记类型是普通笔记(非小部件或其他类型),则加载笔记的内容
if (mType == Notes.TYPE_NOTE)
loadDataContent();
// 初始化 ContentValues用于存储笔记的变化数据
mDiffNoteValues = new ContentValues();
}
// 根据提供的 id 从数据库加载笔记数据
private void loadFromCursor(long id) {
Cursor c = null;
try {
// 查询数据库,获取对应 id 的笔记数据
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, PROJECTION_NOTE, "(_id=?)",
new String[] { String.valueOf(id) }, null);
// 如果查询到数据
if (c != null) {
// 将 Cursor 移动到第一行(一般只有一行数据)
c.moveToNext();
// 从 Cursor 中加载数据到 SqlNote 对象
loadFromCursor(c);
} else {
// 如果查询结果为空,输出警告日志
Log.w(TAG, "loadFromCursor: cursor = null");
}
} finally {
// 无论如何,确保在方法结束时关闭 Cursor
if (c != null)
c.close();
}
}
private void loadFromCursor(Cursor c) {
// 从 Cursor 中提取各列的值并赋给相应的成员变量。
// ID 列的值
mId = c.getLong(ID_COLUMN);
// 提醒时间列的值
mAlertDate = c.getLong(ALERTED_DATE_COLUMN);
// 背景颜色 ID 列的值
mBgColorId = c.getInt(BG_COLOR_ID_COLUMN);
// 创建日期列的值
mCreatedDate = c.getLong(CREATED_DATE_COLUMN);
// 是否包含附件的标志0 或 1
mHasAttachment = c.getInt(HAS_ATTACHMENT_COLUMN);
// 修改日期列的值
mModifiedDate = c.getLong(MODIFIED_DATE_COLUMN);
// 父笔记 ID 列的值
mParentId = c.getLong(PARENT_ID_COLUMN);
// 摘要内容列的值
mSnippet = c.getString(SNIPPET_COLUMN);
// 笔记类型(例如:普通笔记、待办事项等)
mType = c.getInt(TYPE_COLUMN);
// 小部件 ID 列的值
mWidgetId = c.getInt(WIDGET_ID_COLUMN);
// 小部件类型列的值
mWidgetType = c.getInt(WIDGET_TYPE_COLUMN);
// 版本号列的值
mVersion = c.getLong(VERSION_COLUMN);
}
private void loadDataContent() {
// 定义一个 Cursor 用于查询数据
Cursor c = null;
// 清空原有的数据列表,准备加载新的数据
mDataList.clear();
try {
// 查询与当前笔记 ID 相关的数据
c = mContentResolver.query(Notes.CONTENT_DATA_URI, SqlData.PROJECTION_DATA,
"(note_id=?)", new String[] { String.valueOf(mId) }, null);
// 如果查询返回的 Cursor 不为空
if (c != null) {
// 如果查询结果为空,输出警告日志
if (c.getCount() == 0) {
Log.w(TAG, "it seems that the note has not data");
return;
}
// 遍历查询结果,将每一行数据封装成 SqlData 对象并添加到 mDataList 中
while (c.moveToNext()) {
SqlData data = new SqlData(mContext, c);
mDataList.add(data);
}
} else {
// 如果查询的 Cursor 为 null输出警告日志
Log.w(TAG, "loadDataContent: cursor = null");
}
} finally {
// 确保查询结束后关闭 Cursor释放资源
if (c != null)
c.close();
}
}
public boolean setContent(JSONObject js) {
try {
// 从传入的 JSON 对象中获取与笔记相关的元数据部分
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
// 判断笔记类型,如果是系统文件夹,则无法修改
if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) {
Log.w(TAG, "cannot set system folder");
}
// 如果是文件夹类型,只能更新摘要和类型字段
else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) {
// 获取摘要字段的值,如果没有则设为空字符串
String snippet = note.has(NoteColumns.SNIPPET) ? note.getString(NoteColumns.SNIPPET) : "";
// 如果是创建的笔记,或摘要字段发生变化,则记录变化
if (mIsCreate || !mSnippet.equals(snippet)) {
mDiffNoteValues.put(NoteColumns.SNIPPET, snippet);
}
// 更新当前笔记对象的摘要
mSnippet = snippet;
// 获取笔记类型字段的值,如果没有则默认为普通笔记类型
int type = note.has(NoteColumns.TYPE) ? note.getInt(NoteColumns.TYPE) : Notes.TYPE_NOTE;
// 如果是创建的笔记,或类型字段发生变化,则记录变化
if (mIsCreate || mType != type) {
mDiffNoteValues.put(NoteColumns.TYPE, type);
}
// 更新当前笔记对象的类型
mType = type;
}
// 如果是普通笔记类型
else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_NOTE) {
// 从传入的 JSON 中获取数据部分(如果有)
JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
// 获取笔记的唯一 ID如果没有则设为无效 ID
long id = note.has(NoteColumns.ID) ? note.getLong(NoteColumns.ID) : INVALID_ID;
// 如果是创建的笔记,或 ID 字段发生变化,则记录变化
if (mIsCreate || mId != id) {
mDiffNoteValues.put(NoteColumns.ID, id);
}
// 更新当前笔记对象的 ID
mId = id;
// 获取提醒时间字段的值,如果没有则默认为 0
long alertDate = note.has(NoteColumns.ALERTED_DATE) ? note.getLong(NoteColumns.ALERTED_DATE) : 0;
// 如果是创建的笔记,或提醒时间字段发生变化,则记录变化
if (mIsCreate || mAlertDate != alertDate) {
mDiffNoteValues.put(NoteColumns.ALERTED_DATE, alertDate);
}
// 更新当前笔记对象的提醒时间
mAlertDate = alertDate;
// 获取背景颜色 ID 字段的值,如果没有则使用默认的背景颜色 ID
int bgColorId = note.has(NoteColumns.BG_COLOR_ID) ? note.getInt(NoteColumns.BG_COLOR_ID) : ResourceParser.getDefaultBgId(mContext);
// 如果是创建的笔记,或背景颜色 ID 字段发生变化,则记录变化
if (mIsCreate || mBgColorId != bgColorId) {
mDiffNoteValues.put(NoteColumns.BG_COLOR_ID, bgColorId);
}
// 更新当前笔记对象的背景颜色 ID
mBgColorId = bgColorId;
// 获取创建时间字段的值,如果没有则使用当前时间戳
long createDate = note.has(NoteColumns.CREATED_DATE) ? note.getLong(NoteColumns.CREATED_DATE) : System.currentTimeMillis();
// 如果是创建的笔记,或创建时间字段发生变化,则记录变化
if (mIsCreate || mCreatedDate != createDate) {
mDiffNoteValues.put(NoteColumns.CREATED_DATE, createDate);
}
// 更新当前笔记对象的创建时间
mCreatedDate = createDate;
// 获取附件标志(是否包含附件),默认为 0没有附件
int hasAttachment = note.has(NoteColumns.HAS_ATTACHMENT) ? note.getInt(NoteColumns.HAS_ATTACHMENT) : 0;
// 如果是创建的笔记,或附件字段发生变化,则记录变化
if (mIsCreate || mHasAttachment != hasAttachment) {
mDiffNoteValues.put(NoteColumns.HAS_ATTACHMENT, hasAttachment);
}
// 更新当前笔记对象的附件标志
mHasAttachment = hasAttachment;
}
// 1. 获取修改日期,如果没有该字段则使用当前系统时间戳
long modifiedDate = note.has(NoteColumns.MODIFIED_DATE) ? note
.getLong(NoteColumns.MODIFIED_DATE) : System.currentTimeMillis();
// 2. 如果是创建操作,或者修改日期发生变化,则记录该字段的变化
if (mIsCreate || mModifiedDate != modifiedDate) {
mDiffNoteValues.put(NoteColumns.MODIFIED_DATE, modifiedDate);
}
// 3. 更新当前笔记对象的修改日期
mModifiedDate = modifiedDate;
// 4. 获取父级 ID如果没有该字段则默认为 0即记录笔记的父层级信息
long parentId = note.has(NoteColumns.PARENT_ID) ? note
.getLong(NoteColumns.PARENT_ID) : 0;
// 5. 如果是创建操作,或者父级 ID 发生变化,则记录该字段的变化
if (mIsCreate || mParentId != parentId) {
mDiffNoteValues.put(NoteColumns.PARENT_ID, parentId);
}
// 6. 更新当前笔记对象的父级 ID
mParentId = parentId;
// 7. 获取笔记摘要,如果没有该字段则默认为空字符串
String snippet = note.has(NoteColumns.SNIPPET) ? note
.getString(NoteColumns.SNIPPET) : "";
// 8. 如果是创建操作,或者摘要发生变化,则记录该字段的变化
if (mIsCreate || !mSnippet.equals(snippet)) {
mDiffNoteValues.put(NoteColumns.SNIPPET, snippet);
}
// 9. 更新当前笔记对象的摘要
mSnippet = snippet;
// 10. 获取笔记类型(如果没有该字段则默认为普通笔记类型)
int type = note.has(NoteColumns.TYPE) ? note.getInt(NoteColumns.TYPE)
: Notes.TYPE_NOTE;
// 11. 如果是创建操作,或者笔记类型发生变化,则记录该字段的变化
if (mIsCreate || mType != type) {
mDiffNoteValues.put(NoteColumns.TYPE, type);
}
// 12. 更新当前笔记对象的类型
mType = type;
// 13. 获取小部件 ID如果没有该字段则使用无效值
int widgetId = note.has(NoteColumns.WIDGET_ID) ? note.getInt(NoteColumns.WIDGET_ID)
: AppWidgetManager.INVALID_APPWIDGET_ID;
// 14. 如果是创建操作,或者小部件 ID 发生变化,则记录该字段的变化
if (mIsCreate || mWidgetId != widgetId) {
mDiffNoteValues.put(NoteColumns.WIDGET_ID, widgetId);
}
// 15. 更新当前笔记对象的小部件 ID
mWidgetId = widgetId;
// 16. 获取小部件类型(如果没有该字段则默认为无效类型)
int widgetType = note.has(NoteColumns.WIDGET_TYPE) ? note
.getInt(NoteColumns.WIDGET_TYPE) : Notes.TYPE_WIDGET_INVALIDE;
// 17. 如果是创建操作,或者小部件类型发生变化,则记录该字段的变化
if (mIsCreate || mWidgetType != widgetType) {
mDiffNoteValues.put(NoteColumns.WIDGET_TYPE, widgetType);
}
// 18. 更新当前笔记对象的小部件类型
mWidgetType = widgetType;
// 19. 获取原始父级 ID如果没有该字段则默认为 0通常用于记录笔记的移动历史或原始位置
long originParent = note.has(NoteColumns.ORIGIN_PARENT_ID) ? note
.getLong(NoteColumns.ORIGIN_PARENT_ID) : 0;
// 20. 如果是创建操作,或者原始父级 ID 发生变化,则记录该字段的变化
if (mIsCreate || mOriginParent != originParent) {
mDiffNoteValues.put(NoteColumns.ORIGIN_PARENT_ID, originParent);
}
// 21. 更新当前笔记对象的原始父级 ID
mOriginParent = originParent;
// 22. 遍历 `dataArray` 数组中的所有数据(可能是笔记的附加数据或附件等)
for (int i = 0; i < dataArray.length(); i++) {
// 23. 获取当前的数据项JSONObject
JSONObject data = dataArray.getJSONObject(i);
SqlData sqlData = null;
// 24. 如果数据项包含 ID 字段,则尝试在当前的数据列表中查找相应的 `SqlData`
if (data.has(DataColumns.ID)) {
long dataId = data.getLong(DataColumns.ID);
for (SqlData temp : mDataList) {
// 25. 如果在列表中找到了对应 ID 的 `SqlData`,则赋值
if (dataId == temp.getId()) {
sqlData = temp;
}
}
}
// 26. 如果没有找到对应的 `SqlData`,则创建一个新的 `SqlData` 实例
if (sqlData == null) {
sqlData = new SqlData(mContext);
mDataList.add(sqlData); // 将新创建的 `SqlData` 添加到数据列表中
}
// 27. 将当前的 JSON 数据传入 `sqlData` 对象进行处理
sqlData.setContent(data);
}
}
}
catch (JSONException e) {
// 1. 捕获并处理 JSON 异常JSONException这是针对在解析 JSON 数据过程中可能发生的异常
// 2. 将异常信息记录到日志中,使用 Log.e 方法打印错误日志。TAG 是日志标签,通常用于标识日志来源
Log.e(TAG, e.toString());
// 3. 打印堆栈跟踪信息,以便开发人员可以追踪异常发生的调用链和位置
e.printStackTrace();
// 4. 返回 false表示在处理过程中发生了异常操作失败
return false;
}
// 5. 如果没有异常发生,表示操作成功,返回 true
return true;
}
public JSONObject getContent() {
try {
// 1. 创建一个新的 JSON 对象,用于存储最终返回的数据
JSONObject js = new JSONObject();
// 2. 检查是否是创建状态,如果是创建状态,直接返回 null
if (mIsCreate) {
// 记录日志,提示该项尚未创建
Log.e(TAG, "it seems that we haven't created this in database yet");
// 由于没有创建记录,返回 null
return null;
}
// 3. 创建一个用于存储 note 信息的 JSON 对象
JSONObject note = new JSONObject();
// 4. 如果 mType 为 Notes.TYPE_NOTE表示这是一个普通笔记
if (mType == Notes.TYPE_NOTE) {
// 将笔记的各个属性添加到 JSON 对象中
// 添加 ID
note.put(NoteColumns.ID, mId);
// 添加提醒日期
note.put(NoteColumns.ALERTED_DATE, mAlertDate);
// 添加背景颜色 ID
note.put(NoteColumns.BG_COLOR_ID, mBgColorId);
// 添加创建日期
note.put(NoteColumns.CREATED_DATE, mCreatedDate);
// 添加是否有附件的标识
note.put(NoteColumns.HAS_ATTACHMENT, mHasAttachment);
// 添加修改日期
note.put(NoteColumns.MODIFIED_DATE, mModifiedDate);
// 添加父 ID
note.put(NoteColumns.PARENT_ID, mParentId);
// 添加笔记摘录
note.put(NoteColumns.SNIPPET, mSnippet);
// 添加笔记类型
note.put(NoteColumns.TYPE, mType);
// 添加小部件 ID
note.put(NoteColumns.WIDGET_ID, mWidgetId);
// 添加小部件类型
note.put(NoteColumns.WIDGET_TYPE, mWidgetType);
// 添加原始父 ID
note.put(NoteColumns.ORIGIN_PARENT_ID, mOriginParent);
// 将 note JSON 对象添加到最终返回的 JSON 对象中
js.put(GTaskStringUtils.META_HEAD_NOTE, note);
// 5. 创建一个 JSON 数组,用于存储数据项
JSONArray dataArray = new JSONArray();
for (SqlData sqlData : mDataList) {
// 获取 sqlData 对象的内容
JSONObject data = sqlData.getContent();
if (data != null) {
// 将数据项添加到 JSON 数组中
dataArray.put(data);
}
}
// 将数据数组添加到最终返回的 JSON 对象中
js.put(GTaskStringUtils.META_HEAD_DATA, dataArray);
}
// 6. 如果 mType 是 TYPE_FOLDER 或 TYPE_SYSTEM表示这是一个文件夹或系统类型
else if (mType == Notes.TYPE_FOLDER || mType == Notes.TYPE_SYSTEM) {
// 将文件夹或系统类型的基本信息添加到 JSON 对象中
note.put(NoteColumns.ID, mId); // 添加 ID
note.put(NoteColumns.TYPE, mType); // 添加类型
note.put(NoteColumns.SNIPPET, mSnippet); // 添加摘录
js.put(GTaskStringUtils.META_HEAD_NOTE, note); // 将 note JSON 对象添加到最终返回的 JSON 对象中
}
// 7. 返回最终的 JSON 对象
return js;
} catch (JSONException e) {
// 8. 捕获并处理 JSON 解析时的异常
Log.e(TAG, e.toString()); // 记录异常信息
e.printStackTrace(); // 打印异常的堆栈跟踪信息
}
// 如果发生异常,则返回 null
return null;
}
public void setParentId(long id) {
// 9. 设置父 ID
// 更新实例的 mParentId 属性
mParentId = id;
// 将父 ID 放入 mDiffNoteValues 中,可能用于后续的数据库更新
mDiffNoteValues.put(NoteColumns.PARENT_ID, id);
}
public void setGtaskId(String gid) {
// 设置 Gtask ID 到 mDiffNoteValues 中
mDiffNoteValues.put(NoteColumns.GTASK_ID, gid);
}
public void setSyncId(long syncId) {
// 设置同步 ID 到 mDiffNoteValues 中
mDiffNoteValues.put(NoteColumns.SYNC_ID, syncId);
}
public void resetLocalModified() {
// 重置本地修改标志,将其设置为 0
mDiffNoteValues.put(NoteColumns.LOCAL_MODIFIED, 0);
}
public long getId() {
// 返回笔记的 ID
return mId;
}
public long getParentId() {
// 返回父 ID
return mParentId;
}
public String getSnippet() {
// 返回笔记的摘录
return mSnippet;
}
public boolean isNoteType() {
// 判断当前对象是否是普通笔记类型
return mType == Notes.TYPE_NOTE;
}
public void commit(boolean validateVersion) {
// 如果是新创建的笔记
if (mIsCreate) {
// 如果笔记 ID 是无效的,且 mDiffNoteValues 中包含 ID移除它
if (mId == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) {
// 移除无效的 ID
mDiffNoteValues.remove(NoteColumns.ID);
}
// 尝试将笔记插入数据库mDiffNoteValues 存储了笔记的所有变化
Uri uri = mContentResolver.insert(Notes.CONTENT_NOTE_URI, mDiffNoteValues);
try {
// 从 URI 获取生成的 ID
// 获取 URI 路径段中的 ID 部分
mId = Long.valueOf(uri.getPathSegments().get(1));
} catch (NumberFormatException e) {
// 如果发生异常,记录错误并抛出自定义异常
Log.e(TAG, "Get note id error :" + e.toString());
throw new ActionFailureException("create note failed");
}
// 如果获取到的 ID 为 0说明创建失败抛出异常
if (mId == 0) {
throw new IllegalStateException("Create thread id failed");
}
// 如果是笔记类型(不是文件夹或系统类型),则提交相关的 SQL 数据
if (mType == Notes.TYPE_NOTE) {
// 对每个数据项进行提交
for (SqlData sqlData : mDataList) {
// 提交数据项,传递笔记 ID
sqlData.commit(mId, false, -1);
}
}
}
// 如果是更新现有的笔记
else {
// 如果笔记 ID 无效,并且不是根文件夹或通话记录文件夹,抛出异常
if (mId <= 0 && mId != Notes.ID_ROOT_FOLDER && mId != Notes.ID_CALL_RECORD_FOLDER) {
Log.e(TAG, "No such note");
throw new IllegalStateException("Try to update note with invalid id");
}
// 如果 mDiffNoteValues 中有更改数据
if (mDiffNoteValues.size() > 0) {
// 增加版本号
mVersion ++;
int result = 0;
// 如果不进行版本验证,直接更新数据
if (!validateVersion) {
result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "("
+ NoteColumns.ID + "=?)", new String[] {
String.valueOf(mId)
});
}
// 如果进行版本验证,确保更新的版本号不大于当前版本号
else {
result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "("
+ NoteColumns.ID + "=?) AND (" + NoteColumns.VERSION + "<=?)",
new String[] {
String.valueOf(mId), String.valueOf(mVersion)
});
}
// 如果更新失败,输出警告信息
if (result == 0) {
Log.w(TAG, "there is no update. maybe user updates note when syncing");
}
}
// 如果是笔记类型,提交与笔记相关的每个数据项
if (mType == Notes.TYPE_NOTE) {
for (SqlData sqlData : mDataList) {
sqlData.commit(mId, validateVersion, mVersion); // 提交数据项
}
}
}
// 刷新本地数据
// 从数据库中加载当前笔记的信息
loadFromCursor(mId);
if (mType == Notes.TYPE_NOTE)
// 如果是笔记类型,加载相关数据内容
loadDataContent();
// 清空更改的数据记录
mDiffNoteValues.clear();
// 标记为非创建状态
mIsCreate = false;
}
}