|
|
/*
|
|
|
* 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.
|
|
|
*/
|
|
|
|
|
|
//包声明:
|
|
|
// 该类属于 net.micode.notes.gtask.data 包,通常表示这是一个与 Google Tasks 或某个任务管理相关的数据模型类。
|
|
|
package net.micode.notes.gtask.data;
|
|
|
|
|
|
//导入 Cursor 类:
|
|
|
// Cursor 是 Android 中用于从数据库中查询数据的接口,通常用于访问 SQLite 数据库中的记录。
|
|
|
import android.database.Cursor;
|
|
|
|
|
|
//导入 TextUtils 类:
|
|
|
// TextUtils 是 Android 提供的工具类,包含了一些常用的字符串操作方法,如判断字符串是否为空或是否匹配某些模式等。
|
|
|
import android.text.TextUtils;
|
|
|
|
|
|
//导入 Log 类:
|
|
|
// Log 类用于 Android 中的日志输出,开发者可以使用它记录调试信息、错误日志等。
|
|
|
import android.util.Log;
|
|
|
|
|
|
//导入 Notes 类:
|
|
|
// 这个类可能是应用中用于表示便签或任务的类。Notes 类中的常量和方法通常用于访问或操作任务和便签相关的数据。
|
|
|
import net.micode.notes.data.Notes;
|
|
|
|
|
|
//导入 DataColumns, DataConstants, NoteColumns:
|
|
|
// 这些导入语句表明,这些类包含 Notes 类中的常量和字段,它们可能用于表示与任务或便签相关的列名、常量定义等。
|
|
|
import net.micode.notes.data.Notes.DataColumns;
|
|
|
import net.micode.notes.data.Notes.DataConstants;
|
|
|
import net.micode.notes.data.Notes.NoteColumns;
|
|
|
|
|
|
//导入 ActionFailureException 类:
|
|
|
// 这个自定义异常类 ActionFailureException 可能用于处理在执行某些操作时发生的错误,表示某些操作失败。
|
|
|
import net.micode.notes.gtask.exception.ActionFailureException;
|
|
|
|
|
|
//导入 GTaskStringUtils 工具类:
|
|
|
// 这个类看起来是与 Google Tasks 相关的字符串工具类,可能包含处理任务相关字符串的实用方法。
|
|
|
import net.micode.notes.tool.GTaskStringUtils;
|
|
|
|
|
|
//导入 org.json 库的类:这些类用于处理 JSON 数据。
|
|
|
// 在任务管理应用中,任务通常是以 JSON 格式存储或传输的,JSONArray, JSONException, 和 JSONObject 提供了处理 JSON 数据所需的工具。
|
|
|
import org.json.JSONArray;
|
|
|
import org.json.JSONException;
|
|
|
import org.json.JSONObject;
|
|
|
|
|
|
|
|
|
//类:Task 类继承自 Node 类,表示任务的基本模型,包含任务的状态、备注、父任务、优先级等信息。
|
|
|
//Task 类的构造函数:
|
|
|
//初始化了 mCompleted(任务是否完成)、mNotes(任务备注)、mPriorSibling(前一个兄弟任务)、
|
|
|
// mParent(父任务列表)和 mMetaInfo(任务的元数据信息)等属性。
|
|
|
public class Task extends Node {
|
|
|
|
|
|
// 用于日志输出时标识当前类名
|
|
|
private static final String TAG = Task.class.getSimpleName();
|
|
|
|
|
|
// 任务是否完成
|
|
|
private boolean mCompleted;
|
|
|
// 任务的备注信息
|
|
|
private String mNotes;
|
|
|
// 任务的元数据信息,可能包含额外的任务信息
|
|
|
private JSONObject mMetaInfo;
|
|
|
// 当前任务的前一个兄弟任务
|
|
|
private Task mPriorSibling;
|
|
|
// 当前任务所属的任务列表(父任务列表)
|
|
|
private TaskList mParent;
|
|
|
|
|
|
// 构造函数:初始化 Task 对象的默认值
|
|
|
public Task() {
|
|
|
// 调用父类构造函数(假设父类 Node 也有构造函数)
|
|
|
super();
|
|
|
// 默认任务未完成
|
|
|
mCompleted = false;
|
|
|
// 默认没有备注
|
|
|
mNotes = null;
|
|
|
// 默认没有前一个兄弟任务
|
|
|
mPriorSibling = null;
|
|
|
// 默认没有父任务列表
|
|
|
mParent = null;
|
|
|
// 默认没有元数据
|
|
|
mMetaInfo = null;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 生成任务创建的 JSON 数据,表示一个任务的创建动作。
|
|
|
*
|
|
|
* @param actionId 任务创建动作的 ID
|
|
|
* @return 生成的包含任务创建信息的 JSONObject
|
|
|
*/
|
|
|
/*
|
|
|
方法:getCreateAction(int actionId) 生成一个包含任务创建信息的 JSONObject,用于表示一个任务创建的动作。
|
|
|
|
|
|
getCreateAction(int actionId) 方法:
|
|
|
功能:
|
|
|
该方法的主要任务是生成一个 JSONObject,它表示创建任务的动作(create action)。
|
|
|
这个 JSON 对象会包含任务的基本信息,比如名称、创建者 ID、任务类型、父任务 ID、任务列表 ID 等等。
|
|
|
步骤解析:
|
|
|
初始化 JSONObject:创建一个新的 JSONObject(js)对象,用于保存任务创建的所有信息。
|
|
|
设置基本属性:
|
|
|
action_type:表示动作类型,这里是创建任务。
|
|
|
action_id:任务创建动作的唯一 ID,通过方法参数 actionId 传入。
|
|
|
index:任务在其父任务列表中的索引位置,使用 mParent.getChildTaskIndex(this) 获取当前任务在父任务列表中的位置。
|
|
|
创建任务的基本信息:
|
|
|
创建一个名为 entity 的 JSON 对象,包含任务的名称、创建者 ID(默认为 null)、任务类型(这里是 "task")等基本信息。
|
|
|
添加备注:
|
|
|
如果任务有备注(mNotes 不为 null),则将备注信息添加到 entity 中。
|
|
|
设置父任务 ID 和任务列表 ID:
|
|
|
分别通过 mParent.getGid() 获取父任务列表的 ID,并将其存储在 JSON 对象中。
|
|
|
设置前一个兄弟任务 ID:
|
|
|
如果当前任务有前一个兄弟任务(mPriorSibling != null),则将其 ID 添加到 JSON 对象中。
|
|
|
错误处理:
|
|
|
在构建 JSON 的过程中,如果发生 JSONException 异常,记录错误信息并抛出自定义的 ActionFailureException。
|
|
|
JSONException 和 ActionFailureException:
|
|
|
|
|
|
JSONException:
|
|
|
这是 JSON 操作过程中可能抛出的异常,用于处理在构建 JSON 对象时出现的错误。
|
|
|
ActionFailureException:
|
|
|
这是自定义的异常类,用于表示任务创建过程中操作失败的情况。在 JSON 构建失败时,抛出该异常。
|
|
|
日志记录:
|
|
|
|
|
|
使用 Log.e(TAG, e.toString()) 将错误信息打印到日志中,以便开发者调试时查看。
|
|
|
e.printStackTrace() 打印异常栈信息,帮助追踪错误的详细位置。
|
|
|
|
|
|
*/
|
|
|
public JSONObject getCreateAction(int actionId) {
|
|
|
// 创建一个新的 JSON 对象,用于保存任务的创建信息
|
|
|
JSONObject js = new JSONObject();
|
|
|
|
|
|
try {
|
|
|
// 设置 action_type,表示这是一个任务创建的操作
|
|
|
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
|
|
|
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE);
|
|
|
|
|
|
// 设置 action_id,任务创建动作的唯一 ID
|
|
|
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
|
|
|
|
|
|
// 设置任务在父任务列表中的索引位置
|
|
|
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mParent.getChildTaskIndex(this));
|
|
|
|
|
|
// 创建一个 JSON 对象 entity,用于表示任务的基本信息(任务名称、创建者 ID、任务类型等)
|
|
|
JSONObject entity = new JSONObject();
|
|
|
// 设置任务的名称
|
|
|
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
|
|
|
// 设置任务创建者 ID,这里默认为 "null"
|
|
|
entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null");
|
|
|
entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE,
|
|
|
GTaskStringUtils.GTASK_JSON_TYPE_TASK); // 设置任务的类型为 "task"
|
|
|
|
|
|
// 如果任务有备注信息,添加备注到 entity 中
|
|
|
if (getNotes() != null) {
|
|
|
entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes());
|
|
|
}
|
|
|
|
|
|
// 将任务的 entity 信息放入 JSON 中
|
|
|
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
|
|
|
|
|
|
// 设置任务的父任务 ID(当前任务所在的任务列表的 ID)
|
|
|
js.put(GTaskStringUtils.GTASK_JSON_PARENT_ID, mParent.getGid());
|
|
|
|
|
|
// 设置目标父级类型,这里固定为 "group" 类型
|
|
|
js.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT_TYPE,
|
|
|
GTaskStringUtils.GTASK_JSON_TYPE_GROUP);
|
|
|
|
|
|
// 设置任务列表的 ID(父任务列表的 ID)
|
|
|
js.put(GTaskStringUtils.GTASK_JSON_LIST_ID, mParent.getGid());
|
|
|
|
|
|
// 如果当前任务有前一个兄弟任务,则设置 prior_sibling_id
|
|
|
if (mPriorSibling != null) {
|
|
|
js.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, mPriorSibling.getGid());
|
|
|
}
|
|
|
|
|
|
} catch (JSONException e) {
|
|
|
// 如果生成 JSON 时发生错误,记录错误日志,并抛出自定义异常
|
|
|
Log.e(TAG, e.toString());
|
|
|
e.printStackTrace();
|
|
|
throw new ActionFailureException("fail to generate task-create jsonobject");
|
|
|
}
|
|
|
|
|
|
// 返回生成的 JSON 对象
|
|
|
return js;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
方法功能:
|
|
|
getUpdateAction(int actionId) 生成一个 JSON 对象,表示任务的更新动作。这个 JSON 对象包含任务的 ID、名称、备注、删除标记等信息,用于更新任务时进行传输或存储。
|
|
|
参数:
|
|
|
actionId,表示当前任务更新动作的唯一 ID。
|
|
|
返回值:
|
|
|
返回一个 JSONObject,包含任务更新的相关信息。
|
|
|
|
|
|
|
|
|
js.put():
|
|
|
这段代码使用 js.put() 方法将任务更新的相关数据填充到 JSON 对象中。
|
|
|
put() 方法是 JSONObject 类提供的一个 API,用于向 JSON 对象中添加键值对。
|
|
|
更新操作的标识:
|
|
|
GTaskStringUtils.GTASK_JSON_ACTION_TYPE 设置为 GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE,表示这是一个更新操作。
|
|
|
action_id:
|
|
|
使用 actionId 参数设置更新操作的唯一 ID。
|
|
|
任务 ID:
|
|
|
GTaskStringUtils.GTASK_JSON_ID 设置为 getGid(),表示当前任务的唯一 ID。getGid() 方法通常会返回任务的全局唯一标识符(ID)。
|
|
|
任务实体更新:
|
|
|
创建一个名为 entity 的 JSON 对象,用于包含实际更新的任务信息:
|
|
|
任务名称:
|
|
|
GTaskStringUtils.GTASK_JSON_NAME 使用 getName() 方法获取任务的名称。
|
|
|
备注信息:
|
|
|
如果任务有备注(getNotes() != null),则将备注信息添加到 JSON 中。
|
|
|
删除标记:
|
|
|
GTaskStringUtils.GTASK_JSON_DELETED 使用 getDeleted() 方法来获取任务的删除标记(表示该任务是否已被标记为删除)。
|
|
|
错误处理:
|
|
|
如果在生成 JSON 对象的过程中发生 JSONException 异常,会记录错误信息并抛出自定义异常 ActionFailureException。
|
|
|
ActionFailureException 是一个自定义异常类,表示任务更新过程中的失败。异常信息为 "fail to generate task-update jsonobject",有助于开发者识别错误。
|
|
|
返回值:
|
|
|
方法最终返回一个包含任务更新信息的 JSONObject。这个 JSON 对象可以用于后续的任务更新操作,如提交到服务器或保存到数据库。
|
|
|
|
|
|
*/
|
|
|
public JSONObject getUpdateAction(int actionId) {
|
|
|
// 创建一个新的 JSON 对象,表示任务更新动作
|
|
|
JSONObject js = new JSONObject();
|
|
|
|
|
|
try {
|
|
|
// 设置 action_type 字段,表示这是一个更新操作
|
|
|
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
|
|
|
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE);
|
|
|
|
|
|
// 设置 action_id 字段,表示当前更新操作的唯一标识符
|
|
|
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
|
|
|
|
|
|
// 设置任务的 ID,使用 `getGid()` 方法获取当前任务的唯一 ID
|
|
|
js.put(GTaskStringUtils.GTASK_JSON_ID, getGid());
|
|
|
|
|
|
// 创建一个 entity 对象,表示任务更新的实际内容(包括任务的名称、备注和删除标记)
|
|
|
JSONObject entity = new JSONObject();
|
|
|
|
|
|
// 设置任务的名称
|
|
|
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
|
|
|
|
|
|
// 如果任务有备注信息,则添加备注字段
|
|
|
if (getNotes() != null) {
|
|
|
entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes());
|
|
|
}
|
|
|
|
|
|
// 设置任务的删除标记,使用 `getDeleted()` 方法获取任务是否已删除
|
|
|
entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted());
|
|
|
|
|
|
// 将 entity 对象放入 JSON 中,作为任务更新的实际内容
|
|
|
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
|
|
|
|
|
|
} catch (JSONException e) {
|
|
|
// 捕获 JSON 构建过程中的异常
|
|
|
// 打印错误日志
|
|
|
Log.e(TAG, e.toString());
|
|
|
// 输出堆栈信息
|
|
|
e.printStackTrace();
|
|
|
// 如果发生异常,抛出自定义的更新失败异常
|
|
|
throw new ActionFailureException("fail to generate task-update jsonobject");
|
|
|
}
|
|
|
|
|
|
// 返回生成的任务更新 JSON 对象
|
|
|
return js;
|
|
|
}
|
|
|
|
|
|
|
|
|
/*
|
|
|
这段代码展示了一个 `setContentByRemoteJSON(JSONObject js)` 方法,它用于根据从远程服务器或外部系统接收到的 JSON 数据更新任务的属性
|
|
|
- **方法功能**:`setContentByRemoteJSON(JSONObject js)` 根据传入的 JSON 对象,更新当前任务的各个属性。该方法会检查 JSON 中是否包含某些字段,并根据字段的存在情况,调用相应的 setter 方法更新任务的属性值。
|
|
|
- **参数**:`js`,一个 `JSONObject`,包含任务更新的信息。
|
|
|
- **返回值**:无返回值。该方法直接更新任务对象的属性。
|
|
|
|
|
|
1. **检查 JSON 对象是否为空**:
|
|
|
- 该方法首先检查传入的 `js` 对象是否为 `null`。如果是 `null`,说明没有数据需要处理,方法会直接退出。
|
|
|
|
|
|
2. **处理各个属性字段**:
|
|
|
- 代码通过 `js.has()` 方法检查 JSON 对象中是否包含特定字段。如果字段存在,就从 JSON 中提取相应的值,并通过 setter 方法更新任务对象的属性。
|
|
|
- 对应的字段名称通过 `GTaskStringUtils` 类中的常量定义,如 `GTASK_JSON_ID`、`GTASK_JSON_LAST_MODIFIED`、`GTASK_JSON_NAME` 等。这些常量在其他地方应该有定义,用于确保字段名称的一致性,避免硬编码的字符串。
|
|
|
|
|
|
3. **具体字段的处理**:
|
|
|
- **任务 ID**:使用 `getString()` 获取任务 ID,并通过 `setGid()` 方法更新任务的全局 ID。
|
|
|
- **最后修改时间**:使用 `getLong()` 获取任务的最后修改时间,并通过 `setLastModified()` 方法更新。
|
|
|
- **任务名称**:使用 `getString()` 获取任务名称,并通过 `setName()` 方法更新。
|
|
|
- **备注信息**:使用 `getString()` 获取任务的备注,如果备注字段存在,就更新备注信息。
|
|
|
- **删除标记**:使用 `getBoolean()` 获取任务的删除标记(布尔值),并通过 `setDeleted()` 更新。
|
|
|
- **完成标记**:使用 `getBoolean()` 获取任务的完成标记(布尔值),并通过 `setCompleted()` 更新。
|
|
|
|
|
|
4. **异常处理**:
|
|
|
- 如果在从 JSON 中提取数据的过程中发生 `JSONException` 异常,会打印错误信息并抛出自定义异常 `ActionFailureException`,该异常指示任务内容从 JSON 对象中获取失败。
|
|
|
- 异常消息中说明了错误是由于无法从 JSON 对象获取任务内容("fail to get task content from jsonobject")。
|
|
|
|
|
|
5. **setter 方法**:
|
|
|
- `setGid()`, `setLastModified()`, `setName()`, `setNotes()`, `setDeleted()`, 和 `setCompleted()` 等方法是用于设置任务属性的自定义方法。
|
|
|
这些方法应该在任务对象的类中定义,用来更新任务对象的相应字段。
|
|
|
- 该方法通过从传入的 JSON 对象中提取任务相关的信息(如任务 ID、最后修改时间、名称、备注、删除标记、完成标记等),并通过调用相应的 setter 方法来更新任务对象的属性。
|
|
|
- 在实现时,使用了 `js.has()` 来判断是否包含某个字段,避免了因字段缺失而导致的异常。
|
|
|
- 错误处理机制较为健全,当解析 JSON 过程中发生异常时,会记录日志并抛出自定义异常,以便调用者进行处理。
|
|
|
|
|
|
*/
|
|
|
|
|
|
public void setContentByRemoteJSON(JSONObject js) {
|
|
|
// 如果传入的 JSON 对象不为 null
|
|
|
if (js != null) {
|
|
|
try {
|
|
|
// 处理任务 ID,获取并设置任务的全局 ID
|
|
|
if (js.has(GTaskStringUtils.GTASK_JSON_ID)) {
|
|
|
setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID));
|
|
|
}
|
|
|
|
|
|
// 处理任务的最后修改时间,获取并设置
|
|
|
if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) {
|
|
|
setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED));
|
|
|
}
|
|
|
|
|
|
// 处理任务名称,获取并设置
|
|
|
if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) {
|
|
|
setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME));
|
|
|
}
|
|
|
|
|
|
// 处理任务备注,获取并设置
|
|
|
if (js.has(GTaskStringUtils.GTASK_JSON_NOTES)) {
|
|
|
setNotes(js.getString(GTaskStringUtils.GTASK_JSON_NOTES));
|
|
|
}
|
|
|
|
|
|
// 处理删除标记,获取并设置
|
|
|
if (js.has(GTaskStringUtils.GTASK_JSON_DELETED)) {
|
|
|
setDeleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_DELETED));
|
|
|
}
|
|
|
|
|
|
// 处理完成标记,获取并设置
|
|
|
if (js.has(GTaskStringUtils.GTASK_JSON_COMPLETED)) {
|
|
|
setCompleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_COMPLETED));
|
|
|
}
|
|
|
} catch (JSONException e) {
|
|
|
// 如果解析 JSON 过程中发生异常,打印错误信息并抛出自定义异常
|
|
|
Log.e(TAG, e.toString());
|
|
|
e.printStackTrace();
|
|
|
throw new ActionFailureException("fail to get task content from jsonobject");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
功能:
|
|
|
从本地的 JSON 数据中提取相关内容,更新任务的名称。如果 JSON 格式正确且符合预期,它会提取相关字段并更新任务的 name 属性。否则,方法会打印警告信息或错误信息。
|
|
|
参数:
|
|
|
js,一个包含任务信息的 JSONObject,格式应包括 META_HEAD_NOTE 和 META_HEAD_DATA 这两个字段。
|
|
|
返回值:
|
|
|
无返回值,直接修改任务对象的属性。
|
|
|
|
|
|
*/
|
|
|
public void setContentByLocalJSON(JSONObject js) {
|
|
|
// 检查传入的 JSON 是否为 null,且是否包含所需的两个字段
|
|
|
/*
|
|
|
这段代码首先检查传入的 js 对象是否为 null,以及它是否包含两个特定字段:META_HEAD_NOTE 和 META_HEAD_DATA。
|
|
|
这两个字段是该方法解析任务内容所依赖的。如果这两个字段不存在,或者 js 为 null,则会打印警告日志并返回,避免进一步的处理。
|
|
|
*/
|
|
|
if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)
|
|
|
|| !js.has(GTaskStringUtils.META_HEAD_DATA)) {
|
|
|
// 如果条件不满足,打印警告信息并返回
|
|
|
Log.w(TAG, "setContentByLocalJSON: nothing is avaiable");
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
|
|
|
/*如果 JSON 对象有效并且包含所需字段,
|
|
|
接下来会从 JSON 对象中提取出 META_HEAD_NOTE 部分(作为 note 对象)和 META_HEAD_DATA 部分(作为 dataArray 数组)
|
|
|
*/
|
|
|
|
|
|
// 从 JSON 中提取出 META_HEAD_NOTE 对应的 JSONObject
|
|
|
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
|
|
|
// 从 JSON 中提取出 META_HEAD_DATA 对应的 JSONArray
|
|
|
JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
|
|
|
|
|
|
// 检查 note 对象中的 TYPE 是否为 NOTE 类型
|
|
|
//通过 note.getInt(NoteColumns.TYPE) 获取 note 对象中的 TYPE 字段,并与 Notes.TYPE_NOTE 常量进行比较。
|
|
|
// 如果 TYPE 不等于 Notes.TYPE_NOTE(假设 Notes.TYPE_NOTE 是预定义的常量,表示有效的 note 类型),
|
|
|
// 则认为该数据无效,打印错误日志并退出方法。
|
|
|
if (note.getInt(NoteColumns.TYPE) != Notes.TYPE_NOTE) {
|
|
|
// 如果 TYPE 不等于 NOTE 类型,打印错误信息并返回
|
|
|
Log.e(TAG, "invalid type");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 遍历 dataArray 数组中的每个 JSONObject
|
|
|
/*方法通过 dataArray.length() 获取数组的长度,使用 for 循环遍历数组中的每一个 data 对象。
|
|
|
在每次迭代中,通过 data.getString(DataColumns.MIME_TYPE) 获取 MIME_TYPE 字段,
|
|
|
并与 DataConstants.NOTE 常量进行比较。如果 MIME_TYPE 的值是 NOTE,则获取该 data 对象的 CONTENT 字段值,
|
|
|
并调用 setName() 方法更新任务的名称。
|
|
|
一旦找到符合条件的 data 对象,便立即跳出循环(使用 break 语句)
|
|
|
*/
|
|
|
for (int i = 0; i < dataArray.length(); i++) {
|
|
|
// 获取当前遍历的 data 对象
|
|
|
JSONObject data = dataArray.getJSONObject(i);
|
|
|
// 判断 data 中的 MIME_TYPE 是否为 NOTE 类型
|
|
|
if (TextUtils.equals(data.getString(DataColumns.MIME_TYPE), DataConstants.NOTE)) {
|
|
|
// 如果 MIME_TYPE 为 NOTE 类型,从 data 中获取 CONTENT 字段的值,并设置为任务的名称
|
|
|
setName(data.getString(DataColumns.CONTENT));
|
|
|
// 找到第一个符合条件的记录后跳出循环
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
//如果在解析 JSON 数据时发生异常(例如字段缺失或类型不匹配),会捕获 JSONException 并打印错误信息,确保应用不会崩溃。
|
|
|
catch (JSONException e) {
|
|
|
// 如果在解析过程中发生异常,打印错误信息
|
|
|
Log.e(TAG, e.toString());
|
|
|
// 打印堆栈跟踪信息
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
该方法 getLocalJSONFromContent() 的主要功能是根据当前任务的状态生成或更新本地的 JSON 对象(JSONObject),
|
|
|
该对象表示任务的元数据。它会根据任务是否已经同步(即是否有 mMetaInfo)来决定是创建一个新的 JSON 对象,还是更新已有的同步任务的数据。
|
|
|
|
|
|
*/
|
|
|
public JSONObject getLocalJSONFromContent() {
|
|
|
// 获取当前任务的名称
|
|
|
String name = getName();
|
|
|
try {
|
|
|
// 如果 mMetaInfo 为 null,表示任务还未同步,或者是一个新任务
|
|
|
if (mMetaInfo == null) {
|
|
|
// new task created from web
|
|
|
|
|
|
// 如果任务的名称为空,输出警告并返回 null
|
|
|
if (name == null) {
|
|
|
Log.w(TAG, "the note seems to be an empty one");
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
// 创建一个新的 JSON 对象来表示任务的元数据
|
|
|
JSONObject js = new JSONObject();
|
|
|
JSONObject note = new JSONObject();
|
|
|
JSONArray dataArray = new JSONArray();
|
|
|
JSONObject data = new JSONObject();
|
|
|
|
|
|
// 将任务的名称添加到 data 对象中
|
|
|
data.put(DataColumns.CONTENT, name);
|
|
|
// 将 data 对象添加到 dataArray 中
|
|
|
dataArray.put(data);
|
|
|
|
|
|
// 将 dataArray 添加到 js 对象中的 META_HEAD_DATA 字段
|
|
|
js.put(GTaskStringUtils.META_HEAD_DATA, dataArray);
|
|
|
|
|
|
// 设置 note 对象的 TYPE 字段为 NOTE 类型
|
|
|
note.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
|
|
|
// 将 note 对象添加到 js 对象中的 META_HEAD_NOTE 字段
|
|
|
js.put(GTaskStringUtils.META_HEAD_NOTE, note);
|
|
|
|
|
|
return js; // 返回生成的 JSON 对象
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 如果 mMetaInfo 已经存在,表示这是一个已经同步的任务
|
|
|
// 从 mMetaInfo 中获取 META_HEAD_NOTE 和 META_HEAD_DATA
|
|
|
JSONObject note = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
|
|
|
JSONArray dataArray = mMetaInfo.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
|
|
|
|
|
|
// 遍历 dataArray 中的每个 data 对象,更新 MIME_TYPE 为 NOTE 的对象中的 CONTENT 字段
|
|
|
for (int i = 0; i < dataArray.length(); i++) {
|
|
|
JSONObject data = dataArray.getJSONObject(i);
|
|
|
if (TextUtils.equals(data.getString(DataColumns.MIME_TYPE), DataConstants.NOTE)) {
|
|
|
// 更新 data 对象中的 CONTENT 字段为当前任务的名称
|
|
|
data.put(DataColumns.CONTENT, getName());
|
|
|
break; // 找到并更新后跳出循环
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 确保 note 对象中的 TYPE 字段仍然为 NOTE 类型
|
|
|
note.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
|
|
|
// 返回已经更新的 mMetaInfo 对象
|
|
|
return mMetaInfo;
|
|
|
}
|
|
|
}
|
|
|
// 捕获并处理 JSON 解析过程中的异常
|
|
|
catch (JSONException e) {
|
|
|
Log.e(TAG, e.toString());
|
|
|
e.printStackTrace();
|
|
|
// 如果发生异常,返回 null
|
|
|
return null;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
setMetaInfo(MetaData metaData):
|
|
|
该方法接受一个 MetaData 对象作为参数,目的是将 metaData 中的 notes 信息转换为 JSONObject,并赋值给 mMetaInfo。
|
|
|
如果传入的 metaData 和 metaData.getNotes() 不为 null,会尝试将 getNotes() 返回的字符串解析为 JSONObject,并赋值给 mMetaInfo。
|
|
|
如果解析过程中发生错误(如 JSON 格式不合法),会捕获 JSONException,输出警告信息,并将 mMetaInfo 置为 null。
|
|
|
*/
|
|
|
public void setMetaInfo(MetaData metaData) {
|
|
|
if (metaData != null && metaData.getNotes() != null) {
|
|
|
try {
|
|
|
// 将 notes 字符串转换为 JSONObject
|
|
|
mMetaInfo = new JSONObject(metaData.getNotes());
|
|
|
}
|
|
|
|
|
|
catch (JSONException e) { // 如果 JSON 转换失败
|
|
|
// 输出警告日志
|
|
|
Log.w(TAG, e.toString());
|
|
|
// 设置 mMetaInfo 为 null
|
|
|
mMetaInfo = null;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/*
|
|
|
getSyncAction(Cursor c):
|
|
|
该方法根据当前任务的同步状态,决定接下来的同步操作(如更新远程或本地数据等)。
|
|
|
逻辑说明:
|
|
|
该方法首先检查 mMetaInfo 是否包含有效的 note 元数据。
|
|
|
然后,它根据当前数据库记录(通过 Cursor 提供的数据)与 mMetaInfo 中的 note 数据进行比较,确定要执行的同步操作:
|
|
|
SYNC_ACTION_UPDATE_REMOTE:从远程更新数据。
|
|
|
SYNC_ACTION_UPDATE_LOCAL:将远程数据应用到本地。
|
|
|
SYNC_ACTION_NONE:本地和远程都没有更新,不需要同步。
|
|
|
SYNC_ACTION_UPDATE_CONFLICT:本地和远程都进行了修改,发生冲突。
|
|
|
SYNC_ACTION_ERROR:出现错误或无法同步。
|
|
|
*/
|
|
|
|
|
|
public int getSyncAction(Cursor c) {
|
|
|
try {
|
|
|
JSONObject noteInfo = null;
|
|
|
if (mMetaInfo != null && mMetaInfo.has(GTaskStringUtils.META_HEAD_NOTE)) {
|
|
|
// 获取 note 元数据
|
|
|
noteInfo = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
|
|
|
}
|
|
|
|
|
|
// 如果没有获取到 note 信息
|
|
|
if (noteInfo == null) {
|
|
|
Log.w(TAG, "it seems that note meta has been deleted");
|
|
|
// 需要从远程更新
|
|
|
return SYNC_ACTION_UPDATE_REMOTE;
|
|
|
}
|
|
|
|
|
|
// 如果 note 缺少 ID 字段
|
|
|
if (!noteInfo.has(NoteColumns.ID)) {
|
|
|
Log.w(TAG, "remote note id seems to be deleted");
|
|
|
// 需要从本地更新
|
|
|
return SYNC_ACTION_UPDATE_LOCAL;
|
|
|
}
|
|
|
|
|
|
// 校验 note ID 是否匹配
|
|
|
if (c.getLong(SqlNote.ID_COLUMN) != noteInfo.getLong(NoteColumns.ID)) {
|
|
|
Log.w(TAG, "note id doesn't match");
|
|
|
// 如果不匹配,从本地更新
|
|
|
return SYNC_ACTION_UPDATE_LOCAL;
|
|
|
}
|
|
|
|
|
|
// 如果本地未修改
|
|
|
if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) {
|
|
|
// 本地和远程都没有变化
|
|
|
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
|
|
|
// 无需操作
|
|
|
return SYNC_ACTION_NONE;
|
|
|
} else { // 远程有更新
|
|
|
// 从远程更新
|
|
|
return SYNC_ACTION_UPDATE_LOCAL;
|
|
|
}
|
|
|
} else { // 本地已修改
|
|
|
// 校验 gtask ID
|
|
|
if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) {
|
|
|
Log.e(TAG, "gtask id doesn't match");
|
|
|
// gtask ID 不匹配,返回错误
|
|
|
return SYNC_ACTION_ERROR;
|
|
|
}
|
|
|
// 本地修改且没有远程修改
|
|
|
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
|
|
|
// 将本地修改同步到远程
|
|
|
return SYNC_ACTION_UPDATE_REMOTE;
|
|
|
} else {
|
|
|
// 本地和远程都有修改,发生冲突
|
|
|
return SYNC_ACTION_UPDATE_CONFLICT;
|
|
|
}
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
// 异常处理
|
|
|
Log.e(TAG, e.toString());
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
|
|
|
// 出现异常或无法处理时返回错误
|
|
|
return SYNC_ACTION_ERROR;
|
|
|
}
|
|
|
|
|
|
|
|
|
/*
|
|
|
setCompleted(boolean completed)
|
|
|
作用:设置任务的完成状态。
|
|
|
参数:completed 是一个布尔值,表示任务是否已完成。
|
|
|
*/
|
|
|
public void setCompleted(boolean completed) {
|
|
|
//将传入的 completed 参数赋值给任务对象的 mCompleted 属性,用于标识任务是否完成
|
|
|
this.mCompleted = completed;
|
|
|
}
|
|
|
|
|
|
|
|
|
/*
|
|
|
setNotes(String notes)
|
|
|
作用:设置任务的备注信息。
|
|
|
参数:notes 是一个字符串,表示任务的备注或附加说明。
|
|
|
*/
|
|
|
public void setNotes(String notes) {
|
|
|
//将传入的 notes 参数赋值给任务对象的 mNotes 属性,用于存储任务的备注内容。
|
|
|
this.mNotes = notes;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
setPriorSibling(Task priorSibling)
|
|
|
作用:设置任务的前一个兄弟任务。
|
|
|
参数:priorSibling 是一个 Task 对象,表示当前任务的前一个兄弟任务。
|
|
|
*/
|
|
|
public void setPriorSibling(Task priorSibling) {
|
|
|
//将传入的 priorSibling 参数赋值给任务对象的 mPriorSibling 属性,表示当前任务在任务列表中的前一个任务。
|
|
|
this.mPriorSibling = priorSibling;
|
|
|
}
|
|
|
|
|
|
|
|
|
/*
|
|
|
setParent(TaskList parent)
|
|
|
作用:设置任务的父任务列表。
|
|
|
参数:parent 是一个 TaskList 对象,表示任务所属的任务列表。
|
|
|
*/
|
|
|
public void setParent(TaskList parent) {
|
|
|
//将传入的 parent 参数赋值给任务对象的 mParent 属性,表示当前任务所属的父任务列表。
|
|
|
this.mParent = parent;
|
|
|
}
|
|
|
|
|
|
|
|
|
/*
|
|
|
getCompleted()
|
|
|
作用:获取任务的完成状态。
|
|
|
返回值:返回一个布尔值,表示任务是否已完成。
|
|
|
*/
|
|
|
public boolean getCompleted() {
|
|
|
//返回 mCompleted 属性的值,表示任务是否已完成。
|
|
|
return this.mCompleted;
|
|
|
}
|
|
|
|
|
|
|
|
|
/*
|
|
|
getNotes()
|
|
|
|
|
|
作用:获取任务的备注信息。
|
|
|
返回值:返回任务的备注字符串。
|
|
|
*/
|
|
|
|
|
|
public String getNotes() {
|
|
|
//返回 mNotes 属性的值,表示任务的备注或附加说明。
|
|
|
return this.mNotes;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
getPriorSibling()
|
|
|
作用:获取任务的前一个兄弟任务。
|
|
|
返回值:返回一个 Task 对象,表示当前任务的前一个兄弟任务。
|
|
|
*/
|
|
|
|
|
|
public Task getPriorSibling() {
|
|
|
//返回 mPriorSibling 属性的值,表示当前任务在任务列表中的前一个任务。
|
|
|
return this.mPriorSibling;
|
|
|
}
|
|
|
|
|
|
|
|
|
/*
|
|
|
getParent()
|
|
|
作用:获取任务所属的父任务列表。
|
|
|
返回值:返回一个 TaskList 对象,表示任务所属的父任务列表。
|
|
|
*/
|
|
|
|
|
|
public TaskList getParent() {
|
|
|
// 返回 mParent 属性的值,表示当前任务所属的父任务列表。
|
|
|
return this.mParent;
|
|
|
}
|
|
|
|
|
|
|
|
|
}
|