From 8e45bd3aceaf600c107ff90526068d0b527083ae Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 13 Jun 2024 08:30:31 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0gtask=E9=83=A8=E5=88=86?= =?UTF-8?q?=E7=9A=84=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../net/micode/notes/gtask/data/MetaData.java | 47 +++- .../net/micode/notes/gtask/data/Node.java | 80 +++++- .../net/micode/notes/gtask/data/SqlData.java | 61 ++++- .../net/micode/notes/gtask/data/SqlNote.java | 117 ++++++--- .../net/micode/notes/gtask/data/Task.java | 134 +++++++--- .../net/micode/notes/gtask/data/TaskList.java | 139 +++++++++-- .../exception/ActionFailureException.java | 16 ++ .../exception/NetworkFailureException.java | 16 ++ .../notes/gtask/remote/GTaskASyncTask.java | 47 +++- .../notes/gtask/remote/GTaskClient.java | 151 ++++++++++-- .../notes/gtask/remote/GTaskManager.java | 229 ++++++++++-------- .../notes/gtask/remote/GTaskSyncService.java | 32 +++ 12 files changed, 842 insertions(+), 227 deletions(-) diff --git a/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/MetaData.java b/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/MetaData.java index 3a2050b..919a5d4 100644 --- a/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/MetaData.java +++ b/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/MetaData.java @@ -24,59 +24,100 @@ import net.micode.notes.tool.GTaskStringUtils; import org.json.JSONException; import org.json.JSONObject; - +/** + * MetaData类继承自Task类,用于管理任务的元数据。 + * 该类提供了设置和获取与任务相关的GID的方法,以及处理远程JSON内容的方法。 + */ public class MetaData extends Task { + // 日志标签,用于调试输出 private final static String TAG = MetaData.class.getSimpleName(); + // 相关的GID private String mRelatedGid = null; + /** + * 设置元数据 + * @param gid 任务的GID + * @param metaInfo 元数据的JSON对象 + */ public void setMeta(String gid, JSONObject metaInfo) { try { + // 将GID添加到元数据JSON对象中 metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid); } catch (JSONException e) { + // 输出错误日志 Log.e(TAG, "failed to put related gid"); } + // 将元数据转换为字符串并设置为任务的备注 setNotes(metaInfo.toString()); + // 设置任务名称 setName(GTaskStringUtils.META_NOTE_NAME); } + /** + * 获取相关的GID + * @return 相关的GID + */ public String getRelatedGid() { return mRelatedGid; } + /** + * 判断任务是否值得保存 + * @return 如果任务的备注不为空,则返回true;否则返回false + */ @Override public boolean isWorthSaving() { return getNotes() != null; } + /** + * 通过远程JSON内容设置任务内容 + * @param js 远程JSON对象 + */ @Override public void setContentByRemoteJSON(JSONObject js) { super.setContentByRemoteJSON(js); if (getNotes() != null) { try { + // 解析备注中的元数据JSON对象 JSONObject metaInfo = new JSONObject(getNotes().trim()); + // 获取元数据中的GID mRelatedGid = metaInfo.getString(GTaskStringUtils.META_HEAD_GTASK_ID); } catch (JSONException e) { + // 输出警告日志 Log.w(TAG, "failed to get related gid"); mRelatedGid = null; } } } + /** + * 禁止通过本地JSON内容设置任务内容 + * @param js 本地JSON对象 + */ @Override public void setContentByLocalJSON(JSONObject js) { - // this function should not be called + // 此方法不应被调用 throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called"); } + /** + * 禁止从任务内容中获取本地JSON对象 + * @return 本地JSON对象 + */ @Override public JSONObject getLocalJSONFromContent() { throw new IllegalAccessError("MetaData:getLocalJSONFromContent should not be called"); } + /** + * 禁止获取同步动作 + * @param c 游标对象 + * @return 同步动作 + */ @Override public int getSyncAction(Cursor c) { throw new IllegalAccessError("MetaData:getSyncAction should not be called"); } - } diff --git a/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/Node.java b/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/Node.java index 63950e0..fdee51f 100644 --- a/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/Node.java +++ b/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/Node.java @@ -20,33 +20,38 @@ import android.database.Cursor; import org.json.JSONObject; +/** + * Node类是一个抽象类,用于表示任务节点。 + * 该类定义了任务节点的基本属性和操作,包括同步动作的常量、任务节点的GID、名称、最后修改时间、删除状态等。 + * 具体的任务节点需要继承该类并实现抽象方法。 + */ public abstract class Node { + // 同步动作的常量 public static final int SYNC_ACTION_NONE = 0; - public static final int SYNC_ACTION_ADD_REMOTE = 1; - public static final int SYNC_ACTION_ADD_LOCAL = 2; - public static final int SYNC_ACTION_DEL_REMOTE = 3; - public static final int SYNC_ACTION_DEL_LOCAL = 4; - public static final int SYNC_ACTION_UPDATE_REMOTE = 5; - public static final int SYNC_ACTION_UPDATE_LOCAL = 6; - public static final int SYNC_ACTION_UPDATE_CONFLICT = 7; - public static final int SYNC_ACTION_ERROR = 8; + // 任务节点的GID private String mGid; + // 任务节点的名称 private String mName; + // 任务节点的最后修改时间 private long mLastModified; + // 任务节点的删除状态 private boolean mDeleted; + /** + * Node类的构造函数,初始化任务节点的属性 + */ public Node() { mGid = null; mName = ""; @@ -54,46 +59,105 @@ public abstract class Node { mDeleted = false; } + /** + * 获取创建操作的JSON对象 + * @param actionId 操作ID + * @return 创建操作的JSON对象 + */ public abstract JSONObject getCreateAction(int actionId); + /** + * 获取更新操作的JSON对象 + * @param actionId 操作ID + * @return 更新操作的JSON对象 + */ public abstract JSONObject getUpdateAction(int actionId); + /** + * 通过远程JSON对象设置任务节点的内容 + * @param js 远程JSON对象 + */ public abstract void setContentByRemoteJSON(JSONObject js); + /** + * 通过本地JSON对象设置任务节点的内容 + * @param js 本地JSON对象 + */ public abstract void setContentByLocalJSON(JSONObject js); + /** + * 从任务节点的内容中获取本地JSON对象 + * @return 本地JSON对象 + */ public abstract JSONObject getLocalJSONFromContent(); + /** + * 获取同步动作 + * @param c 游标对象 + * @return 同步动作 + */ public abstract int getSyncAction(Cursor c); + /** + * 设置任务节点的GID + * @param gid 任务节点的GID + */ public void setGid(String gid) { this.mGid = gid; } + /** + * 设置任务节点的名称 + * @param name 任务节点的名称 + */ public void setName(String name) { this.mName = name; } + /** + * 设置任务节点的最后修改时间 + * @param lastModified 任务节点的最后修改时间 + */ public void setLastModified(long lastModified) { this.mLastModified = lastModified; } + /** + * 设置任务节点的删除状态 + * @param deleted 任务节点的删除状态 + */ public void setDeleted(boolean deleted) { this.mDeleted = deleted; } + /** + * 获取任务节点的GID + * @return 任务节点的GID + */ public String getGid() { return this.mGid; } + /** + * 获取任务节点的名称 + * @return 任务节点的名称 + */ public String getName() { return this.mName; } + /** + * 获取任务节点的最后修改时间 + * @return 任务节点的最后修改时间 + */ public long getLastModified() { return this.mLastModified; } + /** + * 获取任务节点的删除状态 + * @return 任务节点的删除状态 + */ public boolean getDeleted() { return this.mDeleted; } diff --git a/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/SqlData.java b/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/SqlData.java index 2bf0273..85e4d5b 100644 --- a/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/SqlData.java +++ b/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/SqlData.java @@ -34,43 +34,50 @@ import net.micode.notes.gtask.exception.ActionFailureException; import org.json.JSONException; import org.json.JSONObject; - +/** + * SqlData类用于处理数据库中的笔记数据。 + * 该类提供了从数据库加载数据、设置数据内容、获取数据内容以及提交数据的功能。 + */ public class SqlData { + // 日志标签,用于调试输出 private static final String TAG = SqlData.class.getSimpleName(); + // 无效的ID常量 private static final int INVALID_ID = -99999; + // 数据表的字段投影 public static final String[] PROJECTION_DATA = new String[] { DataColumns.ID, DataColumns.MIME_TYPE, DataColumns.CONTENT, DataColumns.DATA1, DataColumns.DATA3 }; + // 数据表字段的列索引 public static final int DATA_ID_COLUMN = 0; - public static final int DATA_MIME_TYPE_COLUMN = 1; - public static final int DATA_CONTENT_COLUMN = 2; - public static final int DATA_CONTENT_DATA_1_COLUMN = 3; - public static final int DATA_CONTENT_DATA_3_COLUMN = 4; + // 内容解析器,用于访问内容提供者的数据 private ContentResolver mContentResolver; + // 标识数据是否为新创建的 private boolean mIsCreate; + // 数据的各个字段 private long mDataId; - private String mDataMimeType; - private String mDataContent; - private long mDataContentData1; - private String mDataContentData3; + // 存储数据变更的内容值 private ContentValues mDiffDataValues; + /** + * SqlData类的构造函数,用于新创建的数据 + * @param context 应用上下文 + */ public SqlData(Context context) { mContentResolver = context.getContentResolver(); mIsCreate = true; @@ -82,6 +89,11 @@ public class SqlData { mDiffDataValues = new ContentValues(); } + /** + * SqlData类的构造函数,用于从数据库加载的数据 + * @param context 应用上下文 + * @param c 游标对象,指向加载的数据 + */ public SqlData(Context context, Cursor c) { mContentResolver = context.getContentResolver(); mIsCreate = false; @@ -89,6 +101,10 @@ public class SqlData { mDiffDataValues = new ContentValues(); } + /** + * 从游标加载数据 + * @param c 游标对象,指向加载的数据 + */ private void loadFromCursor(Cursor c) { mDataId = c.getLong(DATA_ID_COLUMN); mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN); @@ -97,6 +113,11 @@ public class SqlData { mDataContentData3 = c.getString(DATA_CONTENT_DATA_3_COLUMN); } + /** + * 设置数据内容 + * @param js JSON对象,包含数据内容 + * @throws JSONException 如果JSON解析错误 + */ public void setContent(JSONObject js) throws JSONException { long dataId = js.has(DataColumns.ID) ? js.getLong(DataColumns.ID) : INVALID_ID; if (mIsCreate || mDataId != dataId) { @@ -130,6 +151,11 @@ public class SqlData { mDataContentData3 = dataContentData3; } + /** + * 获取数据内容 + * @return JSON对象,包含数据内容 + * @throws JSONException 如果JSON解析错误 + */ public JSONObject getContent() throws JSONException { if (mIsCreate) { Log.e(TAG, "it seems that we haven't created this in database yet"); @@ -144,16 +170,26 @@ public class SqlData { return js; } + /** + * 提交数据到数据库 + * @param noteId 笔记ID + * @param validateVersion 是否验证版本 + * @param version 版本号 + */ public void commit(long noteId, boolean validateVersion, long version) { if (mIsCreate) { + // 如果是新创建的数据且ID无效,则移除ID字段 if (mDataId == INVALID_ID && mDiffDataValues.containsKey(DataColumns.ID)) { mDiffDataValues.remove(DataColumns.ID); } + // 将笔记ID添加到内容值中 mDiffDataValues.put(DataColumns.NOTE_ID, noteId); + // 插入新数据 Uri uri = mContentResolver.insert(Notes.CONTENT_DATA_URI, mDiffDataValues); try { + // 从插入结果的URI中获取数据ID mDataId = Long.valueOf(uri.getPathSegments().get(1)); } catch (NumberFormatException e) { Log.e(TAG, "Get note id error :" + e.toString()); @@ -163,9 +199,11 @@ public class SqlData { if (mDiffDataValues.size() > 0) { int result = 0; if (!validateVersion) { + // 更新数据 result = mContentResolver.update(ContentUris.withAppendedId( Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, null, null); } else { + // 更新数据并验证版本 result = mContentResolver.update(ContentUris.withAppendedId( Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, " ? in (SELECT " + NoteColumns.ID + " FROM " + TABLE.NOTE @@ -179,10 +217,15 @@ public class SqlData { } } + // 清空变更内容值并重置创建标识 mDiffDataValues.clear(); mIsCreate = false; } + /** + * 获取数据ID + * @return 数据ID + */ public long getId() { return mDataId; } diff --git a/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/SqlNote.java b/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/SqlNote.java index 5d46d01..6e6039f 100644 --- a/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/SqlNote.java +++ b/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/SqlNote.java @@ -37,12 +37,18 @@ import org.json.JSONObject; import java.util.ArrayList; - +/** + * SqlNote类用于处理数据库中的笔记数据。 + * 该类提供了从数据库加载笔记、设置笔记内容、获取笔记内容以及提交笔记的功能。 + */ public class SqlNote { + // 日志标签,用于调试输出 private static final String TAG = SqlNote.class.getSimpleName(); + // 无效的ID常量 private static final int INVALID_ID = -99999; + // 笔记表的字段投影 public static final String[] PROJECTION_NOTE = new String[] { NoteColumns.ID, NoteColumns.ALERTED_DATE, NoteColumns.BG_COLOR_ID, NoteColumns.CREATED_DATE, NoteColumns.HAS_ATTACHMENT, NoteColumns.MODIFIED_DATE, @@ -52,76 +58,59 @@ public class SqlNote { NoteColumns.VERSION }; + // 笔记表字段的列索引 public static final int ID_COLUMN = 0; - public static final int ALERTED_DATE_COLUMN = 1; - 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; - public static final int PARENT_ID_COLUMN = 7; - public static final int SNIPPET_COLUMN = 8; - public static final int TYPE_COLUMN = 9; - public static final int WIDGET_ID_COLUMN = 10; - public static final int WIDGET_TYPE_COLUMN = 11; - public static final int SYNC_ID_COLUMN = 12; - public static final int LOCAL_MODIFIED_COLUMN = 13; - public static final int ORIGIN_PARENT_ID_COLUMN = 14; - public static final int GTASK_ID_COLUMN = 15; - public static final int VERSION_COLUMN = 16; + // 应用上下文 private Context mContext; + // 内容解析器,用于访问内容提供者的数据 private ContentResolver mContentResolver; + // 标识笔记是否为新创建的 private boolean mIsCreate; + // 笔记的各个字段 private long mId; - private long mAlertDate; - private int mBgColorId; - private long mCreatedDate; - private int mHasAttachment; - private long mModifiedDate; - private long mParentId; - private String mSnippet; - private int mType; - private int mWidgetId; - private int mWidgetType; - private long mOriginParent; - private long mVersion; + // 存储笔记变更的内容值 private ContentValues mDiffNoteValues; + // 笔记的数据列表 private ArrayList mDataList; + /** + * SqlNote类的构造函数,用于新创建的笔记 + * @param context 应用上下文 + */ public SqlNote(Context context) { mContext = context; mContentResolver = context.getContentResolver(); @@ -143,6 +132,11 @@ public class SqlNote { mDataList = new ArrayList(); } + /** + * SqlNote类的构造函数,用于从数据库加载的笔记 + * @param context 应用上下文 + * @param c 游标对象,指向加载的笔记 + */ public SqlNote(Context context, Cursor c) { mContext = context; mContentResolver = context.getContentResolver(); @@ -154,6 +148,11 @@ public class SqlNote { mDiffNoteValues = new ContentValues(); } + /** + * SqlNote类的构造函数,通过笔记ID从数据库加载笔记 + * @param context 应用上下文 + * @param id 笔记ID + */ public SqlNote(Context context, long id) { mContext = context; mContentResolver = context.getContentResolver(); @@ -163,9 +162,12 @@ public class SqlNote { if (mType == Notes.TYPE_NOTE) loadDataContent(); mDiffNoteValues = new ContentValues(); - } + /** + * 通过笔记ID从数据库加载笔记 + * @param id 笔记ID + */ private void loadFromCursor(long id) { Cursor c = null; try { @@ -185,6 +187,10 @@ public class SqlNote { } } + /** + * 从游标加载笔记数据 + * @param c 游标对象,指向加载的笔记 + */ private void loadFromCursor(Cursor c) { mId = c.getLong(ID_COLUMN); mAlertDate = c.getLong(ALERTED_DATE_COLUMN); @@ -200,6 +206,9 @@ public class SqlNote { mVersion = c.getLong(VERSION_COLUMN); } + /** + * 从数据库加载笔记的数据内容 + */ private void loadDataContent() { Cursor c = null; mDataList.clear(); @@ -226,13 +235,18 @@ public class SqlNote { } } + /** + * 设置笔记内容 + * @param js JSON对象,包含笔记内容 + * @return 设置成功返回true,否则返回false + */ public boolean setContent(JSONObject js) { try { 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) { - // for folder we can only update the snnipet and type + // 对于文件夹,我们只能更新片段和类型 String snippet = note.has(NoteColumns.SNIPPET) ? note .getString(NoteColumns.SNIPPET) : ""; if (mIsCreate || !mSnippet.equals(snippet)) { @@ -359,6 +373,10 @@ public class SqlNote { return true; } + /** + * 获取笔记内容 + * @return JSON对象,包含笔记内容 + */ public JSONObject getContent() { try { JSONObject js = new JSONObject(); @@ -407,39 +425,74 @@ public class SqlNote { return null; } + /** + * 设置笔记的父ID + * @param id 父ID + */ public void setParentId(long id) { mParentId = id; mDiffNoteValues.put(NoteColumns.PARENT_ID, id); } + /** + * 设置GTask ID + * @param gid GTask ID + */ public void setGtaskId(String gid) { mDiffNoteValues.put(NoteColumns.GTASK_ID, gid); } + /** + * 设置同步ID + * @param syncId 同步ID + */ public void setSyncId(long syncId) { mDiffNoteValues.put(NoteColumns.SYNC_ID, syncId); } + /** + * 重置本地修改标志 + */ public void resetLocalModified() { mDiffNoteValues.put(NoteColumns.LOCAL_MODIFIED, 0); } + /** + * 获取笔记ID + * @return 笔记ID + */ public long getId() { return mId; } + /** + * 获取笔记的父ID + * @return 父ID + */ public long getParentId() { return mParentId; } + /** + * 获取笔记的片段 + * @return 片段 + */ public String getSnippet() { return mSnippet; } + /** + * 判断笔记是否为普通笔记类型 + * @return 如果笔记类型为普通笔记,返回true;否则返回false + */ public boolean isNoteType() { return mType == Notes.TYPE_NOTE; } + /** + * 提交笔记数据到数据库 + * @param validateVersion 是否验证版本 + */ public void commit(boolean validateVersion) { if (mIsCreate) { if (mId == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) { @@ -494,7 +547,7 @@ public class SqlNote { } } - // refresh local info + // 刷新本地信息 loadFromCursor(mId); if (mType == Notes.TYPE_NOTE) loadDataContent(); diff --git a/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/Task.java b/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/Task.java index 6a19454..fcd310d 100644 --- a/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/Task.java +++ b/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/Task.java @@ -31,20 +31,32 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; - +/** + * Task类用于表示一个任务节点,继承自Node类。 + * 该类提供了任务节点的创建、更新、内容设置与获取等功能。 + */ 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() { super(); mCompleted = false; @@ -54,21 +66,26 @@ public class Task extends Node { mMetaInfo = null; } + /** + * 获取任务的创建操作JSON对象 + * @param actionId 操作ID + * @return 创建操作的JSON对象 + */ public JSONObject getCreateAction(int actionId) { 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); - // index + // 设置任务在父节点中的索引 js.put(GTaskStringUtils.GTASK_JSON_INDEX, mParent.getChildTaskIndex(this)); - // entity_delta + // 设置任务的实体变化 JSONObject entity = new JSONObject(); entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null"); @@ -79,17 +96,17 @@ public class Task extends Node { } js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); - // parent_id + // 设置父节点ID js.put(GTaskStringUtils.GTASK_JSON_PARENT_ID, mParent.getGid()); - // dest_parent_type + // 设置目标父节点类型 js.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT_TYPE, GTaskStringUtils.GTASK_JSON_TYPE_GROUP); - // list_id + // 设置任务列表ID js.put(GTaskStringUtils.GTASK_JSON_LIST_ID, mParent.getGid()); - // prior_sibling_id + // 设置前一个兄弟节点ID if (mPriorSibling != null) { js.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, mPriorSibling.getGid()); } @@ -103,21 +120,26 @@ public class Task extends Node { return js; } + /** + * 获取任务的更新操作JSON对象 + * @param actionId 操作ID + * @return 更新操作的JSON对象 + */ public JSONObject getUpdateAction(int actionId) { JSONObject js = new JSONObject(); try { - // action_type + // 设置操作类型为更新 js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE); - // action_id + // 设置操作ID js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); - // id + // 设置任务ID js.put(GTaskStringUtils.GTASK_JSON_ID, getGid()); - // entity_delta + // 设置任务的实体变化 JSONObject entity = new JSONObject(); entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); if (getNotes() != null) { @@ -135,35 +157,39 @@ public class Task extends Node { return js; } + /** + * 通过远程JSON对象设置任务的内容 + * @param js 远程JSON对象 + */ public void setContentByRemoteJSON(JSONObject js) { if (js != null) { try { - // id + // 设置任务ID if (js.has(GTaskStringUtils.GTASK_JSON_ID)) { setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID)); } - // last_modified + // 设置最后修改时间 if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) { setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)); } - // name + // 设置任务名称 if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) { setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME)); } - // notes + // 设置任务备注 if (js.has(GTaskStringUtils.GTASK_JSON_NOTES)) { setNotes(js.getString(GTaskStringUtils.GTASK_JSON_NOTES)); } - // deleted + // 设置任务删除状态 if (js.has(GTaskStringUtils.GTASK_JSON_DELETED)) { setDeleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_DELETED)); } - // completed + // 设置任务完成状态 if (js.has(GTaskStringUtils.GTASK_JSON_COMPLETED)) { setCompleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_COMPLETED)); } @@ -175,6 +201,10 @@ public class Task extends Node { } } + /** + * 通过本地JSON对象设置任务的内容 + * @param js 本地JSON对象 + */ public void setContentByLocalJSON(JSONObject js) { if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE) || !js.has(GTaskStringUtils.META_HEAD_DATA)) { @@ -204,11 +234,15 @@ public class Task extends Node { } } + /** + * 从任务的内容中获取本地JSON对象 + * @return 本地JSON对象 + */ public JSONObject getLocalJSONFromContent() { String name = getName(); try { if (mMetaInfo == null) { - // new task created from web + // 从web新创建的任务 if (name == null) { Log.w(TAG, "the note seems to be an empty one"); return null; @@ -225,7 +259,7 @@ public class Task extends Node { js.put(GTaskStringUtils.META_HEAD_NOTE, note); return js; } else { - // synced task + // 同步的任务 JSONObject note = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); JSONArray dataArray = mMetaInfo.getJSONArray(GTaskStringUtils.META_HEAD_DATA); @@ -247,6 +281,10 @@ public class Task extends Node { } } + /** + * 设置任务的元信息 + * @param metaData 元信息对象 + */ public void setMetaInfo(MetaData metaData) { if (metaData != null && metaData.getNotes() != null) { try { @@ -258,6 +296,11 @@ public class Task extends Node { } } + /** + * 获取任务的同步操作类型 + * @param c 游标对象,指向数据库中的笔记 + * @return 同步操作类型 + */ public int getSyncAction(Cursor c) { try { JSONObject noteInfo = null; @@ -275,31 +318,32 @@ public class Task extends Node { return SYNC_ACTION_UPDATE_LOCAL; } - // validate the note id now + // 验证笔记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) { - // there is no local update + // 本地没有更新 if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { - // no update both side + // 双方都没有更新 return SYNC_ACTION_NONE; } else { - // apply remote to local + // 应用远程更新到本地 return SYNC_ACTION_UPDATE_LOCAL; } } else { - // validate gtask id + // 验证GTask ID if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) { Log.e(TAG, "gtask id doesn't match"); return SYNC_ACTION_ERROR; } if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { - // local modification only + // 仅本地有更新 return SYNC_ACTION_UPDATE_REMOTE; } else { + // 存在冲突 return SYNC_ACTION_UPDATE_CONFLICT; } } @@ -311,39 +355,75 @@ public class Task extends Node { return SYNC_ACTION_ERROR; } + /** + * 判断任务是否值得保存 + * @return 如果任务值得保存返回true,否则返回false + */ public boolean isWorthSaving() { return mMetaInfo != null || (getName() != null && getName().trim().length() > 0) || (getNotes() != null && getNotes().trim().length() > 0); } + /** + * 设置任务完成状态 + * @param completed 任务是否完成 + */ public void setCompleted(boolean completed) { this.mCompleted = completed; } + /** + * 设置任务的备注 + * @param notes 任务的备注 + */ public void setNotes(String notes) { this.mNotes = notes; } + /** + * 设置任务的前一个兄弟节点 + * @param priorSibling 前一个兄弟节点 + */ public void setPriorSibling(Task priorSibling) { this.mPriorSibling = priorSibling; } + /** + * 设置任务的父节点 + * @param parent 父节点 + */ public void setParent(TaskList parent) { this.mParent = parent; } + /** + * 获取任务的完成状态 + * @return 任务是否完成 + */ public boolean getCompleted() { return this.mCompleted; } + /** + * 获取任务的备注 + * @return 任务的备注 + */ public String getNotes() { return this.mNotes; } + /** + * 获取任务的前一个兄弟节点 + * @return 前一个兄弟节点 + */ public Task getPriorSibling() { return this.mPriorSibling; } + /** + * 获取任务的父节点 + * @return 父节点 + */ public TaskList getParent() { return this.mParent; } diff --git a/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/TaskList.java b/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/TaskList.java index 4ea21c5..88baf10 100644 --- a/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/TaskList.java +++ b/NotesMaster/app/src/main/java/net/micode/notes/gtask/data/TaskList.java @@ -29,35 +29,49 @@ import org.json.JSONObject; import java.util.ArrayList; - +/** + * TaskList类用于表示一个任务列表节点,继承自Node类。 + * 该类提供了任务列表的创建、更新、内容设置与获取、子任务管理等功能。 + */ public class TaskList extends Node { + // 日志标签,用于调试输出 private static final String TAG = TaskList.class.getSimpleName(); + // 任务列表的索引 private int mIndex; + // 子任务列表 private ArrayList mChildren; + /** + * TaskList类的构造函数,初始化任务列表的属性 + */ public TaskList() { super(); mChildren = new ArrayList(); mIndex = 1; } + /** + * 获取任务列表的创建操作JSON对象 + * @param actionId 操作ID + * @return 创建操作的JSON对象 + */ public JSONObject getCreateAction(int actionId) { 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); - // index + // 设置任务列表的索引 js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex); - // entity_delta + // 设置任务列表的实体变化 JSONObject entity = new JSONObject(); entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null"); @@ -74,21 +88,26 @@ public class TaskList extends Node { return js; } + /** + * 获取任务列表的更新操作JSON对象 + * @param actionId 操作ID + * @return 更新操作的JSON对象 + */ public JSONObject getUpdateAction(int actionId) { JSONObject js = new JSONObject(); try { - // action_type + // 设置操作类型为更新 js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE); - // action_id + // 设置操作ID js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); - // id + // 设置任务列表ID js.put(GTaskStringUtils.GTASK_JSON_ID, getGid()); - // entity_delta + // 设置任务列表的实体变化 JSONObject entity = new JSONObject(); entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted()); @@ -103,20 +122,24 @@ public class TaskList extends Node { return js; } + /** + * 通过远程JSON对象设置任务列表的内容 + * @param js 远程JSON对象 + */ public void setContentByRemoteJSON(JSONObject js) { if (js != null) { try { - // id + // 设置任务列表ID if (js.has(GTaskStringUtils.GTASK_JSON_ID)) { setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID)); } - // last_modified + // 设置最后修改时间 if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) { setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)); } - // name + // 设置任务列表名称 if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) { setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME)); } @@ -129,6 +152,10 @@ public class TaskList extends Node { } } + /** + * 通过本地JSON对象设置任务列表的内容 + * @param js 本地JSON对象 + */ public void setContentByLocalJSON(JSONObject js) { if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)) { Log.w(TAG, "setContentByLocalJSON: nothing is avaiable"); @@ -157,6 +184,10 @@ public class TaskList extends Node { } } + /** + * 从任务列表的内容中获取本地JSON对象 + * @return 本地JSON对象 + */ public JSONObject getLocalJSONFromContent() { try { JSONObject js = new JSONObject(); @@ -183,28 +214,33 @@ public class TaskList extends Node { } } + /** + * 获取任务列表的同步操作类型 + * @param c 游标对象,指向数据库中的任务列表 + * @return 同步操作类型 + */ public int getSyncAction(Cursor c) { try { if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) { - // there is no local update + // 本地没有更新 if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { - // no update both side + // 双方都没有更新 return SYNC_ACTION_NONE; } else { - // apply remote to local + // 应用远程更新到本地 return SYNC_ACTION_UPDATE_LOCAL; } } else { - // validate gtask id + // 验证GTask ID if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) { Log.e(TAG, "gtask id doesn't match"); return SYNC_ACTION_ERROR; } if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { - // local modification only + // 仅本地有更新 return SYNC_ACTION_UPDATE_REMOTE; } else { - // for folder conflicts, just apply local modification + // 对于文件夹冲突,仅应用本地修改 return SYNC_ACTION_UPDATE_REMOTE; } } @@ -216,16 +252,25 @@ public class TaskList extends Node { return SYNC_ACTION_ERROR; } + /** + * 获取子任务的数量 + * @return 子任务的数量 + */ public int getChildTaskCount() { return mChildren.size(); } + /** + * 添加子任务到任务列表 + * @param task 子任务 + * @return 添加成功返回true,否则返回false + */ public boolean addChildTask(Task task) { boolean ret = false; if (task != null && !mChildren.contains(task)) { ret = mChildren.add(task); if (ret) { - // need to set prior sibling and parent + // 设置前一个兄弟节点和父节点 task.setPriorSibling(mChildren.isEmpty() ? null : mChildren .get(mChildren.size() - 1)); task.setParent(this); @@ -234,6 +279,12 @@ public class TaskList extends Node { return ret; } + /** + * 在指定索引位置添加子任务到任务列表 + * @param task 子任务 + * @param index 索引位置 + * @return 添加成功返回true,否则返回false + */ public boolean addChildTask(Task task, int index) { if (index < 0 || index > mChildren.size()) { Log.e(TAG, "add child task: invalid index"); @@ -244,7 +295,7 @@ public class TaskList extends Node { if (task != null && pos == -1) { mChildren.add(index, task); - // update the task list + // 更新任务列表 Task preTask = null; Task afterTask = null; if (index != 0) @@ -260,6 +311,11 @@ public class TaskList extends Node { return true; } + /** + * 从任务列表中移除子任务 + * @param task 子任务 + * @return 移除成功返回true,否则返回false + */ public boolean removeChildTask(Task task) { boolean ret = false; int index = mChildren.indexOf(task); @@ -267,11 +323,11 @@ public class TaskList extends Node { ret = mChildren.remove(task); if (ret) { - // reset prior sibling and parent + // 重置前一个兄弟节点和父节点 task.setPriorSibling(null); task.setParent(null); - // update the task list + // 更新任务列表 if (index != mChildren.size()) { mChildren.get(index).setPriorSibling( index == 0 ? null : mChildren.get(index - 1)); @@ -281,8 +337,13 @@ public class TaskList extends Node { return ret; } + /** + * 移动子任务到任务列表的指定位置 + * @param task 子任务 + * @param index 目标索引位置 + * @return 移动成功返回true,否则返回false + */ public boolean moveChildTask(Task task, int index) { - if (index < 0 || index >= mChildren.size()) { Log.e(TAG, "move child task: invalid index"); return false; @@ -299,6 +360,11 @@ public class TaskList extends Node { return (removeChildTask(task) && addChildTask(task, index)); } + /** + * 根据GID查找子任务 + * @param gid 子任务的GID + * @return 子任务对象 + */ public Task findChildTaskByGid(String gid) { for (int i = 0; i < mChildren.size(); i++) { Task t = mChildren.get(i); @@ -309,10 +375,20 @@ public class TaskList extends Node { return null; } + /** + * 获取子任务在任务列表中的索引位置 + * @param task 子任务 + * @return 索引位置 + */ public int getChildTaskIndex(Task task) { return mChildren.indexOf(task); } + /** + * 根据索引位置获取子任务 + * @param index 索引位置 + * @return 子任务对象 + */ public Task getChildTaskByIndex(int index) { if (index < 0 || index >= mChildren.size()) { Log.e(TAG, "getTaskByIndex: invalid index"); @@ -321,6 +397,11 @@ public class TaskList extends Node { return mChildren.get(index); } + /** + * 根据GID获取子任务 + * @param gid 子任务的GID + * @return 子任务对象 + */ public Task getChilTaskByGid(String gid) { for (Task task : mChildren) { if (task.getGid().equals(gid)) @@ -329,14 +410,26 @@ public class TaskList extends Node { return null; } + /** + * 获取子任务列表 + * @return 子任务列表 + */ public ArrayList getChildTaskList() { return this.mChildren; } + /** + * 设置任务列表的索引 + * @param index 索引 + */ public void setIndex(int index) { this.mIndex = index; } + /** + * 获取任务列表的索引 + * @return 索引 + */ public int getIndex() { return this.mIndex; } diff --git a/NotesMaster/app/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java b/NotesMaster/app/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java index 15504be..a4153ea 100644 --- a/NotesMaster/app/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java +++ b/NotesMaster/app/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java @@ -16,17 +16,33 @@ package net.micode.notes.gtask.exception; +/** + * ActionFailureException类用于表示操作失败的异常。 + * 该类继承自RuntimeException,并提供了多种构造方法来创建异常对象。 + */ public class ActionFailureException extends RuntimeException { private static final long serialVersionUID = 4425249765923293627L; + /** + * 默认构造方法,创建一个ActionFailureException对象。 + */ public ActionFailureException() { super(); } + /** + * 带有异常信息的构造方法,创建一个ActionFailureException对象。 + * @param paramString 异常信息 + */ public ActionFailureException(String paramString) { super(paramString); } + /** + * 带有异常信息和原因的构造方法,创建一个ActionFailureException对象。 + * @param paramString 异常信息 + * @param paramThrowable 异常原因 + */ public ActionFailureException(String paramString, Throwable paramThrowable) { super(paramString, paramThrowable); } diff --git a/NotesMaster/app/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java b/NotesMaster/app/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java index b08cfb1..6a3cab9 100644 --- a/NotesMaster/app/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java +++ b/NotesMaster/app/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java @@ -16,17 +16,33 @@ package net.micode.notes.gtask.exception; +/** + * NetworkFailureException类用于表示网络操作失败的异常。 + * 该类继承自Exception,并提供了多种构造方法来创建异常对象。 + */ public class NetworkFailureException extends Exception { private static final long serialVersionUID = 2107610287180234136L; + /** + * 默认构造方法,创建一个NetworkFailureException对象。 + */ public NetworkFailureException() { super(); } + /** + * 带有异常信息的构造方法,创建一个NetworkFailureException对象。 + * @param paramString 异常信息 + */ public NetworkFailureException(String paramString) { super(paramString); } + /** + * 带有异常信息和原因的构造方法,创建一个NetworkFailureException对象。 + * @param paramString 异常信息 + * @param paramThrowable 异常原因 + */ public NetworkFailureException(String paramString, Throwable paramThrowable) { super(paramString, paramThrowable); } diff --git a/NotesMaster/app/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java b/NotesMaster/app/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java index 7abccfd..f52dd34 100644 --- a/NotesMaster/app/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java +++ b/NotesMaster/app/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) * @@ -28,23 +27,39 @@ import net.micode.notes.R; import net.micode.notes.ui.NotesListActivity; import net.micode.notes.ui.NotesPreferenceActivity; - +/** + * GTaskASyncTask类用于异步同步任务管理。 + * 该类继承自AsyncTask,并提供了任务的后台执行、进度更新、任务完成的功能。 + */ public class GTaskASyncTask extends AsyncTask { + // 同步通知的ID private static int GTASK_SYNC_NOTIFICATION_ID = 5234235; + /** + * 任务完成监听器接口 + */ public interface OnCompleteListener { void onComplete(); } + // 上下文对象 private Context mContext; + // 通知管理器 private NotificationManager mNotifiManager; + // GTask任务管理器 private GTaskManager mTaskManager; + // 任务完成监听器 private OnCompleteListener mOnCompleteListener; + /** + * 构造函数,初始化GTaskASyncTask对象 + * @param context 上下文对象 + * @param listener 任务完成监听器 + */ public GTaskASyncTask(Context context, OnCompleteListener listener) { mContext = context; mOnCompleteListener = listener; @@ -53,16 +68,28 @@ public class GTaskASyncTask extends AsyncTask { mTaskManager = GTaskManager.getInstance(); } + /** + * 取消同步任务 + */ public void cancelSync() { mTaskManager.cancelSync(); } + /** + * 发布进度信息 + * @param message 进度信息 + */ public void publishProgess(String message) { publishProgress(new String[] { message }); } + /** + * 显示通知 + * @param tickerId 通知栏提示ID + * @param content 通知内容 + */ private void showNotification(int tickerId, String content) { Notification notification = new Notification(R.drawable.notification, mContext .getString(tickerId), System.currentTimeMillis()); @@ -77,10 +104,15 @@ public class GTaskASyncTask extends AsyncTask { pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext, NotesListActivity.class), 0); } -// notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content, pendingIntent); + //notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content, pendingIntent); mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification); } + /** + * 后台执行任务 + * @param unused 不使用的参数 + * @return 同步状态 + */ @Override protected Integer doInBackground(Void... unused) { publishProgess(mContext.getString(R.string.sync_progress_login, NotesPreferenceActivity @@ -88,6 +120,10 @@ public class GTaskASyncTask extends AsyncTask { return mTaskManager.sync(mContext, this); } + /** + * 更新任务进度 + * @param progress 进度信息 + */ @Override protected void onProgressUpdate(String... progress) { showNotification(R.string.ticker_syncing, progress[0]); @@ -96,6 +132,10 @@ public class GTaskASyncTask extends AsyncTask { } } + /** + * 任务执行完成后的操作 + * @param result 同步结果状态 + */ @Override protected void onPostExecute(Integer result) { if (result == GTaskManager.STATE_SUCCESS) { @@ -112,7 +152,6 @@ public class GTaskASyncTask extends AsyncTask { } if (mOnCompleteListener != null) { new Thread(new Runnable() { - public void run() { mOnCompleteListener.onComplete(); } diff --git a/NotesMaster/app/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java b/NotesMaster/app/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java index 199785f..adfe51d 100644 --- a/NotesMaster/app/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java +++ b/NotesMaster/app/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java @@ -55,36 +55,56 @@ import java.nio.charset.Charset; import java.util.LinkedList; import java.util.List; - +/** + * GTaskClient类用于与Google Tasks服务进行交互。 + * 该类实现了登录、获取任务列表、创建任务和任务列表、提交更新、移动任务和删除节点等功能。 + */ public class GTaskClient { + // 日志标签,用于调试输出 private static final String TAG = GTaskClient.class.getSimpleName(); + // Google Tasks服务的URL private static final String GTASK_URL = "https://mail.google.com/tasks/"; + // 获取任务的URL private static final String GTASK_GET_URL = "https://mail.google.com/tasks/ig"; + // 提交任务的URL private static final String GTASK_POST_URL = "https://mail.google.com/tasks/r/ig"; + // 单例实例 private static GTaskClient mInstance = null; + // HttpClient对象 private CloseableHttpClient mHttpClient; + // 获取任务的URL private String mGetUrl; + // 提交任务的URL private String mPostUrl; + // 客户端版本 private long mClientVersion; + // 是否已登录 private boolean mLoggedin; + // 最后登录时间 private long mLastLoginTime; + // 操作ID private int mActionId; + // 账号对象 private Account mAccount; + // 更新数组 private JSONArray mUpdateArray; + /** + * 私有构造函数,初始化GTaskClient对象 + */ private GTaskClient() { mHttpClient = null; mGetUrl = GTASK_GET_URL; @@ -97,6 +117,10 @@ public class GTaskClient { mUpdateArray = null; } + /** + * 获取GTaskClient的单例实例 + * @return GTaskClient实例 + */ public static synchronized GTaskClient getInstance() { if (mInstance == null) { mInstance = new GTaskClient(); @@ -104,18 +128,22 @@ public class GTaskClient { return mInstance; } + /** + * 登录Google Tasks服务 + * @param activity 活动对象 + * @return 登录成功返回true,否则返回false + */ public boolean login(Activity activity) { - // we suppose that the cookie would expire after 5 minutes - // then we need to re-login + // 假设cookie会在5分钟后过期,需要重新登录 final long interval = 1000 * 60 * 5; if (mLastLoginTime + interval < System.currentTimeMillis()) { mLoggedin = false; } - // need to re-login after account switch + // 账号切换后需要重新登录 if (mLoggedin && !TextUtils.equals(getSyncAccount().name, NotesPreferenceActivity - .getSyncAccountName(activity))) { + .getSyncAccountName(activity))) { mLoggedin = false; } @@ -131,7 +159,7 @@ public class GTaskClient { return false; } - // login with custom domain if necessary + // 必要时使用自定义域登录 if (!(mAccount.name.toLowerCase().endsWith("gmail.com") || mAccount.name.toLowerCase() .endsWith("googlemail.com"))) { StringBuilder url = new StringBuilder(GTASK_URL).append("a/"); @@ -146,7 +174,7 @@ public class GTaskClient { } } - // try to login with google official url + // 尝试使用Google官方URL登录 if (!mLoggedin) { mGetUrl = GTASK_GET_URL; mPostUrl = GTASK_POST_URL; @@ -159,6 +187,12 @@ public class GTaskClient { return true; } + /** + * 登录Google账号 + * @param activity 活动对象 + * @param invalidateToken 是否使令牌失效 + * @return 登录成功返回授权令牌,否则返回null + */ private String loginGoogleAccount(Activity activity, boolean invalidateToken) { String authToken; AccountManager accountManager = AccountManager.get(activity); @@ -184,7 +218,7 @@ public class GTaskClient { return null; } - // get the token now + // 获取授权令牌 AccountManagerFuture accountManagerFuture = accountManager.getAuthToken(account, "goanna_mobile", null, activity, null, null); try { @@ -202,10 +236,15 @@ public class GTaskClient { return authToken; } + /** + * 尝试登录Google Tasks服务 + * @param activity 活动对象 + * @param authToken 授权令牌 + * @return 登录成功返回true,否则返回false + */ private boolean tryToLoginGtask(Activity activity, String authToken) { if (!loginGtask(authToken)) { - // maybe the auth token is out of date, now let's invalidate the - // token and try again + // 可能授权令牌已过期,现在让我们使令牌失效并再次尝试 authToken = loginGoogleAccount(activity, true); if (authToken == null) { Log.e(TAG, "login google account failed"); @@ -220,6 +259,11 @@ public class GTaskClient { return true; } + /** + * 登录Google Tasks服务 + * @param authToken 授权令牌 + * @return 登录成功返回true,否则返回false + */ private boolean loginGtask(String authToken) { // 连接超时的毫秒数 int timeoutConnection = 10000; @@ -233,8 +277,7 @@ public class GTaskClient { .setResponseTimeout(Timeout.ofMilliseconds(timeoutResponse)) .build(); - - // login gtask + // 登录GTask服务 try { String loginUrl = mGetUrl + "?auth=" + authToken; // 创建Get请求 @@ -246,7 +289,7 @@ public class GTaskClient { httpClientContext.setCookieStore(cookieStore); String resString = mHttpClient.execute(httpGet, httpClientContext,new BasicHttpClientResponseHandler()); - // get the cookie now + // 获取cookie List cookies = cookieStore.getCookies(); boolean hasAuthCookie = false; for (Cookie cookie : cookies) { @@ -258,7 +301,7 @@ public class GTaskClient { Log.w(TAG, "it seems that there is no auth cookie"); } - // get the client version + // 获取客户端版本 String jsBegin = "_setup("; String jsEnd = ")}"; int begin = resString.indexOf(jsBegin); @@ -274,7 +317,7 @@ public class GTaskClient { e.printStackTrace(); return false; } catch (Exception e) { - // simply catch all exceptions + // 简单捕获所有异常 Log.e(TAG, "httpget gtask_url failed"); return false; } @@ -282,10 +325,18 @@ public class GTaskClient { return true; } + /** + * 获取操作ID + * @return 操作ID + */ private int getActionId() { return mActionId++; } + /** + * 创建HttpPost对象 + * @return HttpPost对象 + */ private HttpPost createHttpPost() { HttpPost httpPost = new HttpPost(mPostUrl); httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); @@ -293,7 +344,12 @@ public class GTaskClient { return httpPost; } - + /** + * 发送POST请求 + * @param js JSON对象 + * @return 响应的JSON对象 + * @throws NetworkFailureException 网络故障异常 + */ private JSONObject postRequest(JSONObject js) throws NetworkFailureException { if (!mLoggedin) { Log.e(TAG, "please login first"); @@ -307,7 +363,7 @@ public class GTaskClient { UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, Charset.forName("utf8")); httpPost.setEntity(entity); - // execute the post + // 执行POST请求 String jsString = mHttpClient.execute(httpPost,new BasicHttpClientResponseHandler()); return new JSONObject(jsString); @@ -330,6 +386,11 @@ public class GTaskClient { } } + /** + * 创建任务 + * @param task 任务对象 + * @throws NetworkFailureException 网络故障异常 + */ public void createTask(Task task) throws NetworkFailureException { commitUpdate(); try { @@ -356,6 +417,11 @@ public class GTaskClient { } } + /** + * 创建任务列表 + * @param tasklist 任务列表对象 + * @throws NetworkFailureException 网络故障异常 + */ public void createTaskList(TaskList tasklist) throws NetworkFailureException { commitUpdate(); try { @@ -366,7 +432,7 @@ public class GTaskClient { actionList.put(tasklist.getCreateAction(getActionId())); jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); - // client version + // client_version jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); // post @@ -382,6 +448,10 @@ public class GTaskClient { } } + /** + * 提交更新 + * @throws NetworkFailureException 网络故障异常 + */ public void commitUpdate() throws NetworkFailureException { if (mUpdateArray != null) { try { @@ -403,10 +473,14 @@ public class GTaskClient { } } + /** + * 添加更新节点 + * @param node 节点对象 + * @throws NetworkFailureException 网络故障异常 + */ public void addUpdateNode(Node node) throws NetworkFailureException { if (node != null) { - // too many update items may result in an error - // set max to 10 items + // 太多更新项可能会导致错误,最大设置为10项 if (mUpdateArray != null && mUpdateArray.length() > 10) { commitUpdate(); } @@ -417,6 +491,13 @@ public class GTaskClient { } } + /** + * 移动任务 + * @param task 任务对象 + * @param preParent 之前的父任务列表 + * @param curParent 当前的父任务列表 + * @throws NetworkFailureException 网络故障异常 + */ public void moveTask(Task task, TaskList preParent, TaskList curParent) throws NetworkFailureException { commitUpdate(); @@ -431,14 +512,13 @@ public class GTaskClient { action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId()); action.put(GTaskStringUtils.GTASK_JSON_ID, task.getGid()); if (preParent == curParent && task.getPriorSibling() != null) { - // put prioring_sibing_id only if moving within the tasklist and - // it is not the first one + // 仅在任务列表内移动且不是第一个时放置prioring_sibling_id action.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, task.getPriorSibling()); } action.put(GTaskStringUtils.GTASK_JSON_SOURCE_LIST, preParent.getGid()); action.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT, curParent.getGid()); if (preParent != curParent) { - // put the dest_list only if moving between tasklists + // 仅在任务列表之间移动时放置dest_list action.put(GTaskStringUtils.GTASK_JSON_DEST_LIST, curParent.getGid()); } actionList.put(action); @@ -456,6 +536,11 @@ public class GTaskClient { } } + /** + * 删除节点 + * @param node 节点对象 + * @throws NetworkFailureException 网络故障异常 + */ public void deleteNode(Node node) throws NetworkFailureException { commitUpdate(); try { @@ -479,6 +564,11 @@ public class GTaskClient { } } + /** + * 获取任务列表 + * @return 任务列表的JSON数组 + * @throws NetworkFailureException 网络故障异常 + */ public JSONArray getTaskLists() throws NetworkFailureException { if (!mLoggedin) { Log.e(TAG, "please login first"); @@ -488,7 +578,7 @@ public class GTaskClient { try { HttpGet httpGet = new HttpGet(mGetUrl); - // get the task list + // 获取任务列表 String resString = mHttpClient.execute(httpGet,new BasicHttpClientResponseHandler()); String jsBegin = "_setup("; String jsEnd = ")}"; @@ -515,6 +605,12 @@ public class GTaskClient { } } + /** + * 获取指定任务列表的任务 + * @param listGid 任务列表的GID + * @return 任务的JSON数组 + * @throws NetworkFailureException 网络故障异常 + */ public JSONArray getTaskList(String listGid) throws NetworkFailureException { commitUpdate(); try { @@ -543,10 +639,17 @@ public class GTaskClient { } } + /** + * 获取同步账号 + * @return 同步账号 + */ public Account getSyncAccount() { return mAccount; } + /** + * 重置更新数组 + */ public void resetUpdateArray() { mUpdateArray = null; } diff --git a/NotesMaster/app/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java b/NotesMaster/app/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java index 73c80f0..c78ca22 100644 --- a/NotesMaster/app/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java +++ b/NotesMaster/app/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java @@ -47,45 +47,37 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Map; - +/** + * GTaskManager类负责管理与Google Task的同步操作。 + * 它实现了同步任务列表和任务、处理元数据、管理同步状态和处理网络或操作失败的情况。 + */ public class GTaskManager { private static final String TAG = GTaskManager.class.getSimpleName(); - public static final int STATE_SUCCESS = 0; - - public static final int STATE_NETWORK_ERROR = 1; - - public static final int STATE_INTERNAL_ERROR = 2; + public static final int STATE_SUCCESS = 0; // 同步成功 + public static final int STATE_NETWORK_ERROR = 1; // 网络错误 + public static final int STATE_INTERNAL_ERROR = 2; // 内部错误 + public static final int STATE_SYNC_IN_PROGRESS = 3; // 同步进行中 + public static final int STATE_SYNC_CANCELLED = 4; // 同步取消 - public static final int STATE_SYNC_IN_PROGRESS = 3; - - public static final int STATE_SYNC_CANCELLED = 4; - - private static GTaskManager mInstance = null; + private static GTaskManager mInstance = null; // 单例实例 private Activity mActivity; - private Context mContext; - private ContentResolver mContentResolver; - private boolean mSyncing; + private boolean mSyncing; // 同步状态标志 + private boolean mCancelled; // 取消同步标志 - private boolean mCancelled; + private HashMap mGTaskListHashMap; // 任务列表映射 + private HashMap mGTaskHashMap; // 任务节点映射 + private HashMap mMetaHashMap; // 元数据映射 - private HashMap mGTaskListHashMap; + private TaskList mMetaList; // 元数据列表 + private HashSet mLocalDeleteIdMap; // 本地删除的ID集合 - private HashMap mGTaskHashMap; - - private HashMap mMetaHashMap; - - private TaskList mMetaList; - - private HashSet mLocalDeleteIdMap; - - private HashMap mGidToNid; - - private HashMap mNidToGid; + private HashMap mGidToNid; // GID到NID的映射 + private HashMap mNidToGid; // NID到GID的映射 private GTaskManager() { mSyncing = false; @@ -99,6 +91,11 @@ public class GTaskManager { mNidToGid = new HashMap(); } + /** + * 获取GTaskManager的单例实例。 + * + * @return 单例实例 + */ public static synchronized GTaskManager getInstance() { if (mInstance == null) { mInstance = new GTaskManager(); @@ -106,11 +103,22 @@ public class GTaskManager { return mInstance; } + /** + * 设置Activity上下文,用于获取AuthToken。 + * + * @param activity Activity实例 + */ public synchronized void setActivityContext(Activity activity) { - // used for getting authtoken mActivity = activity; } + /** + * 执行同步操作。 + * + * @param context 上下文 + * @param asyncTask 异步任务 + * @return 同步状态 + */ public int sync(Context context, GTaskASyncTask asyncTask) { if (mSyncing) { Log.d(TAG, "Sync is in progress"); @@ -131,18 +139,18 @@ public class GTaskManager { GTaskClient client = GTaskClient.getInstance(); client.resetUpdateArray(); - // login google task + // 登录Google Task if (!mCancelled) { if (!client.login(mActivity)) { throw new NetworkFailureException("login google task failed"); } } - // get the task list from google + // 从Google获取任务列表 asyncTask.publishProgess(mContext.getString(R.string.sync_progress_init_list)); initGTaskList(); - // do content sync work + // 执行内容同步工作 asyncTask.publishProgess(mContext.getString(R.string.sync_progress_syncing)); syncContent(); } catch (NetworkFailureException e) { @@ -168,6 +176,11 @@ public class GTaskManager { return mCancelled ? STATE_SYNC_CANCELLED : STATE_SUCCESS; } + /** + * 初始化GTask任务列表。 + * + * @throws NetworkFailureException 网络故障异常 + */ private void initGTaskList() throws NetworkFailureException { if (mCancelled) return; @@ -175,22 +188,21 @@ public class GTaskManager { try { JSONArray jsTaskLists = client.getTaskLists(); - // init meta list first + // 初始化元数据列表 mMetaList = null; for (int i = 0; i < jsTaskLists.length(); i++) { JSONObject object = jsTaskLists.getJSONObject(i); String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID); String name = object.getString(GTaskStringUtils.GTASK_JSON_NAME); - if (name - .equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META)) { + if (name.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META)) { mMetaList = new TaskList(); mMetaList.setContentByRemoteJSON(object); - // load meta data + // 加载元数据 JSONArray jsMetas = client.getTaskList(gid); for (int j = 0; j < jsMetas.length(); j++) { - object = (JSONObject) jsMetas.getJSONObject(j); + object = jsMetas.getJSONObject(j); MetaData metaData = new MetaData(); metaData.setContentByRemoteJSON(object); if (metaData.isWorthSaving()) { @@ -203,32 +215,30 @@ public class GTaskManager { } } - // create meta list if not existed + // 如果元数据列表不存在则创建 if (mMetaList == null) { mMetaList = new TaskList(); - mMetaList.setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX - + GTaskStringUtils.FOLDER_META); + mMetaList.setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META); GTaskClient.getInstance().createTaskList(mMetaList); } - // init task list + // 初始化任务列表 for (int i = 0; i < jsTaskLists.length(); i++) { JSONObject object = jsTaskLists.getJSONObject(i); String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID); String name = object.getString(GTaskStringUtils.GTASK_JSON_NAME); - if (name.startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX) - && !name.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX - + GTaskStringUtils.FOLDER_META)) { + if (name.startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX) && + !name.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META)) { TaskList tasklist = new TaskList(); tasklist.setContentByRemoteJSON(object); mGTaskListHashMap.put(gid, tasklist); mGTaskHashMap.put(gid, tasklist); - // load tasks + // 加载任务 JSONArray jsTasks = client.getTaskList(gid); for (int j = 0; j < jsTasks.length(); j++) { - object = (JSONObject) jsTasks.getJSONObject(j); + object = jsTasks.getJSONObject(j); gid = object.getString(GTaskStringUtils.GTASK_JSON_ID); Task task = new Task(); task.setContentByRemoteJSON(object); @@ -247,6 +257,11 @@ public class GTaskManager { } } + /** + * 执行内容同步。 + * + * @throws NetworkFailureException 网络故障异常 + */ private void syncContent() throws NetworkFailureException { int syncType; Cursor c = null; @@ -259,7 +274,7 @@ public class GTaskManager { return; } - // for local deleted note + // 处理本地删除的便签 try { c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, "(type<>? AND parent_id=?)", new String[] { @@ -286,10 +301,10 @@ public class GTaskManager { } } - // sync folder first + // 同步文件夹 syncFolder(); - // for note existing in database + // 处理数据库中现有的便签 try { c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, "(type=? AND parent_id<>?)", new String[] { @@ -306,10 +321,8 @@ public class GTaskManager { syncType = node.getSyncAction(c); } else { if (c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == 0) { - // local add syncType = Node.SYNC_ACTION_ADD_REMOTE; } else { - // remote delete syncType = Node.SYNC_ACTION_DEL_LOCAL; } } @@ -318,7 +331,6 @@ public class GTaskManager { } else { Log.w(TAG, "failed to query existing note in database"); } - } finally { if (c != null) { c.close(); @@ -326,7 +338,7 @@ public class GTaskManager { } } - // go through remaining items + // 处理剩余项 Iterator> iter = mGTaskHashMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = iter.next(); @@ -334,23 +346,23 @@ public class GTaskManager { doContentSync(Node.SYNC_ACTION_ADD_LOCAL, node, null); } - // mCancelled can be set by another thread, so we neet to check one by - // one - // clear local delete table if (!mCancelled) { if (!DataUtils.batchDeleteNotes(mContentResolver, mLocalDeleteIdMap)) { throw new ActionFailureException("failed to batch-delete local deleted notes"); } } - // refresh local sync id if (!mCancelled) { GTaskClient.getInstance().commitUpdate(); refreshLocalSyncId(); } - } + /** + * 同步文件夹。 + * + * @throws NetworkFailureException 网络故障异常 + */ private void syncFolder() throws NetworkFailureException { Cursor c = null; String gid; @@ -361,7 +373,7 @@ public class GTaskManager { return; } - // for root folder + // 处理根文件夹 try { c = mContentResolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, Notes.ID_ROOT_FOLDER), SqlNote.PROJECTION_NOTE, null, null, null); @@ -373,9 +385,7 @@ public class GTaskManager { mGTaskHashMap.remove(gid); mGidToNid.put(gid, (long) Notes.ID_ROOT_FOLDER); mNidToGid.put((long) Notes.ID_ROOT_FOLDER, gid); - // for system folder, only update remote name if necessary - if (!node.getName().equals( - GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT)) + if (!node.getName().equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT)) doContentSync(Node.SYNC_ACTION_UPDATE_REMOTE, node, c); } else { doContentSync(Node.SYNC_ACTION_ADD_REMOTE, node, c); @@ -390,7 +400,7 @@ public class GTaskManager { } } - // for call-note folder + // 处理通话记录文件夹 try { c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, "(_id=?)", new String[] { @@ -404,11 +414,7 @@ public class GTaskManager { mGTaskHashMap.remove(gid); mGidToNid.put(gid, (long) Notes.ID_CALL_RECORD_FOLDER); mNidToGid.put((long) Notes.ID_CALL_RECORD_FOLDER, gid); - // for system folder, only update remote name if - // necessary - if (!node.getName().equals( - GTaskStringUtils.MIUI_FOLDER_PREFFIX - + GTaskStringUtils.FOLDER_CALL_NOTE)) + if (!node.getName().equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_CALL_NOTE)) doContentSync(Node.SYNC_ACTION_UPDATE_REMOTE, node, c); } else { doContentSync(Node.SYNC_ACTION_ADD_REMOTE, node, c); @@ -424,7 +430,7 @@ public class GTaskManager { } } - // for local existing folders + // 处理本地现有文件夹 try { c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, "(type=? AND parent_id<>?)", new String[] { @@ -441,10 +447,8 @@ public class GTaskManager { syncType = node.getSyncAction(c); } else { if (c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == 0) { - // local add syncType = Node.SYNC_ACTION_ADD_REMOTE; } else { - // remote delete syncType = Node.SYNC_ACTION_DEL_LOCAL; } } @@ -460,7 +464,7 @@ public class GTaskManager { } } - // for remote add folders + // 处理远程添加文件夹 Iterator> iter = mGTaskListHashMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = iter.next(); @@ -476,6 +480,14 @@ public class GTaskManager { GTaskClient.getInstance().commitUpdate(); } + /** + * 执行内容同步操作。 + * + * @param syncType 同步类型 + * @param node 节点 + * @param c 游标 + * @throws NetworkFailureException 网络故障异常 + */ private void doContentSync(int syncType, Node node, Cursor c) throws NetworkFailureException { if (mCancelled) { return; @@ -510,8 +522,6 @@ public class GTaskManager { updateRemoteNode(node, c); break; case Node.SYNC_ACTION_UPDATE_CONFLICT: - // merging both modifications maybe a good idea - // right now just use local update simply updateRemoteNode(node, c); break; case Node.SYNC_ACTION_NONE: @@ -522,6 +532,12 @@ public class GTaskManager { } } + /** + * 添加本地节点。 + * + * @param node 节点 + * @throws NetworkFailureException 网络故障异常 + */ private void addLocalNode(Node node) throws NetworkFailureException { if (mCancelled) { return; @@ -529,11 +545,9 @@ public class GTaskManager { SqlNote sqlNote; if (node instanceof TaskList) { - if (node.getName().equals( - GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT)) { + if (node.getName().equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT)) { sqlNote = new SqlNote(mContext, Notes.ID_ROOT_FOLDER); - } else if (node.getName().equals( - GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_CALL_NOTE)) { + } else if (node.getName().equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_CALL_NOTE)) { sqlNote = new SqlNote(mContext, Notes.ID_CALL_RECORD_FOLDER); } else { sqlNote = new SqlNote(mContext); @@ -549,7 +563,6 @@ public class GTaskManager { if (note.has(NoteColumns.ID)) { long id = note.getLong(NoteColumns.ID); if (DataUtils.existInNoteDatabase(mContentResolver, id)) { - // the id is not available, have to create a new one note.remove(NoteColumns.ID); } } @@ -562,13 +575,10 @@ public class GTaskManager { if (data.has(DataColumns.ID)) { long dataId = data.getLong(DataColumns.ID); if (DataUtils.existInDataDatabase(mContentResolver, dataId)) { - // the data id is not available, have to create - // a new one data.remove(DataColumns.ID); } } } - } } catch (JSONException e) { Log.w(TAG, e.toString()); @@ -584,25 +594,28 @@ public class GTaskManager { sqlNote.setParentId(parentId.longValue()); } - // create the local node sqlNote.setGtaskId(node.getGid()); sqlNote.commit(false); - // update gid-nid mapping mGidToNid.put(node.getGid(), sqlNote.getId()); mNidToGid.put(sqlNote.getId(), node.getGid()); - // update meta updateRemoteMeta(node.getGid(), sqlNote); } + /** + * 更新本地节点。 + * + * @param node 节点 + * @param c 游标 + * @throws NetworkFailureException 网络故障异常 + */ private void updateLocalNode(Node node, Cursor c) throws NetworkFailureException { if (mCancelled) { return; } SqlNote sqlNote; - // update the note locally sqlNote = new SqlNote(mContext, c); sqlNote.setContent(node.getLocalJSONFromContent()); @@ -615,10 +628,16 @@ public class GTaskManager { sqlNote.setParentId(parentId.longValue()); sqlNote.commit(true); - // update meta info updateRemoteMeta(node.getGid(), sqlNote); } + /** + * 添加远程节点。 + * + * @param node 节点 + * @param c 游标 + * @throws NetworkFailureException 网络故障异常 + */ private void addRemoteNode(Node node, Cursor c) throws NetworkFailureException { if (mCancelled) { return; @@ -627,7 +646,6 @@ public class GTaskManager { SqlNote sqlNote = new SqlNote(mContext, c); Node n; - // update remotely if (sqlNote.isNoteType()) { Task task = new Task(); task.setContentByLocalJSON(sqlNote.getContent()); @@ -642,12 +660,10 @@ public class GTaskManager { GTaskClient.getInstance().createTask(task); n = (Node) task; - // add meta updateRemoteMeta(task.getGid(), sqlNote); } else { TaskList tasklist = null; - // we need to skip folder if it has already existed String folderName = GTaskStringUtils.MIUI_FOLDER_PREFFIX; if (sqlNote.getId() == Notes.ID_ROOT_FOLDER) folderName += GTaskStringUtils.FOLDER_DEFAULT; @@ -671,7 +687,6 @@ public class GTaskManager { } } - // no match we can add now if (tasklist == null) { tasklist = new TaskList(); tasklist.setContentByLocalJSON(sqlNote.getContent()); @@ -681,17 +696,22 @@ public class GTaskManager { n = (Node) tasklist; } - // update local note sqlNote.setGtaskId(n.getGid()); sqlNote.commit(false); sqlNote.resetLocalModified(); sqlNote.commit(true); - // gid-id mapping mGidToNid.put(n.getGid(), sqlNote.getId()); mNidToGid.put(sqlNote.getId(), n.getGid()); } + /** + * 更新远程节点。 + * + * @param node 节点 + * @param c 游标 + * @throws NetworkFailureException 网络故障异常 + */ private void updateRemoteNode(Node node, Cursor c) throws NetworkFailureException { if (mCancelled) { return; @@ -699,14 +719,11 @@ public class GTaskManager { SqlNote sqlNote = new SqlNote(mContext, c); - // update remotely node.setContentByLocalJSON(sqlNote.getContent()); GTaskClient.getInstance().addUpdateNode(node); - // update meta updateRemoteMeta(node.getGid(), sqlNote); - // move task if necessary if (sqlNote.isNoteType()) { Task task = (Task) node; TaskList preParentList = task.getParent(); @@ -725,11 +742,17 @@ public class GTaskManager { } } - // clear local modified flag sqlNote.resetLocalModified(); sqlNote.commit(true); } + /** + * 更新远程元数据。 + * + * @param gid GID + * @param sqlNote SqlNote实例 + * @throws NetworkFailureException 网络故障异常 + */ private void updateRemoteMeta(String gid, SqlNote sqlNote) throws NetworkFailureException { if (sqlNote != null && sqlNote.isNoteType()) { MetaData metaData = mMetaHashMap.get(gid); @@ -746,12 +769,16 @@ public class GTaskManager { } } + /** + * 刷新本地同步ID。 + * + * @throws NetworkFailureException 网络故障异常 + */ private void refreshLocalSyncId() throws NetworkFailureException { if (mCancelled) { return; } - // get the latest gtask list mGTaskHashMap.clear(); mGTaskListHashMap.clear(); mMetaHashMap.clear(); @@ -790,10 +817,18 @@ public class GTaskManager { } } + /** + * 获取同步账户。 + * + * @return 同步账户名称 + */ public String getSyncAccount() { return GTaskClient.getInstance().getSyncAccount().name; } + /** + * 取消同步操作。 + */ public void cancelSync() { mCancelled = true; } diff --git a/NotesMaster/app/src/main/java/net/micode/notes/gtask/remote/GTaskSyncService.java b/NotesMaster/app/src/main/java/net/micode/notes/gtask/remote/GTaskSyncService.java index cca36f7..f943200 100644 --- a/NotesMaster/app/src/main/java/net/micode/notes/gtask/remote/GTaskSyncService.java +++ b/NotesMaster/app/src/main/java/net/micode/notes/gtask/remote/GTaskSyncService.java @@ -23,6 +23,10 @@ import android.content.Intent; import android.os.Bundle; import android.os.IBinder; +/** + * GTaskSyncService负责在后台执行GTask的同步操作。 + * 它使用GTaskASyncTask来执行实际的同步工作,并在同步过程中发送广播通知。 + */ public class GTaskSyncService extends Service { public final static String ACTION_STRING_NAME = "sync_action_type"; @@ -42,6 +46,10 @@ public class GTaskSyncService extends Service { private static String mSyncProgress = ""; + /** + * 开始同步任务。 + * 如果当前没有同步任务在进行,则创建一个新的GTaskASyncTask并执行。 + */ private void startSync() { if (mSyncTask == null) { mSyncTask = new GTaskASyncTask(this, new GTaskASyncTask.OnCompleteListener() { @@ -56,6 +64,10 @@ public class GTaskSyncService extends Service { } } + /** + * 取消当前的同步任务。 + * 如果当前有同步任务在进行,则取消它。 + */ private void cancelSync() { if (mSyncTask != null) { mSyncTask.cancelSync(); @@ -97,6 +109,10 @@ public class GTaskSyncService extends Service { return null; } + /** + * 发送广播通知同步状态。 + * @param msg 同步进度信息 + */ public void sendBroadcast(String msg) { mSyncProgress = msg; Intent intent = new Intent(GTASK_SERVICE_BROADCAST_NAME); @@ -105,6 +121,10 @@ public class GTaskSyncService extends Service { sendBroadcast(intent); } + /** + * 静态方法,启动同步服务。 + * @param activity 调用该方法的Activity + */ public static void startSync(Activity activity) { GTaskManager.getInstance().setActivityContext(activity); Intent intent = new Intent(activity, GTaskSyncService.class); @@ -112,16 +132,28 @@ public class GTaskSyncService extends Service { activity.startService(intent); } + /** + * 静态方法,取消同步服务。 + * @param context 调用该方法的Context + */ public static void cancelSync(Context context) { Intent intent = new Intent(context, GTaskSyncService.class); intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_CANCEL_SYNC); context.startService(intent); } + /** + * 检查是否有同步任务在进行。 + * @return 如果有同步任务在进行,返回true;否则返回false。 + */ public static boolean isSyncing() { return mSyncTask != null; } + /** + * 获取同步进度信息。 + * @return 同步进度信息字符串 + */ public static String getProgressString() { return mSyncProgress; } -- 2.34.1