Compare commits

...

5 Commits

@ -30,54 +30,59 @@ public abstract class Node {//定义各种常量
private long mLastModified;//记录最后一次修改时间
private boolean mDeleted;//表征是否被删除
public Node() {
//mGid: 字符串类型,用于标识 Node 对象的唯一 ID。
//mName: 字符串类型,表示 Node 对象的名称。
//mLastModified: 长整型,表示 Node 对象最后一次修改的时间戳。
//mDeleted: 布尔型,表示 Node 对象是否已被删除。
public Node() {
mGid = null;
mName = "";
mLastModified = 0;
mDeleted = false;
}
//getCreateAction(int actionId): 返回一个 JSON 对象,用于创建一个新的 Node 对象。
public abstract JSONObject getCreateAction(int actionId);
//getUpdateAction(int actionId): 返回一个 JSON 对象,用于更新已有的 Node 对象。
public abstract JSONObject getUpdateAction(int actionId);
//setContentByRemoteJSON(JSONObject js): 从远程 JSON 对象中解析数据并设置 Node 对象的属性。
public abstract void setContentByRemoteJSON(JSONObject js);
//setContentByLocalJSON(JSONObject js): 从本地 JSON 对象中解析数据并设置 Node 对象的属性。
public abstract void setContentByLocalJSON(JSONObject js);
//getLocalJSONFromContent(): 返回一个本地 JSON 对象,包含了 Node 对象的所有属性。
public abstract JSONObject getLocalJSONFromContent();
//getSyncAction(Cursor c): 返回一个整型值,表示需要执行的同步操作类型。
public abstract int getSyncAction(Cursor c);
//setGid(String gid): 设置 mGid 属性的值。
public void setGid(String gid) {
this.mGid = gid;
}
//setName(String name): 设置 mName 属性的值。
public void setName(String name) {
this.mName = name;
}
//setLastModified(long lastModified): 设置 mLastModified 属性的值。
public void setLastModified(long lastModified) {
this.mLastModified = lastModified;
}
//setDeleted(boolean deleted): 设置 mDeleted 属性的值。
public void setDeleted(boolean deleted) {
this.mDeleted = deleted;
}
//getGid(): 返回 mGid 属性的值。
public String getGid() {
return this.mGid;
}
//getName(): 返回 mName 属性的值。
public String getName() {
return this.mName;
}
//getLastModified(): 返回 mLastModified 属性的值。
public long getLastModified() {
return this.mLastModified;
}
//getDeleted(): 返回 mDeleted 属性的值。
public boolean getDeleted() {
return this.mDeleted;
}

@ -74,47 +74,66 @@ public class SqlData {
}
private void loadFromCursor(Cursor c) {
// 从 Cursor 对象中获取列索引为 DATA_ID_COLUMN 的长整型数据,并将其赋值给当前对象的 mDataId 属性
mDataId = c.getLong(DATA_ID_COLUMN);
// 从 Cursor 对象中获取列索引为 DATA_MIME_TYPE_COLUMN 的字符串数据,并将其赋值给当前对象的 mDataMimeType 属性
mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN);
// 从 Cursor 对象中获取列索引为 DATA_CONTENT_COLUMN 的字符串数据,并将其赋值给当前对象的 mDataContent 属性
mDataContent = c.getString(DATA_CONTENT_COLUMN);
// 从 Cursor 对象中获取列索引为 DATA_CONTENT_DATA_1_COLUMN 的长整型数据,并将其赋值给当前对象的 mDataContentData1 属性
mDataContentData1 = c.getLong(DATA_CONTENT_DATA_1_COLUMN);
// 从 Cursor 对象中获取列索引为 DATA_CONTENT_DATA_3_COLUMN 的字符串数据,并将其赋值给当前对象的 mDataContentData3 属性
mDataContentData3 = c.getString(DATA_CONTENT_DATA_3_COLUMN);
}
public void setContent(JSONObject js) throws JSONException {
//如果传入的JSONObject对象中有DataColumns.ID这一项则设置否则设为INVALID_ID
// 如果传入的JSONObject对象中有DataColumns.ID这一项则设置否则设为INVALID_ID
long dataId = js.has(DataColumns.ID) ? js.getLong(DataColumns.ID) : INVALID_ID;
// 如果当前是新增操作或数据ID已发生变化将数据ID加入到待更新列表中
if (mIsCreate || mDataId != dataId) {
mDiffDataValues.put(DataColumns.ID, dataId);
}
// 更新当前数据ID
mDataId = dataId;
// 获取数据的MIME类型如果不存在则设置为DataConstants.NOTE
String dataMimeType = js.has(DataColumns.MIME_TYPE) ? js.getString(DataColumns.MIME_TYPE)
: DataConstants.NOTE;
// 如果当前是新增操作或数据的MIME类型已发生变化将MIME类型加入到待更新列表中
if (mIsCreate || !mDataMimeType.equals(dataMimeType)) {
mDiffDataValues.put(DataColumns.MIME_TYPE, dataMimeType);
}
// 更新当前数据的MIME类型
mDataMimeType = dataMimeType;
// 获取数据的内容,如果不存在则设置为空字符串
String dataContent = js.has(DataColumns.CONTENT) ? js.getString(DataColumns.CONTENT) : "";
// 如果当前是新增操作或数据的内容已发生变化,将数据内容加入到待更新列表中
if (mIsCreate || !mDataContent.equals(dataContent)) {
mDiffDataValues.put(DataColumns.CONTENT, dataContent);
}
// 更新当前数据的内容
mDataContent = dataContent;
// 获取数据的DATA1如果不存在则设置为0
long dataContentData1 = js.has(DataColumns.DATA1) ? js.getLong(DataColumns.DATA1) : 0;
// 如果当前是新增操作或数据的DATA1已发生变化将DATA1加入到待更新列表中
if (mIsCreate || mDataContentData1 != dataContentData1) {
mDiffDataValues.put(DataColumns.DATA1, dataContentData1);
}
// 更新当前数据的DATA1
mDataContentData1 = dataContentData1;
// 获取数据的DATA3如果不存在则设置为空字符串
String dataContentData3 = js.has(DataColumns.DATA3) ? js.getString(DataColumns.DATA3) : "";
// 如果当前是新增操作或数据的DATA3已发生变化将DATA3加入到待更新列表中
if (mIsCreate || !mDataContentData3.equals(dataContentData3)) {
mDiffDataValues.put(DataColumns.DATA3, dataContentData3);
}
// 更新当前数据的DATA3
mDataContentData3 = dataContentData3;
}
public JSONObject getContent() throws JSONException {//创建JSONObject对象。并将相关数据放入其中并返回
if (mIsCreate) {
Log.e(TAG, "it seems that we haven't created this in database yet");
@ -129,14 +148,15 @@ public class SqlData {
return js;
}
public void commit(long noteId, boolean validateVersion, long version) {//commit函数用于把当前造作所做的修改保存到数据库
public void commit(long noteId, boolean validateVersion, long version) {
// 如果是新建数据,则需要把 noteId 设置进去,并插入到数据库中
if (mIsCreate) {
if (mDataId == INVALID_ID && mDiffDataValues.containsKey(DataColumns.ID)) {
mDiffDataValues.remove(DataColumns.ID);
}
// 把 noteId 设置进去
mDiffDataValues.put(DataColumns.NOTE_ID, noteId);
// 插入到数据库中
Uri uri = mContentResolver.insert(Notes.CONTENT_DATA_URI, mDiffDataValues);
try {
mDataId = Long.valueOf(uri.getPathSegments().get(1));
@ -144,13 +164,14 @@ public class SqlData {
Log.e(TAG, "Get note id error :" + e.toString());
throw new ActionFailureException("create note failed");
}
} else {
} else { // 如果不是新建数据,则需要更新数据
if (mDiffDataValues.size() > 0) {
int result = 0;
// 如果不需要验证版本号,则直接更新数据库
if (!validateVersion) {
result = mContentResolver.update(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, null, null);
} else {
} else { // 如果需要验证版本号,则需要在更新前进行检查
result = mContentResolver.update(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues,
" ? in (SELECT " + NoteColumns.ID + " FROM " + TABLE.NOTE
@ -163,7 +184,7 @@ public class SqlData {
}
}
}
// 清空修改数据的 Map并标记为非新建数据
mDiffDataValues.clear();
mIsCreate = false;
}

@ -169,6 +169,15 @@ public class SqlNote {
}
}
//具体地说这个方法依次从Cursor对象中读取ID_COLUMN、ALERTED_DATE_COLUMN、BG_COLOR_ID_COLUMN、
//CREATED_DATE_COLUMN、HAS_ATTACHMENT_COLUMN、MODIFIED_DATE_COLUMN、PARENT_ID_COLUMN、SNIPPET_COLUMN、
//TYPE_COLUMN、WIDGET_ID_COLUMN、WIDGET_TYPE_COLUMN和VERSION_COLUMN对应的列的值
//并将这些值设置为该类的成员变量mId、mAlertDate、mBgColorId、mCreatedDate、mHasAttachment、mModifiedDate、
//mParentId、mSnippet、mType、mWidgetId、mWidgetType和mVersion的值。
// oadFromCursor方法是一个私有方法它有一个参数c该参数是一个Cursor对象。
// 这个方法的作用是从Cursor对象中读取数据并将其设置为该类的成员变量的值。
private void loadFromCursor(Cursor c) {
mId = c.getLong(ID_COLUMN);
mAlertDate = c.getLong(ALERTED_DATE_COLUMN);
@ -183,7 +192,7 @@ public class SqlNote {
mWidgetType = c.getInt(WIDGET_TYPE_COLUMN);
mVersion = c.getLong(VERSION_COLUMN);
}
//loadDataContent方法也是一个私有方法它不接受任何参数。这个方法的作用是从数据库中读取笔记的数据内容。
private void loadDataContent() {
Cursor c = null;
mDataList.clear();
@ -213,24 +222,26 @@ public class SqlNote {
public boolean setContent(JSONObject js) {
try {
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
// 获取JSON对象中META_HEAD_NOTE字段对应的JSONObject对象并赋值给note
if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) {
// 如果note的TYPE字段为TYPE_SYSTEM打印warning信息
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) : "";
// 如果note的TYPE字段为TYPE_FOLDER更新Java对象mSnippet和mType的值
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;
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) {
// 如果note的TYPE字段为TYPE_NOTE更新Java对象的各个字段值
JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
long id = note.has(NoteColumns.ID) ? note.getLong(NoteColumns.ID) : INVALID_ID;
if (mIsCreate || mId != id) {
@ -238,43 +249,37 @@ public class SqlNote {
}
mId = id;
long alertDate = note.has(NoteColumns.ALERTED_DATE) ? note
.getLong(NoteColumns.ALERTED_DATE) : 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;
int bgColorId = note.has(NoteColumns.BG_COLOR_ID) ? note
.getInt(NoteColumns.BG_COLOR_ID) : ResourceParser.getDefaultBgId(mContext);
int bgColorId = note.has(NoteColumns.BG_COLOR_ID) ? note.getInt(NoteColumns.BG_COLOR_ID) : ResourceParser.getDefaultBgId(mContext);
if (mIsCreate || mBgColorId != bgColorId) {
mDiffNoteValues.put(NoteColumns.BG_COLOR_ID, bgColorId);
}
mBgColorId = bgColorId;
long createDate = note.has(NoteColumns.CREATED_DATE) ? note
.getLong(NoteColumns.CREATED_DATE) : System.currentTimeMillis();
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;
int hasAttachment = note.has(NoteColumns.HAS_ATTACHMENT) ? note
.getInt(NoteColumns.HAS_ATTACHMENT) : 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;
long modifiedDate = note.has(NoteColumns.MODIFIED_DATE) ? note
.getLong(NoteColumns.MODIFIED_DATE) : System.currentTimeMillis();
long modifiedDate = note.has(NoteColumns.MODIFIED_DATE) ? note.getLong(NoteColumns.MODIFIED_DATE) : System.currentTimeMillis();
if (mIsCreate || mModifiedDate != modifiedDate) {
mDiffNoteValues.put(NoteColumns.MODIFIED_DATE, modifiedDate);
}
mModifiedDate = modifiedDate;
long parentId = note.has(NoteColumns.PARENT_ID) ? note
.getLong(NoteColumns.PARENT_ID) : 0;
long parentId = note.has(NoteColumns.PARENT_ID) ? note.getLong(NoteColumns.PARENT_ID) : 0;
if (mIsCreate || mParentId != parentId) {
mDiffNoteValues.put(NoteColumns.PARENT_ID, parentId);
}
@ -308,6 +313,12 @@ public class SqlNote {
}
mWidgetType = widgetType;
/* JSON
@param jsonData JSON
@return
*/
long originParent = note.has(NoteColumns.ORIGIN_PARENT_ID) ? note
.getLong(NoteColumns.ORIGIN_PARENT_ID) : 0;
if (mIsCreate || mOriginParent != originParent) {
@ -347,13 +358,14 @@ public class SqlNote {
try {
JSONObject js = new JSONObject();
if (mIsCreate) {
if (mIsCreate) { // 如果这个对象还没有被创建
Log.e(TAG, "it seems that we haven't created this in database yet");
return null;
}
// 创建一个名为 note 的 JSON 对象,并将这个对象的属性添加到里面
JSONObject note = new JSONObject();
if (mType == Notes.TYPE_NOTE) {
if (mType == Notes.TYPE_NOTE) { // 如果这个对象是一条笔记
note.put(NoteColumns.ID, mId);
note.put(NoteColumns.ALERTED_DATE, mAlertDate);
note.put(NoteColumns.BG_COLOR_ID, mBgColorId);
@ -366,8 +378,9 @@ public class SqlNote {
note.put(NoteColumns.WIDGET_ID, mWidgetId);
note.put(NoteColumns.WIDGET_TYPE, mWidgetType);
note.put(NoteColumns.ORIGIN_PARENT_ID, mOriginParent);
js.put(GTaskStringUtils.META_HEAD_NOTE, note);
js.put(GTaskStringUtils.META_HEAD_NOTE, note); // 将这个 JSON 对象添加到 js 中
// 创建一个名为 dataArray 的 JSON 数组,并将每个 SqlData 对象的 content 属性添加到里面
JSONArray dataArray = new JSONArray();
for (SqlData sqlData : mDataList) {
JSONObject data = sqlData.getContent();
@ -375,84 +388,85 @@ public class SqlNote {
dataArray.put(data);
}
}
js.put(GTaskStringUtils.META_HEAD_DATA, dataArray);
} else if (mType == Notes.TYPE_FOLDER || mType == Notes.TYPE_SYSTEM) {
js.put(GTaskStringUtils.META_HEAD_DATA, dataArray); // 将这个 JSON 数组添加到 js 中
} else if (mType == Notes.TYPE_FOLDER || mType == Notes.TYPE_SYSTEM) { // 如果这个对象是一个文件夹或者系统类型
note.put(NoteColumns.ID, mId);
note.put(NoteColumns.TYPE, mType);
note.put(NoteColumns.SNIPPET, mSnippet);
js.put(GTaskStringUtils.META_HEAD_NOTE, note);
js.put(GTaskStringUtils.META_HEAD_NOTE, note); // 将这个 JSON 对象添加到 js 中
}
return js;
return js; // 返回 JSON 对象
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
}
return null;
return null; // 如果出现异常返回 null
}
public void setParentId(long id) {
mParentId = id;
mDiffNoteValues.put(NoteColumns.PARENT_ID, id);
public void setParentId(long id) { //设置笔记的父笔记ID
mParentId = id; //保存父笔记ID
mDiffNoteValues.put(NoteColumns.PARENT_ID, id); //将更改的值加入到 mDiffNoteValues 中
}
public void setGtaskId(String gid) {
mDiffNoteValues.put(NoteColumns.GTASK_ID, gid);
public void setGtaskId(String gid) { //设置笔记的 Google 任务ID
mDiffNoteValues.put(NoteColumns.GTASK_ID, gid); //将更改的值加入到 mDiffNoteValues 中
}
public void setSyncId(long syncId) {
mDiffNoteValues.put(NoteColumns.SYNC_ID, syncId);
public void setSyncId(long syncId) { //设置笔记的同步ID
mDiffNoteValues.put(NoteColumns.SYNC_ID, syncId); //将更改的值加入到 mDiffNoteValues 中
}
public void resetLocalModified() {
mDiffNoteValues.put(NoteColumns.LOCAL_MODIFIED, 0);
public void resetLocalModified() { //重置本地修改状态
mDiffNoteValues.put(NoteColumns.LOCAL_MODIFIED, 0); //将更改的值加入到 mDiffNoteValues 中
}
public long getId() {
return mId;
public long getId() { //获取笔记ID
return mId; //返回笔记ID
}
public long getParentId() {
return mParentId;
public long getParentId() { //获取笔记的父笔记ID
return mParentId; //返回笔记的父笔记ID
}
public String getSnippet() {
return mSnippet;
public String getSnippet() { //获取笔记片段
return mSnippet; //返回笔记片段
}
public boolean isNoteType() {
return mType == Notes.TYPE_NOTE;
public boolean isNoteType() { //判断笔记是否为Note类型
return mType == Notes.TYPE_NOTE; //如果笔记类型是Note则返回true否则返回false
}
public void commit(boolean validateVersion) {
if (mIsCreate) {
public void commit(boolean validateVersion) { //提交更改,参数为是否校验版本号
if (mIsCreate) { //如果是新建笔记
if (mId == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) {
mDiffNoteValues.remove(NoteColumns.ID);
}
//插入新笔记
Uri uri = mContentResolver.insert(Notes.CONTENT_NOTE_URI, mDiffNoteValues);
try {
mId = Long.valueOf(uri.getPathSegments().get(1));
mId = Long.valueOf(uri.getPathSegments().get(1)); //获取新笔记ID
} catch (NumberFormatException e) {
Log.e(TAG, "Get note id error :" + e.toString());
throw new ActionFailureException("create note failed");
throw new ActionFailureException("create note failed"); //抛出异常,创建笔记失败
}
if (mId == 0) {
throw new IllegalStateException("Create thread id failed");
}
if (mType == Notes.TYPE_NOTE) {
if (mType == Notes.TYPE_NOTE) { //如果是笔记类型
for (SqlData sqlData : mDataList) {
sqlData.commit(mId, false, -1);
sqlData.commit(mId, false, -1); //保存笔记的数据
}
}
} else {
} else { //如果是更新已有笔记
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");
}
if (mDiffNoteValues.size() > 0) {
mVersion ++;
if (mDiffNoteValues.size() > 0) { //如果有更改需要提交
mVersion ++; //更新版本号
int result = 0;
if (!validateVersion) {
result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "("
@ -479,6 +493,7 @@ public class SqlNote {
}
// refresh local info
//loadFromCursor(mId) 方法是一个私有方法,它会查询指定 ID 的笔记记录,并将返回的 Cursor 对象的数据填充到NoteItem 的成员变量中
loadFromCursor(mId);
if (mType == Notes.TYPE_NOTE)
loadDataContent();

@ -35,62 +35,58 @@ import org.json.JSONObject;
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;
private boolean mCompleted; // 声明一个布尔类型的变量,表示任务是否已完成
private String mNotes; // 声明一个字符串类型的变量,表示任务的备注信息
private JSONObject mMetaInfo; // 声明一个JSONObject类型的变量表示任务的元信息
private Task mPriorSibling; // 声明一个Task类型的变量表示当前任务的上一个任务
private TaskList mParent; // 声明一个TaskList类型的变量表示当前任务所属的任务列表
public Task() {
super();
mCompleted = false;
mNotes = null;
mPriorSibling = null;
mParent = null;
mMetaInfo = null;
super(); // 调用父类的无参构造函数
mCompleted = false; // 初始化mCompleted为false
mNotes = null; // 初始化mNotes为null
mPriorSibling = null; // 初始化mPriorSibling为null
mParent = null; // 初始化mParent为null
mMetaInfo = null; // 初始化mMetaInfo为null
}
public JSONObject getCreateAction(int actionId) {
JSONObject js = new JSONObject();
JSONObject js = new JSONObject(); // 声明并初始化一个JSONObject对象
try {
// action_type
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE);
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE); // 将指定的键值对放入JSONObject对象中
// action_id
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); // 将指定的键值对放入JSONObject对象中
// index
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mParent.getChildTaskIndex(this));
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mParent.getChildTaskIndex(this)); // 将指定的键值对放入JSONObject对象中
// entity_delta
JSONObject entity = new JSONObject();
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null");
JSONObject entity = new JSONObject(); // 声明并初始化一个JSONObject对象
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); // 将指定的键值对放入JSONObject对象中
entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null"); // 将指定的键值对放入JSONObject对象中
entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE,
GTaskStringUtils.GTASK_JSON_TYPE_TASK);
if (getNotes() != null) {
entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes());
GTaskStringUtils.GTASK_JSON_TYPE_TASK); // 将指定的键值对放入JSONObject对象中
if (getNotes() != null) { // 如果任务备注信息不为空
entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes()); // 将指定的键值对放入JSONObject对象中
}
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); // 将指定的键值对放入JSONObject对象中
// parent_id
js.put(GTaskStringUtils.GTASK_JSON_PARENT_ID, mParent.getGid());
js.put(GTaskStringUtils.GTASK_JSON_PARENT_ID, mParent.getGid()); // 将指定的键值对放入JSONObject对象中
// dest_parent_type
js.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT_TYPE,
GTaskStringUtils.GTASK_JSON_TYPE_GROUP);
GTaskStringUtils.GTASK_JSON_TYPE_GROUP); // 将指定的键值对放入JSONObject对象中
// list_id
js.put(GTaskStringUtils.GTASK_JSON_LIST_ID, mParent.getGid());
js.put(GTaskStringUtils.GTASK_JSON_LIST_ID, mParent.getGid()); // 将指定的键值对放入JSONObject对象中
// prior_sibling_id
if (mPriorSibling != null) {
if (mPriorSibling != null) { // 如果当前任务的上一个任务不为空
js.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, mPriorSibling.getGid());
}
@ -102,7 +98,11 @@ public class Task extends Node {
return js;
}
/*getUpdateAction(int actionId)JSONObject
JSONObjectjsaction_typeID action_id
IDJSONObjectentityjs
JSONActionFailureException
*/
public JSONObject getUpdateAction(int actionId) {
JSONObject js = new JSONObject();
@ -134,7 +134,11 @@ public class Task extends Node {
return js;
}
/*setContentByRemoteJSON(JSONObject js)JSONObject
JSONObjectnullJSONObjectidlast_modifiedname
notesdeletedcompleted
JSONActionFailureException
*/
public void setContentByRemoteJSON(JSONObject js) {
if (js != null) {
try {
@ -176,20 +180,24 @@ public class Task extends Node {
}
public void setContentByLocalJSON(JSONObject js) {
// 检查传入的 JSON 对象是否合法
if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)
|| !js.has(GTaskStringUtils.META_HEAD_DATA)) {
Log.w(TAG, "setContentByLocalJSON: nothing is avaiable");
}
try {
// 获取元数据中的笔记和数据部分
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
// 检查笔记类型是否为 Notes.TYPE_NOTE
if (note.getInt(NoteColumns.TYPE) != Notes.TYPE_NOTE) {
Log.e(TAG, "invalid type");
return;
}
// 在数据部分中查找笔记内容
for (int i = 0; i < dataArray.length(); i++) {
JSONObject data = dataArray.getJSONObject(i);
if (TextUtils.equals(data.getString(DataColumns.MIME_TYPE), DataConstants.NOTE)) {
@ -208,12 +216,13 @@ public class Task extends Node {
String name = getName();
try {
if (mMetaInfo == null) {
// new task created from web
// 新任务从网络创建
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();
@ -225,10 +234,11 @@ 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);
// 在数据部分中查找笔记内容,并设置新名称
for (int i = 0; i < dataArray.length(); i++) {
JSONObject data = dataArray.getJSONObject(i);
if (TextUtils.equals(data.getString(DataColumns.MIME_TYPE), DataConstants.NOTE)) {
@ -237,6 +247,7 @@ public class Task extends Node {
}
}
// 设置笔记类型为 Notes.TYPE_NOTE
note.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
return mMetaInfo;
}
@ -246,7 +257,12 @@ public class Task extends Node {
return null;
}
}
/*
MetaData
metaData.getNotes()
metaDatanullmetaData.getNotes()nullJSONObjectmMetaInfo
mMetaInfonull
*/
public void setMetaInfo(MetaData metaData) {
if (metaData != null && metaData.getNotes() != null) {
try {
@ -257,7 +273,12 @@ public class Task extends Node {
}
}
}
/*
Cursor
noteInfonull
mMetaInfonullnoteInfomMetaInfoJSONObject
*/
public int getSyncAction(Cursor c) {
try {
JSONObject noteInfo = null;
@ -310,7 +331,16 @@ public class Task extends Node {
return SYNC_ACTION_ERROR;
}
/*isWorthSaving(): TaskmMetaInfonullnamenotestruefalse
setCompleted(boolean completed): Taskcompleted
setNotes(String notes): Tasknotes
setPriorSibling(Task priorSibling): TaskpriorSibling
setParent(TaskList parent): Taskparent
getCompleted(): Taskcompleted
getNotes(): Tasknotes
getPriorSibling(): TaskpriorSibling
getParent(): Taskparent
*/
public boolean isWorthSaving() {
return mMetaInfo != null || (getName() != null && getName().trim().length() > 0)
|| (getNotes() != null && getNotes().trim().length() > 0);

@ -29,20 +29,26 @@ import org.json.JSONObject;
import java.util.ArrayList;
//定义了一个名为TaskList的类并继承自Node类
public class TaskList extends Node {
//定义了一个名为TAG的静态字符串变量用于在日志中标记该类
private static final String TAG = TaskList.class.getSimpleName();
//定义了一个名为mIndex的整型变量用于表示任务列表的索引
private int mIndex;
//定义了一个名为mChildren的Task类型的ArrayList变量用于存储该任务列表的子任务。
private ArrayList<Task> mChildren;
//定义了一个无参构造函数初始化了mChildren变量和mIndex变量
public TaskList() {
super();
mChildren = new ArrayList<Task>();
mIndex = 1;
}
/* getCreateActionJSONObject
actionIdjsJSONObject
jsaction_typeaction_idindexentity_delta
entity_deltanamecreator_identity_type
jsActionFailureExceptionjs
*/
public JSONObject getCreateAction(int actionId) {
JSONObject js = new JSONObject();
@ -128,7 +134,15 @@ public class TaskList extends Node {
}
}
}
/*setContentByLocalJSON(JSONObject js)JSON
JSONGTaskStringUtils.META_HEAD_NOTE
JSONGTaskStringUtils.META_HEAD_NOTEJSONObject
JSONObjectNoteColumns.TYPENotes.TYPE_FOLDER
NoteColumns.SNIPPETsetName()
Notes.TYPE_SYSTEMNoteColumns.IDNotes.ID_ROOT_FOLDER
Notes.ID_CALL_RECORD_FOLDER
*/
public void setContentByLocalJSON(JSONObject js) {
if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)) {
Log.w(TAG, "setContentByLocalJSON: nothing is avaiable");
@ -156,7 +170,13 @@ public class TaskList extends Node {
e.printStackTrace();
}
}
/*getLocalJSONFromContent()JSONJSONObjectfolder
GTaskStringUtils.MIUI_FOLDER_PREFFIX
NoteColumns.SNIPPET
NoteColumns.TYPENotes.TYPE_SYSTEM
Notes.TYPE_FOLDERfolderMETA_HEAD_NOTEJSONObject
*/
public JSONObject getLocalJSONFromContent() {
try {
JSONObject js = new JSONObject();
@ -182,7 +202,14 @@ public class TaskList extends Node {
return null;
}
}
/*getSyncAction(Cursor c)
IDID
SYNC_ACTION_NONEIDSYNC_ACTION_UPDATE_LOCAL
gtask idIDSYNC_ACTION_ERROR
gtask idIDID
IDSYNC_ACTION_UPDATE_REMOTE
IDSYNC_ACTION_UPDATE_REMOTE
*/
public int getSyncAction(Cursor c) {
try {
if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) {
@ -215,11 +242,11 @@ public class TaskList extends Node {
return SYNC_ACTION_ERROR;
}
//getChildTaskCount(): 返回子任务的数量。
public int getChildTaskCount() {
return mChildren.size();
}
//addChildTask(Task task): 添加一个子任务。如果任务不为null且不在子任务列表中则添加到列表中并设置前一个兄弟和父任务。
public boolean addChildTask(Task task) {
boolean ret = false;
if (task != null && !mChildren.contains(task)) {
@ -233,7 +260,7 @@ public class TaskList extends Node {
}
return ret;
}
//添加一个子任务到特定的位置。如果位置无效则返回false。如果任务不为null且不在子任务列表中则添加到列表中并设置前一个
public boolean addChildTask(Task task, int index) {
if (index < 0 || index > mChildren.size()) {
Log.e(TAG, "add child task: invalid index");
@ -259,7 +286,7 @@ public class TaskList extends Node {
return true;
}
//从子任务列表中移除一个任务。如果任务不在列表中则返回false。否则从列表中移除任务并重置前一个兄弟和父任务。如果任务后面有其他任务则将它们的前一个兄弟设置为它的前一个兄弟。
public boolean removeChildTask(Task task) {
boolean ret = false;
int index = mChildren.indexOf(task);
@ -280,7 +307,7 @@ public class TaskList extends Node {
}
return ret;
}
// 移动一个任务到一个新的位置。如果索引无效则返回false。如果任务不在列表中则返回false。如果任务已经在目标位置则返回true。否则将任务从当前位置移除并添加到新位置。
public boolean moveChildTask(Task task, int index) {
if (index < 0 || index >= mChildren.size()) {
@ -298,7 +325,7 @@ public class TaskList extends Node {
return true;
return (removeChildTask(task) && addChildTask(task, index));
}
//根据GID查找一个子任务。如果找到则返回该任务否则返回null。
public Task findChildTaskByGid(String gid) {
for (int i = 0; i < mChildren.size(); i++) {
Task t = mChildren.get(i);
@ -308,11 +335,11 @@ public class TaskList extends Node {
}
return null;
}
//获取一个任务的索引。如果任务不在列表中,则返回-1。
public int getChildTaskIndex(Task task) {
return mChildren.indexOf(task);
}
//根据索引获取一个任务。如果索引无效则返回null。
public Task getChildTaskByIndex(int index) {
if (index < 0 || index >= mChildren.size()) {
Log.e(TAG, "getTaskByIndex: invalid index");
@ -320,7 +347,7 @@ public class TaskList extends Node {
}
return mChildren.get(index);
}
//根据GID获取一个任务。如果找到则返回该任务否则返回null。
public Task getChilTaskByGid(String gid) {
for (Task task : mChildren) {
if (task.getGid().equals(gid))
@ -328,15 +355,15 @@ public class TaskList extends Node {
}
return null;
}
//获取子任务列表。
public ArrayList<Task> getChildTaskList() {
return this.mChildren;
}
//设置任务的索引
public void setIndex(int index) {
this.mIndex = index;
}
//设置任务的索引
public int getIndex() {
return this.mIndex;
}

@ -15,7 +15,7 @@
*/
package net.micode.notes.gtask.exception;
//ActionFailureException 继承自 RuntimeException通常用于表示在执行某个操作时发生了异常或错误
public class ActionFailureException extends RuntimeException {
private static final long serialVersionUID = 4425249765923293627L;

@ -15,7 +15,7 @@
*/
package net.micode.notes.gtask.exception;
//NetworkFailureException 继承自 Exception通常用于表示网络相关的异常或错误。
public class NetworkFailureException extends Exception {
private static final long serialVersionUID = 2107610287180234136L;

@ -28,15 +28,15 @@ import net.micode.notes.R;
import net.micode.notes.ui.NotesListActivity;
import net.micode.notes.ui.NotesPreferenceActivity;
//定义了一个类GTaskASyncTask继承自AsyncTask类。AsyncTask是一个抽象类定义了异步任务的处理流程开发者需要实现其抽象方法来处理具体的任务。
public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
//定义一个静态的通知ID
private static int GTASK_SYNC_NOTIFICATION_ID = 5234235;
//定义一个接口OnCompleteListener包含一个方法onComplete()。在任务完成时调用该接口的onComplete()方法,通知任务执行完毕。
public interface OnCompleteListener {
void onComplete();
}
//定义了一些成员变量,包括上下文、通知管理器、任务管理器和任务完成的监听器。
private Context mContext;
private NotificationManager mNotifiManager;
@ -44,7 +44,7 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
private GTaskManager mTaskManager;
private OnCompleteListener mOnCompleteListener;
//构造函数,初始化类中的成员变量。
public GTaskASyncTask(Context context, OnCompleteListener listener) {
mContext = context;
mOnCompleteListener = listener;
@ -52,17 +52,20 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
.getSystemService(Context.NOTIFICATION_SERVICE);
mTaskManager = GTaskManager.getInstance();
}
//定义了cancelSync()方法,用于取消同步任务
public void cancelSync() {
mTaskManager.cancelSync();
}
//定义了publishProgess()方法,用于发布同步进度。
public void publishProgess(String message) {
publishProgress(new String[] {
message
});
}
/*showNotification()tickerId
contentNotification
tickerIdPendingIntentNotificationManagernotify()
*/
private void showNotification(int tickerId, String content) {
Notification notification = new Notification(R.drawable.notification, mContext
.getString(tickerId), System.currentTimeMillis());
@ -83,6 +86,7 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
}
@Override
//doInBackground() 方法是在新的线程中执行的,主要是用来执行耗时操作。在这里,它调用了 publishProgress() 方法来通知 UI 线程更新进度,然后调用了 mTaskManager.sync() 方法来进行同步操作。
protected Integer doInBackground(Void... unused) {
publishProgess(mContext.getString(R.string.sync_progress_login, NotesPreferenceActivity
.getSyncAccountName(mContext)));
@ -90,6 +94,7 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
}
@Override
//onProgressUpdate() 方法在 UI 线程中执行,它用来更新 UI。在这里它调用了 showNotification() 方法来显示通知,并且如果当前的 mContext 对象是 GTaskSyncService 的实例,它还会发送一个广播
protected void onProgressUpdate(String... progress) {
showNotification(R.string.ticker_syncing, progress[0]);
if (mContext instanceof GTaskSyncService) {
@ -98,6 +103,10 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
}
@Override
/*onPostExecute() UI 线
mTaskManager.sync() showNotification() mOnCompleteListener null
线 mOnCompleteListener.onComplete()
*/
protected void onPostExecute(Integer result) {
if (result == GTaskManager.STATE_SUCCESS) {
showNotification(R.string.ticker_success, mContext.getString(

@ -64,30 +64,40 @@ import java.util.zip.InflaterInputStream;
public class GTaskClient {
private static final String TAG = GTaskClient.class.getSimpleName();
// Google任务的URL
private static final String GTASK_URL = "https://mail.google.com/tasks/";
// Google任务的获取URL
private static final String GTASK_GET_URL = "https://mail.google.com/tasks/ig";
// Google任务的发布URL
private static final String GTASK_POST_URL = "https://mail.google.com/tasks/r/ig";
private static GTaskClient mInstance = null;
// Http客户端
private DefaultHttpClient mHttpClient;
private String mGetUrl;
private String mPostUrl;
// 客户端版本号
private long mClientVersion;
// 是否已登录
private boolean mLoggedin;
// 上次登录时间
private long mLastLoginTime;
// 操作ID
private int mActionId;
// 账户信息
private Account mAccount;
// 更新任务的JSONArray
private JSONArray mUpdateArray;
private GTaskClient() {
@ -110,14 +120,13 @@ public class GTaskClient {
}
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))) {
@ -129,14 +138,17 @@ public class GTaskClient {
return true;
}
// 记录上次登录时间
mLastLoginTime = System.currentTimeMillis();
// 登录Google账户
String authToken = loginGoogleAccount(activity, false);
if (authToken == null) {
Log.e(TAG, "login google account failed");
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/");
@ -151,7 +163,7 @@ public class GTaskClient {
}
}
// try to login with google official url
// 尝试使用Google官方URL登录
if (!mLoggedin) {
mGetUrl = GTASK_GET_URL;
mPostUrl = GTASK_POST_URL;
@ -159,24 +171,27 @@ public class GTaskClient {
return false;
}
}
mLoggedin = true;
return true;
}
private String loginGoogleAccount(Activity activity, boolean invalidateToken) {
String authToken;
// 从 Google 帐户管理器中获取指定类型的所有帐户
AccountManager accountManager = AccountManager.get(activity);
Account[] accounts = accountManager.getAccountsByType("com.google");
// 如果没有 Google 帐户,则返回 null
if (accounts.length == 0) {
Log.e(TAG, "there is no available google account");
return null;
}
// 从应用程序设置中获取帐户名称
String accountName = NotesPreferenceActivity.getSyncAccountName(activity);
Account account = null;
for (Account a : accounts) {
// 如果帐户名与应用程序设置中的帐户名称匹配,则使用该帐户
if (a.name.equals(accountName)) {
account = a;
break;
@ -185,38 +200,44 @@ public class GTaskClient {
if (account != null) {
mAccount = account;
} else {
// 如果无法获取与应用程序设置中的帐户名称匹配的帐户,则返回 null
Log.e(TAG, "unable to get an account with the same name in the settings");
return null;
}
// get the token now
// 现在获取令牌
AccountManagerFuture<Bundle> accountManagerFuture = accountManager.getAuthToken(account,
"goanna_mobile", null, activity, null, null);
try {
Bundle authTokenBundle = accountManagerFuture.getResult();
// 获取令牌字符串
authToken = authTokenBundle.getString(AccountManager.KEY_AUTHTOKEN);
// 如果需要使令牌无效,则使其无效并重新登录
if (invalidateToken) {
accountManager.invalidateAuthToken("com.google", authToken);
loginGoogleAccount(activity, false);
}
} catch (Exception e) {
// 如果无法获取令牌,则返回 null
Log.e(TAG, "get auth token failed");
authToken = null;
}
// 返回令牌字符串
return authToken;
}
// 尝试使用给定的令牌登录到 Gtask
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");
return false;
}
// 如果新的令牌也无法登录,则返回 false
if (!loginGtask(authToken)) {
Log.e(TAG, "login gtask failed");
return false;
@ -225,7 +246,9 @@ public class GTaskClient {
return true;
}
// 使用给定的令牌登录到 Gtask
private boolean loginGtask(String authToken) {
// 设置 HTTP 连接和套接字超时时间
int timeoutConnection = 10000;
int timeoutSocket = 15000;
HttpParams httpParameters = new BasicHttpParams();
@ -238,12 +261,14 @@ public class GTaskClient {
// login gtask
try {
// 构造登录URL
String loginUrl = mGetUrl + "?auth=" + authToken;
// 创建一个 HTTP GET 请求
HttpGet httpGet = new HttpGet(loginUrl);
HttpResponse response = null;
response = mHttpClient.execute(httpGet);
// 发送请求并获取响应
HttpResponse response = mHttpClient.execute(httpGet);
// get the cookie now
// 获取响应中的 cookie
List<Cookie> cookies = mHttpClient.getCookieStore().getCookies();
boolean hasAuthCookie = false;
for (Cookie cookie : cookies) {
@ -255,7 +280,7 @@ public class GTaskClient {
Log.w(TAG, "it seems that there is no auth cookie");
}
// get the client version
// 获取客户端版本号
String resString = getResponseContent(response.getEntity());
String jsBegin = "_setup(";
String jsEnd = ")}</script>";
@ -277,20 +302,21 @@ public class GTaskClient {
return false;
}
// 返回值为 true 表示请求成功
return true;
}
//这是一个私有方法返回一个自增的整数值即操作ID。在应用程序中每个HTTP请求都有一个唯一的操作ID用于跟踪该请求。
private int getActionId() {
return mActionId++;
}
//这个方法返回一个HttpPost对象该对象具有两个请求头Content-Type和AT。Content-Type指定请求正文的媒体类型AT是一个自定义请求头表示访问令牌
private HttpPost createHttpPost() {
HttpPost httpPost = new HttpPost(mPostUrl);
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
httpPost.setHeader("AT", "1");
return httpPost;
}
//这个方法返回HTTP响应实体的内容。它首先检查响应实体的内容编码是否为gzip或deflate并相应地创建一个解压缩输入流。然后它使用InputStreamReader和BufferedReader逐行读取响应实体的内容并将其添加到StringBuilder中。最后返回StringBuilder的字符串表示形式
private String getResponseContent(HttpEntity entity) throws IOException {
String contentEncoding = null;
if (entity.getContentEncoding() != null) {
@ -323,23 +349,30 @@ public class GTaskClient {
}
}
/**
* HTTP POSTGoogleAPIJSON
*
* @param js JSONJSONObject
* @return JSONObject
* @throws NetworkFailureException NetworkFailureException
*/
private JSONObject postRequest(JSONObject js) throws NetworkFailureException {
if (!mLoggedin) {
if (!mLoggedin) { // 如果未登录,则抛出异常
Log.e(TAG, "please login first");
throw new ActionFailureException("not logged in");
}
HttpPost httpPost = createHttpPost();
HttpPost httpPost = createHttpPost(); // 创建HttpPost对象
try {
LinkedList<BasicNameValuePair> list = new LinkedList<BasicNameValuePair>();
list.add(new BasicNameValuePair("r", js.toString()));
list.add(new BasicNameValuePair("r", js.toString())); // 将JSON数据作为参数添加到HttpPost对象中
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8");
httpPost.setEntity(entity);
httpPost.setEntity(entity); // 设置HttpPost对象的实体
// execute the post
HttpResponse response = mHttpClient.execute(httpPost);
String jsString = getResponseContent(response.getEntity());
return new JSONObject(jsString);
// 执行HttpPost请求
HttpResponse response = mHttpClient.execute(httpPost); // 发送HttpPost请求并接收响应
String jsString = getResponseContent(response.getEntity()); // 获取响应的实体内容
return new JSONObject(jsString); // 将响应的实体内容转换为JSONObject对象并返回
} catch (ClientProtocolException e) {
Log.e(TAG, e.toString());
@ -360,20 +393,26 @@ public class GTaskClient {
}
}
/**
*
*
* @param task
* @throws NetworkFailureException NetworkFailureException
*/
public void createTask(Task task) throws NetworkFailureException {
commitUpdate();
commitUpdate(); // 提交更改
try {
JSONObject jsPost = new JSONObject();
JSONArray actionList = new JSONArray();
// action_list
// 添加“创建任务”操作到操作列表中
actionList.put(task.getCreateAction(getActionId()));
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
// client_version
// 将操作列表和客户端版本添加到jsPost对象中
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
// post
// 发送HttpPost请求并从响应中获取新任务的ID并将其设置到任务对象中
JSONObject jsResponse = postRequest(jsPost);
JSONObject jsResult = (JSONObject) jsResponse.getJSONArray(
GTaskStringUtils.GTASK_JSON_RESULTS).get(0);
@ -385,10 +424,10 @@ public class GTaskClient {
throw new ActionFailureException("create task: handing jsonobject failed");
}
}
//createTaskList 方法创建一个新的任务列表
public void createTaskList(TaskList tasklist) throws NetworkFailureException {
commitUpdate();
try {
try {//JSONObject 和 JSONArray 是 Java 中的 JSON 对象和数组getActionId() 方法返回任务的 ID。
JSONObject jsPost = new JSONObject();
JSONArray actionList = new JSONArray();
@ -400,21 +439,25 @@ public class GTaskClient {
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
// post
//postRequest 方法向服务器发送请求并返回响应的 JSON 对象。
JSONObject jsResponse = postRequest(jsPost);
JSONObject jsResult = (JSONObject) jsResponse.getJSONArray(
GTaskStringUtils.GTASK_JSON_RESULTS).get(0);
tasklist.setGid(jsResult.getString(GTaskStringUtils.GTASK_JSON_NEW_ID));
} catch (JSONException e) {
//JSONException 是在处理 JSON 时可能出现的异常。
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("create tasklist: handing jsonobject failed");
}
}
}//JSONException 是在处理 JSON 时可能出现的异常。
//commitUpdate 方法提交之前对任务列表的修改
public void commitUpdate() throws NetworkFailureException {
if (mUpdateArray != null) {
//if 语句检查是否存在要提交的更新
try {
//mUpdateArray 是一个 JSONArray 对象,包含要提交的更新操作。
JSONObject jsPost = new JSONObject();
// action_list
@ -423,7 +466,7 @@ public class GTaskClient {
// client_version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
postRequest(jsPost);
postRequest(jsPost);//postRequest 方法向服务器发送请求并返回响应的 JSON 对象
mUpdateArray = null;
} catch (JSONException e) {
Log.e(TAG, e.toString());
@ -432,13 +475,13 @@ public class GTaskClient {
}
}
}
//addUpdateNode 方法向任务列表中添加一个更新操作。
public void addUpdateNode(Node node) throws NetworkFailureException {
if (node != null) {
// too many update items may result in an error
// set max to 10 items
// set max to 10 itemsmUpdateArray.length() > 10 判断要提交的更新操作数量是否超过 10 个。
if (mUpdateArray != null && mUpdateArray.length() > 10) {
commitUpdate();
commitUpdate();//commitUpdate() 方法提交之前对任务列表的修改。
}
if (mUpdateArray == null)
@ -446,7 +489,7 @@ public class GTaskClient {
mUpdateArray.put(node.getUpdateAction(getActionId()));
}
}
//在 moveTask 方法中,首先调用了 commitUpdate 方法,然后创建了一个 JSON 对象 jsPost它包含一个 JSON 数组 actionList
public void moveTask(Task task, TaskList preParent, TaskList curParent)
throws NetworkFailureException {
commitUpdate();
@ -485,7 +528,7 @@ public class GTaskClient {
throw new ActionFailureException("move task: handing jsonobject failed");
}
}
//在 deleteNode 方法中,也调用了 commitUpdate 方法,然后创建了一个 JSON 对象 jsPost它包含一个 JSON 数组 actionList。然后将 node 对象的 deleted 属性设置为 true并将其 updateAction 添加到 actionList 中。最后,将客户端版本设置为 jsPost 对象的属性,并使用 postRequest 方法将其发送到 Google Tasks API。如果出现任何异常则会抛出 ActionFailureException
public void deleteNode(Node node) throws NetworkFailureException {
commitUpdate();
try {

@ -22,8 +22,9 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
//定义一个继承自 Service 的服务类 GTaskSyncService
public class GTaskSyncService extends Service {
//定义一些常量,其中 ACTION_STRING_NAME 是字符串类型的常量表示同步操作的类型ACTION_START_SYNC 和 ACTION_CANCEL_SYNC 是整型常量分别表示开始同步和取消同步操作的类型ACTION_INVALID 表示无效操作的类型。
public final static String ACTION_STRING_NAME = "sync_action_type";
public final static int ACTION_START_SYNC = 0;
@ -37,11 +38,11 @@ public class GTaskSyncService extends Service {
public final static String GTASK_SERVICE_BROADCAST_IS_SYNCING = "isSyncing";
public final static String GTASK_SERVICE_BROADCAST_PROGRESS_MSG = "progressMsg";
//定义静态变量 mSyncTask 和 mSyncProgress分别表示当前的同步任务和同步进度。
private static GTaskASyncTask mSyncTask = null;
private static String mSyncProgress = "";
//定义 startSync 方法,用于开始同步任务。如果当前没有正在运行的同步任务,那么创建一个新的 GTaskASyncTask 异步任务并执行,执行完成后发送广播并停止当前服务。
private void startSync() {
if (mSyncTask == null) {
mSyncTask = new GTaskASyncTask(this, new GTaskASyncTask.OnCompleteListener() {
@ -55,19 +56,20 @@ public class GTaskSyncService extends Service {
mSyncTask.execute();
}
}
//取消正在运行的同步任务
private void cancelSync() {
if (mSyncTask != null) {
mSyncTask.cancelSync();
}
}
//重写 onCreate 方法,在服务创建时将 mSyncTask 置为 null
@Override
public void onCreate() {
mSyncTask = null;
}
@Override
//重写 onStartCommand 方法,处理服务的启动命令。如果启动命令中包含同步操作的类型,
public int onStartCommand(Intent intent, int flags, int startId) {
Bundle bundle = intent.getExtras();
if (bundle != null && bundle.containsKey(ACTION_STRING_NAME)) {
@ -87,16 +89,17 @@ public class GTaskSyncService extends Service {
}
@Override
//onLowMemory() 方法在系统内存不足时被调用,可以在此方法中释放一些占用内存的资源。在这里,如果 mSyncTask 不为空,则调用其 cancelSync() 方法取消同步任务。
public void onLowMemory() {
if (mSyncTask != null) {
mSyncTask.cancelSync();
}
}
//onBind(Intent intent) 方法是 Service 的一个回调方法,用于绑定服务。这个方法的实现在本例中返回 null表示这个 Service 不支持绑定。
public IBinder onBind(Intent intent) {
return null;
}
//sendBroadcast(String msg) 方法将同步进度信息通过广播的形式发送出去。这里将 mSyncProgress 赋值为 msg并创建一个 Intent 对象,设置 action 为 GTASK_SERVICE_BROADCAST_NAME 常量。然后将 mSyncTask 是否为空和 mSyncProgress 信息放到 Intent 中,调用 sendBroadcast() 方法发送广播
public void sendBroadcast(String msg) {
mSyncProgress = msg;
Intent intent = new Intent(GTASK_SERVICE_BROADCAST_NAME);
@ -104,24 +107,24 @@ public class GTaskSyncService extends Service {
intent.putExtra(GTASK_SERVICE_BROADCAST_PROGRESS_MSG, msg);
sendBroadcast(intent);
}
//startSync(Activity activity) 方法用于启动同步任务。首先通过 GTaskManager.getInstance() 获取 GTaskManager 实例,然后设置其 ActivityContext 为传入的 activity 参数。接着创建一个 Intent 对象,设置其目标服务为 GTaskSyncService并将 ACTION_STRING_NAME 常量和 ACTION_START_SYNC 常量放到 Intent 中。最后调用 activity 的 startService() 方法启动服务。
public static void startSync(Activity activity) {
GTaskManager.getInstance().setActivityContext(activity);
Intent intent = new Intent(activity, GTaskSyncService.class);
intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_START_SYNC);
activity.startService(intent);
}
//cancelSync(Context context) 方法用于取消同步任务。创建一个 Intent 对象,设置其目标服务为 GTaskSyncService并将 ACTION_STRING_NAME 常量和 ACTION_CANCEL_SYNC 常量放到 Intent 中。最后调用 context 的 startService() 方法启动服务。
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);
}
//isSyncing() 方法用于判断是否正在进行同步任务。直接返回 mSyncTask 是否为空的结果。
public static boolean isSyncing() {
return mSyncTask != null;
}
//isSyncing() 方法用于判断是否正在进行同步任务。直接返回 mSyncTask 是否为空的结果。
public static String getProgressString() {
return mSyncProgress;
}

Loading…
Cancel
Save