diff --git a/src/Notes-master/.idea/caches/build_file_checksums.ser b/src/Notes-master/.idea/caches/build_file_checksums.ser
deleted file mode 100644
index db95d16..0000000
Binary files a/src/Notes-master/.idea/caches/build_file_checksums.ser and /dev/null differ
diff --git a/src/Notes-master/.idea/markdown-navigator-enh.xml b/src/Notes-master/.idea/markdown-navigator-enh.xml
new file mode 100644
index 0000000..a8fcc84
--- /dev/null
+++ b/src/Notes-master/.idea/markdown-navigator-enh.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Notes-master/.idea/markdown-navigator.xml b/src/Notes-master/.idea/markdown-navigator.xml
new file mode 100644
index 0000000..57b84e5
--- /dev/null
+++ b/src/Notes-master/.idea/markdown-navigator.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Notes-master/.idea/modules/Notes-master.iml b/src/Notes-master/.idea/modules/Notes-master.iml
index 21ca423..7ec378f 100644
--- a/src/Notes-master/.idea/modules/Notes-master.iml
+++ b/src/Notes-master/.idea/modules/Notes-master.iml
@@ -17,4 +17,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/Notes-master/.idea/modules/app/Notes-master.app.iml b/src/Notes-master/.idea/modules/app/Notes-master.app.iml
index e9f35bf..87830b7 100644
--- a/src/Notes-master/.idea/modules/app/Notes-master.app.iml
+++ b/src/Notes-master/.idea/modules/app/Notes-master.app.iml
@@ -50,4 +50,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/Notes-master/.idea/sonarIssues.xml b/src/Notes-master/.idea/sonarIssues.xml
new file mode 100644
index 0000000..465ef5e
--- /dev/null
+++ b/src/Notes-master/.idea/sonarIssues.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Notes-master/.idea/sonarlint/issuestore/3/a/3aac5305cb73bfbdeb8078cd264d04323fa80e92 b/src/Notes-master/.idea/sonarlint/issuestore/3/a/3aac5305cb73bfbdeb8078cd264d04323fa80e92
new file mode 100644
index 0000000..e69de29
diff --git a/src/Notes-master/.idea/sonarlint/issuestore/9/3/934a4e2abf19d28a53f6aeb1dcd99248c44b6892 b/src/Notes-master/.idea/sonarlint/issuestore/9/3/934a4e2abf19d28a53f6aeb1dcd99248c44b6892
new file mode 100644
index 0000000..a0df7ff
--- /dev/null
+++ b/src/Notes-master/.idea/sonarlint/issuestore/9/3/934a4e2abf19d28a53f6aeb1dcd99248c44b6892
@@ -0,0 +1,5 @@
+
+2
+java:S2386,"Make this member "protected".(X
+n
+java:S3776"RRefactor this method to reduce its Cognitive Complexity from 16 to the 15 allowed.(
\ No newline at end of file
diff --git a/src/Notes-master/.idea/sonarlint/issuestore/c/1/c182d0c9c237ea8a46a92ccaae9bb5c751923a88 b/src/Notes-master/.idea/sonarlint/issuestore/c/1/c182d0c9c237ea8a46a92ccaae9bb5c751923a88
new file mode 100644
index 0000000..fd4c7f2
--- /dev/null
+++ b/src/Notes-master/.idea/sonarlint/issuestore/c/1/c182d0c9c237ea8a46a92ccaae9bb5c751923a88
@@ -0,0 +1,3 @@
+
+[
+java:S1124"EReorder the modifiers to comply with the Java Language Specification.(
\ No newline at end of file
diff --git a/src/Notes-master/.idea/sonarlint/issuestore/d/1/d187f1271655c3d91661a39fe6de395b6a9f290a b/src/Notes-master/.idea/sonarlint/issuestore/d/1/d187f1271655c3d91661a39fe6de395b6a9f290a
new file mode 100644
index 0000000..f59a333
--- /dev/null
+++ b/src/Notes-master/.idea/sonarlint/issuestore/d/1/d187f1271655c3d91661a39fe6de395b6a9f290a
@@ -0,0 +1,3 @@
+
+i
+java:S3776"RRefactor this method to reduce its Cognitive Complexity from 16 to the 15 allowed.(ǎ
\ No newline at end of file
diff --git a/src/Notes-master/.idea/sonarlint/issuestore/e/0/e094aec5c3e1b6f44539adff3114f5a1ad603ddc b/src/Notes-master/.idea/sonarlint/issuestore/e/0/e094aec5c3e1b6f44539adff3114f5a1ad603ddc
new file mode 100644
index 0000000..75d7970
--- /dev/null
+++ b/src/Notes-master/.idea/sonarlint/issuestore/e/0/e094aec5c3e1b6f44539adff3114f5a1ad603ddc
@@ -0,0 +1,8 @@
+
+r
+java:S3923"[Remove this conditional structure or edit its code blocks so that they're not all the same.(ԡ
+
+java:S1319"pThe return type of this method should be an interface such as "List" rather than the implementation "ArrayList".(ﷺ
+t
+java:S2293*"YReplace the type specification in this constructor call with the diamond operator ("<>").(ʩ
+Y java:S125"").(
+u
+java:S2293"YReplace the type specification in this constructor call with the diamond operator ("<>").(
+n
+java:S3776"RRefactor this method to reduce its Cognitive Complexity from 91 to the 15 allowed.(
+2
+java:S2386."Make this member "protected".(u
+u
+java:S2293"YReplace the type specification in this constructor call with the diamond operator ("<>").(
\ No newline at end of file
diff --git a/src/Notes-master/.idea/sonarlint/issuestore/f/4/f4a01d6a4fcb971362ec00a83903fd3902f52164 b/src/Notes-master/.idea/sonarlint/issuestore/f/4/f4a01d6a4fcb971362ec00a83903fd3902f52164
new file mode 100644
index 0000000..e69de29
diff --git a/src/Notes-master/.idea/sonarlint/issuestore/index.pb b/src/Notes-master/.idea/sonarlint/issuestore/index.pb
new file mode 100644
index 0000000..b513b71
--- /dev/null
+++ b/src/Notes-master/.idea/sonarlint/issuestore/index.pb
@@ -0,0 +1,15 @@
+
+@
+app/build.gradle,f\4\f4a01d6a4fcb971362ec00a83903fd3902f52164
+k
+;app/src/main/java/net/micode/notes/gtask/data/MetaData.java,c\1\c182d0c9c237ea8a46a92ccaae9bb5c751923a88
+g
+7app/src/main/java/net/micode/notes/gtask/data/Node.java,3\a\3aac5305cb73bfbdeb8078cd264d04323fa80e92
+j
+:app/src/main/java/net/micode/notes/gtask/data/SqlData.java,9\3\934a4e2abf19d28a53f6aeb1dcd99248c44b6892
+j
+:app/src/main/java/net/micode/notes/gtask/data/SqlNote.java,f\1\f1226eeacd46c914d51f3d1a6d6f27377490d2a4
+g
+7app/src/main/java/net/micode/notes/gtask/data/Task.java,d\1\d187f1271655c3d91661a39fe6de395b6a9f290a
+k
+;app/src/main/java/net/micode/notes/gtask/data/TaskList.java,e\0\e094aec5c3e1b6f44539adff3114f5a1ad603ddc
\ No newline at end of file
diff --git a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/MetaData.java b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/MetaData.java
index 3a2050b..9250255 100644
--- a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/MetaData.java
+++ b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/MetaData.java
@@ -24,39 +24,51 @@ import net.micode.notes.tool.GTaskStringUtils;
import org.json.JSONException;
import org.json.JSONObject;
-
+// 功能描述:主要是描述数据属性(property)的信息,用来支持例如指示存储位置、历史数据、资源查找、文件记录等功能。
+//实现:继承task类,用于记录数据的变化
public class MetaData extends Task {
+ // 调用getSimpleName ()函数得到类的简写名称存入字符串TAG中
private final static String TAG = MetaData.class.getSimpleName();
-
+ // 相关GID文件 (GID文件用来保存帮助文件的信息)
private String mRelatedGid = null;
-
+ // 调用JSONObject库函数put (),Task类中的setNotes ()和setName ()函数,实现设置数据,即生成元数据库
public void setMeta(String gid, JSONObject metaInfo) {
try {
+ // 将这对键值放入metaInfo这个jsonobject对象中
metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid);
+ // 捕捉异常放入TAG
} catch (JSONException e) {
Log.e(TAG, "failed to put related gid");
}
+ // 设置便签,将json类的metainfo转换为String
setNotes(metaInfo.toString());
+ // 设置gtask名字
setName(GTaskStringUtils.META_NOTE_NAME);
}
-
+ // 获取相关联的Gid
public String getRelatedGid() {
return mRelatedGid;
}
@Override
+ //判断是否值得存放,即当前数据是否有效,若数据非空则返回真值
public boolean isWorthSaving() {
return getNotes() != null;
}
@Override
+ //功能:使用远程json数据对象设置元数据内容
+ //实现:调用父类Task中的setContentByRemoteJSON ()函数,如果获取的notes非空,则去掉获取notes的空格后存入metaInfo中,并从metaInfo获取键值来获取相关gid;如果为空,则抛出异常
+ //参数:js属于JSONObject类,属于远程的数据
public void setContentByRemoteJSON(JSONObject js) {
+ //普通的直接引用。与this类似,super相当于是指向当前对象的父类,这样就可以用super.xxx来引用父类的成员。
super.setContentByRemoteJSON(js);
if (getNotes() != null) {
try {
JSONObject metaInfo = new JSONObject(getNotes().trim());
mRelatedGid = metaInfo.getString(GTaskStringUtils.META_HEAD_GTASK_ID);
} catch (JSONException e) {
+ // 输出异常
Log.w(TAG, "failed to get related gid");
mRelatedGid = null;
}
@@ -64,17 +76,20 @@ public class MetaData extends Task {
}
@Override
+ //功能:使用本地json数据对象设置元数据内容,一般不会用到,若用到,则抛出异常
public void setContentByLocalJSON(JSONObject js) {
// this function should not be called
throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called");
}
@Override
+ // 功能:从元数据内容中获取本地json对象,一般不会用到,若用到,则抛出异常
public JSONObject getLocalJSONFromContent() {
throw new IllegalAccessError("MetaData:getLocalJSONFromContent should not be called");
}
@Override
+ // 功能:获取同步动作状态,一般不会用到,若用到,则抛出异常
public int getSyncAction(Cursor c) {
throw new IllegalAccessError("MetaData:getSyncAction should not be called");
}
diff --git a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/Node.java b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/Node.java
index 63950e0..88eaa20 100644
--- a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/Node.java
+++ b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/Node.java
@@ -20,6 +20,7 @@ import android.database.Cursor;
import org.json.JSONObject;
+// 建立node类来提供模板,设置各种参数及定义各种函数,会在别的地方用到,定义了各种同步活动的标识码
public abstract class Node {
public static final int SYNC_ACTION_NONE = 0;
@@ -46,14 +47,14 @@ public abstract class Node {
private long mLastModified;
private boolean mDeleted;
-
+ //实现:设置mgid为空,名字为空,最后一次修改时间为0(没有修改),mDeleted为false表示未删除。
public Node() {
mGid = null;
mName = "";
mLastModified = 0;
mDeleted = false;
}
-
+ // 创建JSONObject对象,创建操作和更新操作,参数为int actionid
public abstract JSONObject getCreateAction(int actionId);
public abstract JSONObject getUpdateAction(int actionId);
diff --git a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/SqlData.java b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/SqlData.java
index d3ec3be..5c4f186 100644
--- a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/SqlData.java
+++ b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/SqlData.java
@@ -36,6 +36,7 @@ import org.json.JSONObject;
public class SqlData {
+ //调用getSimpleName ()函数将类的简写名称存入string类型变量TAG中
private static final String TAG = SqlData.class.getSimpleName();
private static final int INVALID_ID = -99999;
@@ -70,7 +71,8 @@ public class SqlData {
private String mDataContentData3;
private ContentValues mDiffDataValues;
-
+ //功能:第一种构造函数,初始化
+ //参数:类型为context,从上下文获取,初始化其中变量
public SqlData(Context context) {
mContentResolver = context.getContentResolver();
mIsCreate = true;
@@ -81,14 +83,17 @@ public class SqlData {
mDataContentData3 = "";
mDiffDataValues = new ContentValues();
}
-
+ //功能:第二中构造函数,初始化
+ //实现:通过游标cursor c来获取数据,进行替换
+ //参数:游标c是将传进来的参数替换掉初始的数值
public SqlData(Context context, Cursor c) {
mContentResolver = context.getContentResolver();
mIsCreate = false;
loadFromCursor(c);
mDiffDataValues = new ContentValues();
}
-
+ //功能:从光标处加载数据,DATA_ID_COLUMN等参数为0,1,2,3,4,应为获取五列参数
+ //实现:用各种get函数获取相关值
private void loadFromCursor(Cursor c) {
mDataId = c.getLong(DATA_ID_COLUMN);
mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN);
@@ -96,16 +101,23 @@ public class SqlData {
mDataContentData1 = c.getLong(DATA_CONTENT_DATA_1_COLUMN);
mDataContentData3 = c.getString(DATA_CONTENT_DATA_3_COLUMN);
}
-
+ //功能:设置共享数据并提供异常抛出与处理机制
+ //实现:首先js判断是否有DataColumns.ID,然后判断是否为第一种构造方式,将DataColumns.ID列和对应dataId列值加入到SQLData中,
+ //然后更新mDataId,最后判断并设置mDataMimeType、mDataContent等需共享的数据
public void setContent(JSONObject js) throws JSONException {
+ // 如果传入JSONObject有DataColumns.ID,则dataID = DataColumns.ID,否则设置为INVALID_ID=-99999
long dataId = js.has(DataColumns.ID) ? js.getLong(DataColumns.ID) : INVALID_ID;
+ //如果mIsCreate为True(根据第一种构造方式)或者mDataId(当前数据的ID)与dataId(元数据的ID)不符。
+ //第一种构造方式只是简单的初始化,没具体内容
if (mIsCreate || mDataId != dataId) {
+ // 将DataColumns.ID列和对应dataId列值加入到SQLData中
mDiffDataValues.put(DataColumns.ID, dataId);
}
mDataId = dataId;
-
+ // 判断并更新
String dataMimeType = js.has(DataColumns.MIME_TYPE) ? js.getString(DataColumns.MIME_TYPE)
: DataConstants.NOTE;
+ // 这个对象的MimeType不和(dataMimeType)共享数据一样,则将共享数据.MIME_TYPE加入数据库中
if (mIsCreate || !mDataMimeType.equals(dataMimeType)) {
mDiffDataValues.put(DataColumns.MIME_TYPE, dataMimeType);
}
@@ -129,7 +141,8 @@ public class SqlData {
}
mDataContentData3 = dataContentData3;
}
-
+ //功能:获取共享的数据内容,并提供异常抛出与处理机制
+ //实现:根据mIsCreate判断初始化类型,如果为第一种无内容的初始化,则返回null,否则,将要共享的内容存入JSONObject类的js中
public JSONObject getContent() throws JSONException {
if (mIsCreate) {
Log.e(TAG, "it seems that we haven't created this in database yet");
@@ -143,7 +156,9 @@ public class SqlData {
js.put(DataColumns.DATA3, mDataContentData3);
return js;
}
-
+ //功能:commit 函数用于把当前所做的修改保存到数据库
+ //实现:首先判断构造方式,如果为第一种构造方式,判断是否为有效然后更新共享数据;如果为第二种构造方式,首先判断要共享的数据mDiffDataValues是否存在,然后确认版本,如果版本还没有确认,则记录id和data,如果已经确认,则更新对应版本ID,最后将要共享的数据清空,回到初始化,表示已经共享
+ //参数:long类型的noteId,boolean类型的validateVersion用于版本确认,long类型的version为版本号
public void commit(long noteId, boolean validateVersion, long version) {
if (mIsCreate) {
@@ -182,7 +197,7 @@ public class SqlData {
mDiffDataValues.clear();
mIsCreate = false;
}
-
+ // 获取当前ID
public long getId() {
return mDataId;
}
diff --git a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/SqlNote.java b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/SqlNote.java
index f4d0011..5050a1d 100644
--- a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/SqlNote.java
+++ b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/SqlNote.java
@@ -77,13 +77,13 @@ public class SqlNote {
public static final int WIDGET_TYPE_COLUMN = 11;
public static final int SYNC_ID_COLUMN = 12;
-
+ // 本地修改的符号
public static final int LOCAL_MODIFIED_COLUMN = 13;
-
+ // 在进入临时文件夹之前,原始的父id(未使用)
public static final int ORIGIN_PARENT_ID_COLUMN = 14;
-
+ // 用户id
public static final int GTASK_ID_COLUMN = 15;
-
+ //版本
public static final int VERSION_COLUMN = 16;
private Context mContext;
@@ -121,7 +121,8 @@ public class SqlNote {
private ContentValues mDiffNoteValues;
private ArrayList mDataList;
-
+ //第一种构造函数
+ //构造函数,参数只有context,初始化新建的对象中的所有变量
public SqlNote(Context context) {
mContext = context;
mContentResolver = context.getContentResolver();
@@ -142,7 +143,8 @@ public class SqlNote {
mDiffNoteValues = new ContentValues();
mDataList = new ArrayList();
}
-
+ //第二种构造函数
+ //参数有context和cursor,对cursor指向的对象进行初始化
public SqlNote(Context context, Cursor c) {
mContext = context;
mContentResolver = context.getContentResolver();
@@ -154,7 +156,8 @@ public class SqlNote {
mDiffNoteValues = new ContentValues();
}
-
+ //第三种构造方式
+ //构造函数,参数有 context 和 id,对 id 指向的对象进行初始化
public SqlNote(Context context, long id) {
mContext = context;
mContentResolver = context.getContentResolver();
@@ -165,9 +168,11 @@ public class SqlNote {
loadDataContent();
mDiffNoteValues = new ContentValues();
}
-
+ //功能:通过id从光标处加载数据
+ //实现:通过id获取ContentResolver中的相应内容,并赋给cursor,如果有内容就将移入文档,并再次等待光标的内容;否则日志显示警告,最后关闭光标,方法完毕
private void loadFromCursor(long id) {
Cursor c = null;
+ //避免异常
try {
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, PROJECTION_NOTE, "(_id=?)",
new String[] {
@@ -184,7 +189,8 @@ public class SqlNote {
c.close();
}
}
-
+ //功能:通过cursor从光标加载数据
+ //实现:各种get类型的函数,通过光标c获取参数
private void loadFromCursor(Cursor c) {
mId = c.getLong(ID_COLUMN);
mAlertDate = c.getLong(ALERTED_DATE_COLUMN);
@@ -199,7 +205,10 @@ public class SqlNote {
mWidgetType = c.getInt(WIDGET_TYPE_COLUMN);
mVersion = c.getLong(VERSION_COLUMN);
}
-
+ //功能:通过content机制获取共享数据并加载到数据库当前光标处
+ //实现:获取ID对应content内容,如果查询到该note的id确实有对应项,即cursor有对应,获取ID对应content内容
+ //如果光标处有内容,提示note无数据warning,当记录数量不为0,则循环直到记录不存在,不断地取出记录放到DataList中
+ //如果cursor为空,警告,最终判断光标为空,则关闭
private void loadDataContent() {
Cursor c = null;
mDataList.clear();
@@ -225,16 +234,23 @@ public class SqlNote {
c.close();
}
}
-
+ //功能:设置通过content机制用于共享的数据信息
+ //实现:先判断是不是系统文件夹,再判断是否为文件夹类型,如果共享数据存在摘要,则将其赋给声明的 snippet变量,否则变量为空
+ //如果SQLNote采用的是第一种构造方式,或者snippet为空,则将snippet这一项键值存入contentvalue中,尽管是“”
+ //如果是note,获取提示日期,设置用于共享数据的信息,最后遍历 dataArray,查找 id 为 dataId 的数据,更新sqlData
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) {
+ // snnipet——片段、片断
// for folder we can only update the snnipet and type
String snippet = note.has(NoteColumns.SNIPPET) ? note
.getString(NoteColumns.SNIPPET) : "";
+ // 如果SQLNote采用的是第一种构造方式,或者snippet为空,则将snippet这一项键值存入contentvalue中,尽管是“”
if (mIsCreate || !mSnippet.equals(snippet)) {
mDiffNoteValues.put(NoteColumns.SNIPPET, snippet);
}
@@ -246,7 +262,9 @@ public class SqlNote {
mDiffNoteValues.put(NoteColumns.TYPE, type);
}
mType = type;
+ //如果是NOTE
} else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_NOTE) {
+ // 获取提示日期
JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
long id = note.has(NoteColumns.ID) ? note.getLong(NoteColumns.ID) : INVALID_ID;
if (mIsCreate || mId != id) {
@@ -358,7 +376,10 @@ public class SqlNote {
}
return true;
}
-
+ //功能:获取content机制提供的数据并加载到note中
+ //实现:判断采用的是第一种构造方式,自然实施初始化而已,显示错误:没创建数据库
+ //再判断如果对象的类型是note类型,这个对象的13项按键值对方式(ID, mId)、(ALERTED_DATE, mAlertDate)···加入note中
+ //类型为系统文件或目录文件时,将id,类型,以及摘要,存入jsonobject,然后对应META_HEAD_NOTE键,存入共享
public JSONObject getContent() {
try {
JSONObject js = new JSONObject();
@@ -392,7 +413,9 @@ public class SqlNote {
}
}
js.put(GTaskStringUtils.META_HEAD_DATA, dataArray);
+ // 类型为系统文件或目录文件时
} else if (mType == Notes.TYPE_FOLDER || mType == Notes.TYPE_SYSTEM) {
+ // 将id,类型,以及摘要,存入jsonobject,然后对应META_HEAD_NOTE键,存入共享
note.put(NoteColumns.ID, mId);
note.put(NoteColumns.TYPE, mType);
note.put(NoteColumns.SNIPPET, mSnippet);
@@ -406,7 +429,7 @@ public class SqlNote {
}
return null;
}
-
+ // 设置当前 id 的父 id
public void setParentId(long id) {
mParentId = id;
mDiffNoteValues.put(NoteColumns.PARENT_ID, id);
diff --git a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/Task.java b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/Task.java
index 1c42e99..97d24c9 100644
--- a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/Task.java
+++ b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/Task.java
@@ -31,7 +31,7 @@ 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();
@@ -44,7 +44,8 @@ public class Task extends Node {
private Task mPriorSibling;
private TaskList mParent;
-
+ //功能:Task类的构造函数,对对象进行初始化
+ //实现:调用父类构造方法,对变量初始化
public Task() {
super();
mCompleted = false;
@@ -53,12 +54,16 @@ public class Task extends Node {
mParent = null;
mMetaInfo = null;
}
-
+ //功能:获取创建的action。获取当前创建的action的属性值,比如说它的id号、类型、index值。
+ //实现:首先新建一个 JSONObject 的对象js用来存放同步过程中所用到的 task 信息,然后在共享数据js里存入action_type、action_id、index
+ //再新建一个 JSONObject 对象entity打包存放 name,creator id,type task,判断是否有notes,有则将其也放入entity中
+ //最后将entity、parent_id、dest_parent_type、list_id存入js中,判断如果存在优先兄弟 task,则将其 id 放入 js 中
public JSONObject getCreateAction(int actionId) {
JSONObject js = new JSONObject();
try {
// action_type
+ // 共享数据存入动作类型action_ type
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE);
@@ -69,11 +74,13 @@ public class Task extends Node {
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mParent.getChildTaskIndex(this));
// entity_delta
+ // 新建一个 JSONObject 对象打包存放 name,creator id,type task
JSONObject entity = new JSONObject();
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null");
entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE,
GTaskStringUtils.GTASK_JSON_TYPE_TASK);
+ // 如果存在 notes ,则将其也放入 entity 中
if (getNotes() != null) {
entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes());
}
@@ -102,7 +109,8 @@ public class Task extends Node {
return js;
}
-
+ //功能:获取更新的action
+ //实现:和上面getCreateAction差不多
public JSONObject getUpdateAction(int actionId) {
JSONObject js = new JSONObject();
@@ -134,7 +142,8 @@ public class Task extends Node {
return js;
}
-
+ //功能:通过远端的jsonobject获取任务内容
+ //实现:首先判断js是否非空,接着判断如果有id这个变量,就进行gid的设置,同样方法设置last_modified、name等变量
public void setContentByRemoteJSON(JSONObject js) {
if (js != null) {
try {
@@ -174,7 +183,10 @@ public class Task extends Node {
}
}
}
-
+ //功能:通过本地的jsonobject获取内容
+ //实现:首先判断js是否为空或者没有META_HEAD_NOTE,为空则显示日志,创建JSONObject类note存入js的META_HEAD_NOTE
+ //创建JSONArray类dataArray存入META_HEAD_DATA,判断note的TYPE不能匹配Notes的TYPE则无效
+ //最后遍历 dataArray 查找与数据库中DataConstants.NOTE 记录信息一致的 data
public void setContentByLocalJSON(JSONObject js) {
if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)
|| !js.has(GTaskStringUtils.META_HEAD_DATA)) {
@@ -203,7 +215,8 @@ public class Task extends Node {
}
}
}
-
+ //功能:通过Content机制获取本地JSON数据。
+ //实现:通过判断元数据是否存在,如果不存在,则创建一个新的对象,并将信息完善。最后返回js对象。
public JSONObject getLocalJSONFromContent() {
String name = getName();
try {
@@ -246,7 +259,8 @@ public class Task extends Node {
return null;
}
}
-
+ //功能:设置元数据信息
+ //参数:MetaData类 metaData,元数据
public void setMetaInfo(MetaData metaData) {
if (metaData != null && metaData.getNotes() != null) {
try {
@@ -257,7 +271,8 @@ public class Task extends Node {
}
}
}
-
+ //功能:获取同步操作
+ //实现:判断mMetaInfo是否被删除或者远程数据被删除,然后判断光标传入的note ID是否匹配并判断本地的便签数据是否已更新
public int getSyncAction(Cursor c) {
try {
JSONObject noteInfo = null;
@@ -310,16 +325,17 @@ public class Task extends Node {
return SYNC_ACTION_ERROR;
}
-
+ //功能:判断是否值得存放,即当前数据是否有效,若数据非空 或 名字合法存在且去除空格后的名字长度大于零则返回真值。
+ // 其它:trim() 的作用是去除字符串前后的空格:public String trim()返回字符串的副本,忽略前导空白和尾部空白
public boolean isWorthSaving() {
return mMetaInfo != null || (getName() != null && getName().trim().length() > 0)
|| (getNotes() != null && getNotes().trim().length() > 0);
}
-
+ // 将task设置为修改完毕
public void setCompleted(boolean completed) {
this.mCompleted = completed;
}
-
+ // 设定mNotes
public void setNotes(String notes) {
this.mNotes = notes;
}
diff --git a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/TaskList.java b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/TaskList.java
index 6444a4e..d1a70c9 100644
--- a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/TaskList.java
+++ b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/data/TaskList.java
@@ -42,7 +42,8 @@ public class TaskList extends Node {
mChildren = new ArrayList();
mIndex = 1;
}
-
+ //功能:获取生成动作
+ //实现:创建JSONObject js存入action_type、action_id、index、entity_delta,生成并返回一个包含了一定数据的JSONObject实体
public JSONObject getCreateAction(int actionId) {
JSONObject js = new JSONObject();
@@ -73,7 +74,8 @@ public class TaskList extends Node {
return js;
}
-
+ //功能:接受更新action,返回jsonobject
+ //实现:同上面getCreateAction类似
public JSONObject getUpdateAction(int actionId) {
JSONObject js = new JSONObject();
@@ -102,7 +104,8 @@ public class TaskList extends Node {
return js;
}
-
+ //功能:通过云端 JSON 数据设置实例化对象 js 的内容
+ //实现:通过传入的js判断非空,然后设置id、last_modified、name
public void setContentByRemoteJSON(JSONObject js) {
if (js != null) {
try {
@@ -128,7 +131,8 @@ public class TaskList extends Node {
}
}
}
-
+ //功能:通过本地 JSON 数据设置对象 js 内容
+ //实现:实现方法也与上面setContentByRemoteJSON类似,不过设置的是根据本地js传入
public void setContentByLocalJSON(JSONObject js) {
if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)) {
Log.w(TAG, "setContentByLocalJSON: nothing is avaiable");
@@ -159,7 +163,8 @@ public class TaskList extends Node {
e.printStackTrace();
}
}
-
+ //功能:从content获取本地json
+ //实现:getname()函数获取文件夹名称
public JSONObject getLocalJSONFromContent() {
try {
JSONObject js = new JSONObject();
@@ -185,7 +190,12 @@ public class TaskList extends Node {
return null;
}
}
-
+ //功能:通过 cursor 获取同步信息
+ //实现:首先判断本地记录是否被修改,如果没有修改,再判断光标处的ID与最后一次修改是否相等
+ //如果相等则返回“不同步”,如果不等则返回“同步”
+ //如果本地记录已经修改,则判断获取的ID是否匹配,若不匹配则返回同步动作失败
+ //其它:“同步”是指将remote端更新至local端。另外为什么 if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified())
+ //为什么这个判断最后 if else返回的都是SYNC_ACTION_UPDATE_REMOTE?
public int getSyncAction(Cursor c) {
try {
if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) {
@@ -222,7 +232,10 @@ public class TaskList extends Node {
public int getChildTaskCount() {
return mChildren.size();
}
-
+ //功能:在当前任务表中添加新的子任务
+ //实现:如果传入的子任务不是空并且当前的子任务序列中不含有该任务,就将这个任务加入子任务中
+ //然后设置兄弟任务优先级,若子任务为空,返回 NULL,否则返回子任务数量-1,最后设置该任务的父任务
+ //返回值为是否成功添加任务
public boolean addChildTask(Task task) {
boolean ret = false;
if (task != null && !mChildren.contains(task)) {
@@ -236,7 +249,9 @@ public class TaskList extends Node {
}
return ret;
}
-
+ //功能:在当前任务表的指定位置添加新的任务。
+ //实现:先获取要添加的任务在任务表中的位置,在索引位置添加任务,update the task list
+ //然后让插入的任务与前后连在一块,将下一个任务设置兄弟任务优先级
public boolean addChildTask(Task task, int index) {
if (index < 0 || index > mChildren.size()) {
Log.e(TAG, "add child task: invalid index");
@@ -262,7 +277,8 @@ public class TaskList extends Node {
return true;
}
-
+ //功能:删除TaskList中的一个Task
+ //实现:方法同addChildTask()类似
public boolean removeChildTask(Task task) {
boolean ret = false;
int index = mChildren.indexOf(task);
@@ -283,7 +299,7 @@ public class TaskList extends Node {
}
return ret;
}
-
+ // 功能:将当前TaskList中含有的某个Task移到index位置
public boolean moveChildTask(Task task, int index) {
if (index < 0 || index >= mChildren.size()) {
@@ -301,7 +317,8 @@ public class TaskList extends Node {
return true;
return (removeChildTask(task) && addChildTask(task, index));
}
-
+ //功能:通过Gid寻找子任务(未使用)
+ //实现:从头至尾遍历整个任务列表判断任务的gid与传入的gid是否相等
public Task findChildTaskByGid(String gid) {
for (int i = 0; i < mChildren.size(); i++) {
Task t = mChildren.get(i);
@@ -311,11 +328,11 @@ public class TaskList extends Node {
}
return null;
}
-
+ // 获取子任务索引列表
public int getChildTaskIndex(Task task) {
return mChildren.indexOf(task);
}
-
+ // 返回指定index的Task
public Task getChildTaskByIndex(int index) {
if (index < 0 || index >= mChildren.size()) {
Log.e(TAG, "getTaskByIndex: invalid index");
@@ -323,7 +340,7 @@ public class TaskList extends Node {
}
return mChildren.get(index);
}
-
+ // 返回指定gid的Task
public Task getChilTaskByGid(String gid) {
for (Task task : mChildren) {
if (task.getGid().equals(gid))
@@ -331,7 +348,7 @@ public class TaskList extends Node {
}
return null;
}
-
+ //获取子任务列表
public ArrayList getChildTaskList() {
return this.mChildren;
}
diff --git a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java
index 15504be..b46c8c4 100644
--- a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java
+++ b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java
@@ -14,12 +14,23 @@
* limitations under the License.
*/
+// 小米便签行为异常处理
+
package net.micode.notes.gtask.exception;
+/**
+ * 异常处理类,继承自RuntimeException类
+ */
public class ActionFailureException extends RuntimeException {
+ // 定义:serialVersionUID相当于java类的身份证,主要用于版本控制。
+ // 作用:验证版本一致性,如果不一致会导致反序列化的时候版本不一致的异常。
private static final long serialVersionUID = 4425249765923293627L;
+ /**
+ * 构造函数(包括下面的两个构造函数)
+ */
public ActionFailureException() {
+ // super引用父类成分,this引用当前类
super();
}
diff --git a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java
index b08cfb1..000f124 100644
--- a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java
+++ b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java
@@ -14,11 +14,19 @@
* limitations under the License.
*/
+// 小米便签网络异常处理
+
package net.micode.notes.gtask.exception;
+/**
+ * 网络异常类,继承自Exception类
+ */
public class NetworkFailureException extends Exception {
private static final long serialVersionUID = 2107610287180234136L;
+ /**
+ * 构造函数(以下三个都是)
+ */
public NetworkFailureException() {
super();
}
diff --git a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java
index 777f88c..d7503ef 100644
--- a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java
+++ b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java
@@ -1,3 +1,6 @@
+//【1】 AsyncTask,意为“异步任务”,是指执行某一功能但不要求立刻得到结果,因而可以正常进行其他操作。
+//【2】Android使用异步任务是为了使主线程保持较高的响应性,把耗时的任务交给AsyncTask等工作者线程处理。
+//【3】AsyncTask方便快捷,过程可控,适合简单的异步操作,实际可用于倒计时功能、进度条显示等。
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
@@ -24,90 +27,151 @@ import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
+// 自动生成的该程序包名下的R.java,用于引用已建立的资源
import net.micode.notes.R;
import net.micode.notes.ui.NotesListActivity;
import net.micode.notes.ui.NotesPreferenceActivity;
-
+/**
+ *【1】定义:GTaskASyncTask类继承于抽象类 AsyncTask。
+ *【2】功能:处理GTask的异步任务,实现UI线程与后台线程间的通讯。
+ *【3】主要方法:
+ private void showNotification(int tickerId, String content) ——向用户提示当前同步的状态,是一个用于交互的方法。
+ protected Integer doInBackground(Void... unused) ——重点方法,在后台线程执行,定义了所要完成的任务,比较耗时。
+ protected void onProgressUpdate(String... progress) —— 此方法在主线程执行,用于显示任务执行的进度条。
+ protected void onPostExecute(Integer result) ——相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。
+ */
public class GTaskASyncTask extends AsyncTask {
-
+ // 定义:static int变量存储GTask同步通知的ID。
private static int GTASK_SYNC_NOTIFICATION_ID = 5234235;
+ /**
+ * 方法:声明一个OnCompleteListener接口,其onComplete ()用来初始化异步功能(在GTaskSyncService里实现,发送一个空广播)。
+ */
public interface OnCompleteListener {
void onComplete();
}
private Context mContext;
+ // 对象: 实例化一个通知管理器类。
private NotificationManager mNotifiManager;
private GTaskManager mTaskManager;
private OnCompleteListener mOnCompleteListener;
+ /**
+ * 【1】作用:GTaskASyncTask的构造函数。
+ * 【2】参数:
+ context类——可以访问application的资源和相关的类,比如说启动Activity、启动和停止Service、发送广播消息(Intent)、注册广播消息(Intent)接收者、访问apk中各种资源(如Resources和AssetManager)、访问Package的相关信息、APK的各种权限管理等。
+ OnCompleteListener接口——上文已声明。
+ */
public GTaskASyncTask(Context context, OnCompleteListener listener) {
mContext = context;
mOnCompleteListener = listener;
+ // getSystemService是Activity的一个方法,可根据传入的参数获得应服务的对象。这里以Context的NOTIFICATION_SERVICE为对象。
mNotifiManager = (NotificationManager) mContext
.getSystemService(Context.NOTIFICATION_SERVICE);
+ // getInstance ()函数用于使用单例模式创建类的实例。
mTaskManager = GTaskManager.getInstance();
}
+ /**
+ *【1】功能:取消同步
+ *【2】方法:对实例mTaskManager调用中断同步函数。
+ */
public void cancelSync() {
mTaskManager.cancelSync();
}
+ /**
+ *【1】功能:显示信息
+ *【2】方法:通过publishProgress发布String []里的信息,系统将会调用onProgressUpdate ()方法更新进度条
+ */
public void publishProgess(String message) {
publishProgress(new String[] {
message
});
}
+ /**
+ * 【1】功能:显示通知
+ * 【2】方法:向用户通知同步的进程,是一个用于交互的方法
+ */
private void showNotification(int tickerId, String content) {
+ // 实例化一个通知对象
Notification notification = new Notification(R.drawable.notification, mContext
.getString(tickerId), System.currentTimeMillis());
+ // 添加默认呼吸灯提醒
notification.defaults = Notification.DEFAULT_LIGHTS;
+ // 用户点击清除按钮或点击通知后,提示会自动消失
notification.flags = Notification.FLAG_AUTO_CANCEL;
+ // 类: PendingIntent 是 Android 提供的一种用于外部程序调起自身程序的能力,生命周期不与主程序相关。
PendingIntent pendingIntent;
+ // 如果同步失败,就从系统取得一个用于启动NotesPreferenceActivity的PendingIntent对象。
if (tickerId != R.string.ticker_success) {
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
NotesPreferenceActivity.class), 0);
} else {
+ // 如果同步成功,就从系统取得一个用于启动NotesListActivity的PendingIntent对象。
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
NotesListActivity.class), 0);
}
+ // 设置一个关于最新事件的通知。
//notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content,
// pendingIntent);
+ // 将通知加入状态栏,通过notify ()方法来执行一个notification的消息。
mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification);
}
+ //Java5的元数据,是自动加上去的一个标志,目的是告知你下面这个方法是从父类/接口继承过来的,需要重写一次。
@Override
+ /**
+ *【1】功能:异步执行后台线程将要完成的任务。
+ *【2】实现:使用publishProgress ( )方法传入UI界面的相关参数,并调用onProgressUpdate()。
+ *【3】参数:Void... unused 表示不会传入参数。(注:java类型后面跟三个点是代表可以接受多个实际参数,这里的多个指的是不限个数。)
+ */
protected Integer doInBackground(Void... unused) {
+ // 将同步账户的名字传递给登陆的进程,利用publishProgress方法来跟进该任务的执行进度。
publishProgess(mContext.getString(R.string.sync_progress_login, NotesPreferenceActivity
.getSyncAccountName(mContext)));
+ // 进行后台的同步工作,并返回其同步结果。
return mTaskManager.sync(mContext, this);
}
@Override
+ /**
+ *【1】功能:显示进度的更新。
+ *【2】方法:在调用publishProgress时,该方法被执行,并将进度信息更新到UI组件中。
+ *【3】参数:string类型数组。
+ */
protected void onProgressUpdate(String... progress) {
showNotification(R.string.ticker_syncing, progress[0]);
+ // 判断mContext是否是GTaskSyncService的实例,若是则发送一个广播。
if (mContext instanceof GTaskSyncService) {
((GTaskSyncService) mContext).sendBroadcast(progress[0]);
}
}
@Override
+ /**
+ *【1】功能:执行完后台任务后更新UI,显示结果即进度条 。
+ *【2】方法: 在dolnBackground执行完成后,该方法会被UI线程调用。根据不同的result(同步成功、网络错误、内部错误、同步取消)执行不同的操作,并将后台的计算结果传递到UI进程,在界面上展示出来。
+ *【3】参数:integer类型,是AsyncTask初始化的第三个参数result。
+ */
protected void onPostExecute(Integer result) {
+ // 若同步成功,则显示成功并展示出同步的账户与最新同步时间。
if (result == GTaskManager.STATE_SUCCESS) {
showNotification(R.string.ticker_success, mContext.getString(
R.string.success_sync_account, mTaskManager.getSyncAccount()));
NotesPreferenceActivity.setLastSyncTime(mContext, System.currentTimeMillis());
- } else if (result == GTaskManager.STATE_NETWORK_ERROR) {
+ } else if (result == GTaskManager.STATE_NETWORK_ERROR) { // 因网络错误而同步失败
showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_network));
- } else if (result == GTaskManager.STATE_INTERNAL_ERROR) {
+ } else if (result == GTaskManager.STATE_INTERNAL_ERROR) { // 因内部访问问题而同步失败
showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_internal));
- } else if (result == GTaskManager.STATE_SYNC_CANCELLED) {
+ } else if (result == GTaskManager.STATE_SYNC_CANCELLED) { // 因主动取消而同步失败
showNotification(R.string.ticker_cancel, mContext
.getString(R.string.error_sync_cancelled));
}
@@ -115,6 +179,7 @@ public class GTaskASyncTask extends AsyncTask {
new Thread(new Runnable() {
public void run() {
+ // 接口回调,返回到主线程中。
mOnCompleteListener.onComplete();
}
}).start();
diff --git a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java
index c2ac22f..cffd796 100644
--- a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java
+++ b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java
@@ -60,10 +60,14 @@ import java.util.zip.GZIPInputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
-
+/**
+ * 功能:登录Google账户(可用于自动登录),更新账户信息,获取任务列表等
+ */
public class GTaskClient {
+ // 设置本类的TAG,作用是日志的打印输出和标识此类
private static final String TAG = GTaskClient.class.getSimpleName();
+ // 谷歌邮箱的URL
private static final String GTASK_URL = "https://mail.google.com/tasks/";
private static final String GTASK_GET_URL = "https://mail.google.com/tasks/ig";
@@ -90,6 +94,10 @@ public class GTaskClient {
private JSONArray mUpdateArray;
+ /**
+ * 定义:GTaskClient的构造函数
+ * 功能:给GTaskClient类中各个成员赋初始值,即初始化客户端
+ */
private GTaskClient() {
mHttpClient = null;
mGetUrl = GTASK_GET_URL;
@@ -102,6 +110,10 @@ public class GTaskClient {
mUpdateArray = null;
}
+ /**
+ * 功能:使用单例模式创建GTaskClient的实例
+ * 实现:当mInstance的值为NULL时,新建一个GTaskClient的实例赋值给mInstance
+ */
public static synchronized GTaskClient getInstance() {
if (mInstance == null) {
mInstance = new GTaskClient();
@@ -109,27 +121,39 @@ public class GTaskClient {
return mInstance;
}
+ /**
+ * 功能:实现登录
+ * 方法:使用下面定义的loginGoogleAccount( )方法登录Google账户 ,使用下面定义的loginGtask( )方法登录gtask,登录成功返回true,登录失败返回false
+ * 参数:要执行登录操作的活动
+ */
public boolean login(Activity activity) {
// we suppose that the cookie would expire after 5 minutes
// then we need to re-login
+ // 设置登录时间为5分钟,若超时则重新登录
final long interval = (long) 1000 * 60 * 5;
if (mLastLoginTime + interval < System.currentTimeMillis()) {
mLoggedin = false;
}
// need to re-login after account switch
+ // 功能:切换用户需重新登录
+ // 方法:判断条件为,在已登录条件下,将已登录用户名和要切换的用户名进行比较,若字符串不相等,则登录失败,将登录状态设置为未登录(false)
if (mLoggedin
&& !TextUtils.equals(getSyncAccount().name, NotesPreferenceActivity
.getSyncAccountName(activity))) {
mLoggedin = false;
}
+ // 若符合以上条件,则显示“已经登录成功”字样
if (mLoggedin) {
Log.d(TAG, "already logged in");
return true;
}
+ // 更新登陆的时间
mLastLoginTime = System.currentTimeMillis();
+ // 功能:判断是否登入google账号
+ // 方法:使用下面定义的loginGoogleAccount( )方法,返回登录令牌(string),即用用户提供的账户密码去登陆Google账户
String authToken = loginGoogleAccount(activity, false);
if (authToken == null) {
Log.e(TAG, "login google account failed");
@@ -137,6 +161,8 @@ public class GTaskClient {
}
// login with custom domain if necessary
+ // 功能:在google账号登陆成功后,尝试能否使用用户的域名登陆gtask
+ // 方法:判断输入的字符串结尾有无谷歌域名,然后设置用户的getUrl和postUrl
if (!(mAccount.name.toLowerCase().endsWith("gmail.com") || mAccount.name.toLowerCase()
.endsWith("googlemail.com"))) {
StringBuilder url = new StringBuilder(GTASK_URL).append("a/");
@@ -152,6 +178,7 @@ public class GTaskClient {
}
// try to login with google official url
+ // 若前面的尝试失败,则尝试使用官方的域名登陆
if (!mLoggedin) {
mGetUrl = GTASK_GET_URL;
mPostUrl = GTASK_POST_URL;
@@ -164,9 +191,16 @@ public class GTaskClient {
return true;
}
+ /**
+ * 功能:登录谷歌账号
+ * 方法:使用令牌机制,使用AccountManager管理注册账号
+ */
private String loginGoogleAccount(Activity activity, boolean invalidateToken) {
+ // 使用登录令牌核实用户信息和判断登录状态,既保证登录顺畅,又避免cookie无限期保存导致账号被盗
String authToken;
+ // 账户管理器集中管理已注册账号和密码
AccountManager accountManager = AccountManager.get(activity);
+ // 将账号管理对象中所有的谷歌账号存入account数组里备用
Account[] accounts = accountManager.getAccountsByType("com.google");
if (accounts.length == 0) {
@@ -207,6 +241,11 @@ public class GTaskClient {
return authToken;
}
+ /**
+ * 功能:尝试登录Gtask,此方法作为登录的预判,用于判断令牌对于登录gtask账号是否有效
+ * 方法:此函数使用后面定义的loginGtask( )方法和已获得的令牌进行一次登陆,如果成功则返回true,如果不成功则登陆google的账户重新获取令牌。
+ * 参数:要进行登录的活动,登录gtask账号使用的令牌
+ */
private boolean tryToLoginGtask(Activity activity, String authToken) {
if (!loginGtask(authToken)) {
// maybe the auth token is out of date, now let's invalidate the
@@ -225,6 +264,11 @@ public class GTaskClient {
return true;
}
+ /**
+ * 功能:通过令牌登录Gtask,登录成功返回true,失败放回false
+ * 方法:使用mgeturl和令牌构造loginurl,通过get方法得到http的对象,获取cookie、版本号
+ * 参数:已获得的令牌
+ */
private boolean loginGtask(String authToken) {
int timeoutConnection = 10000;
int timeoutSocket = 15000;
@@ -280,10 +324,17 @@ public class GTaskClient {
return true;
}
+ /**
+ * 功能:获取活动ID+1并将其返回
+ */
private int getActionId() {
return mActionId++;
}
+ /**
+ * 功能:返回一个用于向网络传输数据的httpPost对象
+ * 实现:新创建一个httpPost对象,设置头部信息
+ */
private HttpPost createHttpPost() {
HttpPost httpPost = new HttpPost(mPostUrl);
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
@@ -291,6 +342,11 @@ public class GTaskClient {
return httpPost;
}
+ /**
+ * 功能:通过URL获取响应后返回的数据,也就是网络上的数据和资源,但可能会抛出异常
+ * 实现:使用getContentEncoding ( )方法获取一个字节流,对内容进行格式转换,返回值是获取到的资源内容
+ * 参数:HttpEntity对象
+ */
private String getResponseContent(HttpEntity entity) throws IOException {
String contentEncoding = null;
if (entity.getContentEncoding() != null) {
@@ -323,6 +379,11 @@ public class GTaskClient {
}
}
+ /**
+ * 功能:通过JSON向客户端发送请求并调用getResponseContent方法来获取返回的信息
+ * 方法:通过JSON发送请求,利用UrlEncodedFormEntity entity和httpPost.setEntity把js中的内容放置到httpPost中,将资源存储到string中,再次放入json后返回
+ * 参数:JSONObject对象
+ */
private JSONObject postRequest(JSONObject js) throws NetworkFailureException {
if (!mLoggedin) {
Log.e(TAG, "please login first");
@@ -360,6 +421,10 @@ public class GTaskClient {
}
}
+ /**
+ * 功能: 创建单个任务,设置好action的链表、client_version、post
+ * 方法:创建单个任务,通过json获取TASK中的内容并创建对应的jsPost,通过postRequest方法获取任务的返回信息,使用setGid方法设置task的new_id
+ */
public void createTask(Task task) throws NetworkFailureException {
commitUpdate();
try {
@@ -386,6 +451,11 @@ public class GTaskClient {
}
}
+ /**
+ * 功能:创建任务列表,与createTask类似,区别在于最后设置的是tasklist的gid
+ * 方法:定义了JSONObject对象jsPost,通过jsPost设置好动作列表,用户名版本
+ * 参数:Tasklist类对象(自定义类)
+ */
public void createTaskList(TaskList tasklist) throws NetworkFailureException {
commitUpdate();
try {
@@ -412,6 +482,10 @@ public class GTaskClient {
}
}
+ /**
+ * 功能:提交更新数据
+ * 方法:判断mUpdateArray的值并进行相应操作。若更新则使用jsPost.put( )添加对应关系,提交UpdateArray和ClientVersion 。
+ */
public void commitUpdate() throws NetworkFailureException {
if (mUpdateArray != null) {
try {
@@ -433,6 +507,11 @@ public class GTaskClient {
}
}
+ /**
+ * 功能:添加更新的节点,对更新列表进行操作
+ * 方法:调用commitUpdate ()实现
+ * 参数:Node类对象(自定义类)
+ */
public void addUpdateNode(Node node) throws NetworkFailureException {
if (node != null) {
// too many update items may result in an error
@@ -447,6 +526,10 @@ public class GTaskClient {
}
}
+ /**
+ * 功能:移动任务到不同的task列表中
+ * 方法:先得到任务ID,之后更新任务移动后的相关属性值,最后将完成更新后的请求发送
+ */
public void moveTask(Task task, TaskList preParent, TaskList curParent)
throws NetworkFailureException {
commitUpdate();
@@ -486,6 +569,10 @@ public class GTaskClient {
}
}
+ /**
+ * 功能:删除操作节点
+ * 方法:利用JSON,删除后使用postRequest发送删除后的结果
+ */
public void deleteNode(Node node) throws NetworkFailureException {
commitUpdate();
try {
@@ -509,6 +596,10 @@ public class GTaskClient {
}
}
+ /**
+ * 功能:获取任务列表
+ * 方法:先通过GetURI使用getResponseContent从网上获取数据,然后筛选出 "_setup(" 到 “)}” 的部分,并从中获取GTASK_JSON_LISTS的内容返回
+ */
public JSONArray getTaskLists() throws NetworkFailureException {
if (!mLoggedin) {
Log.e(TAG, "please login first");
@@ -547,6 +638,9 @@ public class GTaskClient {
}
}
+ /**
+ * 功能:获取任务列表
+ */
public JSONArray getTaskList(String listGid) throws NetworkFailureException {
commitUpdate();
try {
@@ -575,10 +669,16 @@ public class GTaskClient {
}
}
+ /**
+ * 功能:获取同步账户
+ */
public Account getSyncAccount() {
return mAccount;
}
+ /**
+ * 功能:重置更新内容
+ */
public void resetUpdateArray() {
mUpdateArray = null;
}
diff --git a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java
index 613f659..e358891 100644
--- a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java
+++ b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+// 实现同步功能的主函数
+
package net.micode.notes.gtask.remote;
import android.app.Activity;
@@ -47,18 +49,20 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
-
+/**
+ * 【1】定义:GTask管理类
+ * 【2】功能:提供同步本地和远端的任务,初始化任务列表,同步内容、文件夹,添加、更新本地和远端结点,刷新本地同步任务ID等功能
+ */
public class GTaskManager {
+ // 定义了一系列静态变量来显示GTask当前的状态
+ //(1)设置GTask的TAG
private static final String TAG = GTaskManager.class.getSimpleName();
+ //(2)进程状态:用0、1、2、3、4分别表示成功、网络错误、内部错误、同步中、取消同步
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;
private static GTaskManager mInstance = null;
@@ -87,18 +91,32 @@ public class GTaskManager {
private HashMap mNidToGid;
+ /**
+ * 类的构造函数,对其内部变量进行初始化
+ */
private GTaskManager() {
+ // 正在同步标识,false代表未同步
mSyncing = false;
+ // 取消同步标识,false代表可以取消
mCancelled = false;
+ // 任务列表以哈希表的形式创立
mGTaskListHashMap = new HashMap();
+ // 创建一个节点表
mGTaskHashMap = new HashMap();
+ // 创建一个删除本地ID的map
mMetaHashMap = new HashMap();
mMetaList = null;
mLocalDeleteIdMap = new HashSet();
+ // 创建Gid(google id)到Nid(节点 id)的映射
mGidToNid = new HashMap();
+ // 与mGidToNid相反的映射
mNidToGid = new HashMap();
}
+ /**
+ * 功能:获取一个实例,通过GTaskManager()新建一个mInstance
+ *(注:synchronized指明该函数可以运行在多线程下)
+ */
public static synchronized GTaskManager getInstance() {
if (mInstance == null) {
mInstance = new GTaskManager();
@@ -106,20 +124,29 @@ public class GTaskManager {
return mInstance;
}
+ /**
+ * 功能:获取当前的操作并更新至GTask中
+ */
public synchronized void setActivityContext(Activity activity) {
// used for getting authtoken
mActivity = activity;
}
+ /**
+ * 功能:实现同步操作,包括同步前设置环境,进行同步,处理异常,同步结束清空缓存
+ */
public int sync(Context context, GTaskASyncTask asyncTask) {
+ // 当前状态是正在同步中
if (mSyncing) {
- Log.d(TAG, "Sync is in progress");
- return STATE_SYNC_IN_PROGRESS;
+ Log.d(TAG, "Sync is in progress"); // 声明同步正在运行
+ return STATE_SYNC_IN_PROGRESS; // 返回同步状态
}
+ // 对同步时GTaskManager的属性进行更新
mContext = context;
mContentResolver = mContext.getContentResolver();
mSyncing = true;
mCancelled = false;
+ // 对各种结构进行清空
mGTaskListHashMap.clear();
mGTaskHashMap.clear();
mMetaHashMap.clear();
@@ -127,35 +154,42 @@ public class GTaskManager {
mGidToNid.clear();
mNidToGid.clear();
+ // 异常处理程序
try {
+ // 实例化一个GTask用户对象
GTaskClient client = GTaskClient.getInstance();
+ // 重置更新数组
client.resetUpdateArray();
// login google task
+ // 若此时未取消同步操作,进行登录操作,尝试登录到google task
if (!mCancelled) {
+ // 如果mActivity登录不上则抛出一个异常
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) {
+ } catch (NetworkFailureException e) { // 网络异常
Log.e(TAG, e.toString());
return STATE_NETWORK_ERROR;
- } catch (ActionFailureException e) {
+ } catch (ActionFailureException e) { //操作未完成
Log.e(TAG, e.toString());
return STATE_INTERNAL_ERROR;
- } catch (Exception e) {
+ } catch (Exception e) { //内部错误
Log.e(TAG, e.toString());
e.printStackTrace();
return STATE_INTERNAL_ERROR;
- } finally {
+ } finally { //在同步操作结束后,更新GTaskManager的属性
mGTaskListHashMap.clear();
mGTaskHashMap.clear();
mMetaHashMap.clear();
@@ -165,37 +199,53 @@ public class GTaskManager {
mSyncing = false;
}
+ // 若在同步时操作未取消,则返回同步成功,否则返回同步操作取消
return mCancelled ? STATE_SYNC_CANCELLED : STATE_SUCCESS;
}
+ /**
+ * 功能:初始化GTask列表,将google上的JSONTaskList转为本地任务列表
+ * @throws NetworkFailureException
+ */
private void initGTaskList() throws NetworkFailureException {
+ // 判断是否取消该次操作
if (mCancelled)
return;
+ // 实例化一个GTask用户对象
GTaskClient client = GTaskClient.getInstance();
try {
+ // 客户端获取任务列表jsTaskLists
JSONArray jsTaskLists = client.getTaskLists();
// init meta list first
+ // 初始化元数据列表
mMetaList = null;
+ // 不断把任务列表里的每个任务通过远程JSON设置内容并把元数据都放到哈希表中
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);
+ JSONObject object = jsTaskLists.getJSONObject(i); // 取出单个JSON对象
+ String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID); // 获取它的id
+ String name = object.getString(GTaskStringUtils.GTASK_JSON_NAME); // 获取它的名字
+ // 新建数组,并为新建的数组设定内容
if (name
.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META)) {
mMetaList = new TaskList();
mMetaList.setContentByRemoteJSON(object);
// load meta data
+ // 获取元数据
JSONArray jsMetas = client.getTaskList(gid);
+ // 把jsMetas里的每一个有识别码的metaData都放到哈希表中
for (int j = 0; j < jsMetas.length(); j++) {
object = (JSONObject) jsMetas.getJSONObject(j);
MetaData metaData = new MetaData();
metaData.setContentByRemoteJSON(object);
+ // 判断前面获取的元数据有无价值加入列表中
if (metaData.isWorthSaving()) {
mMetaList.addChildTask(metaData);
+ // 操作getGid:取得组识别码函数
if (metaData.getGid() != null) {
+ // 把元数据放到哈希表中
mMetaHashMap.put(metaData.getRelatedGid(), metaData);
}
}
@@ -204,6 +254,7 @@ public class GTaskManager {
}
// create meta list if not existed
+ // 如果元数据列表不存在,则在客户端创建一个
if (mMetaList == null) {
mMetaList = new TaskList();
mMetaList.setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX
@@ -212,7 +263,9 @@ public class GTaskManager {
}
// 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);
@@ -221,11 +274,13 @@ public class GTaskManager {
&& !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
+ // 获取任务id号
JSONArray jsTasks = client.getTaskList(gid);
for (int j = 0; j < jsTasks.length(); j++) {
object = (JSONObject) jsTasks.getJSONObject(j);
@@ -240,46 +295,60 @@ public class GTaskManager {
}
}
}
- } catch (JSONException e) {
+ } catch (JSONException e) { // 初始化时捕捉异常
Log.e(TAG, e.toString());
e.printStackTrace();
+ // 抛出异常,提交 JSONObject 失败
throw new ActionFailureException("initGTaskList: handing JSONObject failed");
}
}
+ /**
+ * 功能:实现内容同步的操作
+ * @throws NetworkFailureException
+ */
private void syncContent() throws NetworkFailureException {
int syncType;
Cursor c = null;
String gid;
Node node;
+ // 初始化本地删除列表
mLocalDeleteIdMap.clear();
+ // 判断该操作是否已被取消
if (mCancelled) {
return;
}
// for local deleted note
+ // 对于删除本地便签的操作的同步
try {
+ // 定位要删除的节点位置
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE,
"(type<>? AND parent_id=?)", new String[] {
String.valueOf(Notes.TYPE_SYSTEM), String.valueOf(Notes.ID_TRASH_FOLER)
}, null);
+ // 若获取到的待删除便签不为空,则进行同步操作
if (c != null) {
+ // 方法:如果节点位置不为空,用while循环把节点一个一个的往后移动,并不多更新gid和哈希表,直到最后移动到列表尾不能再移动,把c指向的note放到本地删除节点ID的图里。
while (c.moveToNext()) {
gid = c.getString(SqlNote.GTASK_ID_COLUMN);
node = mGTaskHashMap.get(gid);
if (node != null) {
+ // 将待删除的节点对应的google id从映射表中移除
mGTaskHashMap.remove(gid);
+ // 在远程删除对应节点
doContentSync(Node.SYNC_ACTION_DEL_REMOTE, node, c);
}
+ // 在本地删除记录中添加这一项记录
mLocalDeleteIdMap.add(c.getLong(SqlNote.ID_COLUMN));
}
- } else {
+ } else { // 或者发现没有待删除的节点,报错
Log.w(TAG, "failed to query trash folder");
}
- } finally {
+ } finally { // 最后把c关闭并重置
if (c != null) {
c.close();
c = null;
@@ -287,10 +356,13 @@ public class GTaskManager {
}
// sync folder first
+ // 对文件夹进行同步
syncFolder();
// for note existing in database
+ // 对已经存在与数据库的节点进行同步
try {
+ // c指针指向待操作的便签位置
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE,
"(type=? AND parent_id<>?)", new String[] {
String.valueOf(Notes.TYPE_NOTE), String.valueOf(Notes.ID_TRASH_FOLER)
@@ -301,25 +373,31 @@ public class GTaskManager {
node = mGTaskHashMap.get(gid);
if (node != null) {
mGTaskHashMap.remove(gid);
+ // 建立google id到节点id的映射
mGidToNid.put(gid, c.getLong(SqlNote.ID_COLUMN));
+ // 建立节点id到google id的映射
mNidToGid.put(c.getLong(SqlNote.ID_COLUMN), gid);
+ // 更新此时的同步类型
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;
}
}
doContentSync(syncType, node, c);
}
} else {
+ // 警告,询问数据库中已创建的便签失败
Log.w(TAG, "failed to query existing note in database");
}
- } finally {
+ } finally { // 最后关闭c并重置
if (c != null) {
c.close();
c = null;
@@ -327,16 +405,19 @@ public class GTaskManager {
}
// go through remaining items
+ // 用迭代器扫描剩下的项目,逐个进行同步
Iterator> iter = mGTaskHashMap.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = iter.next();
node = entry.getValue();
+ // 在本地增加这些节点
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");
@@ -344,6 +425,7 @@ public class GTaskManager {
}
// refresh local sync id
+ // 更新同步表
if (!mCancelled) {
GTaskClient.getInstance().commitUpdate();
refreshLocalSyncId();
@@ -351,6 +433,10 @@ public class GTaskManager {
}
+ /**
+ * 功能:同步文件夹
+ * @throws NetworkFailureException
+ */
private void syncFolder() throws NetworkFailureException {
Cursor c = null;
String gid;
@@ -363,27 +449,32 @@ public class GTaskManager {
// for root folder
try {
+ // 使指针指向根文件夹的位置
c = mContentResolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI,
Notes.ID_ROOT_FOLDER), SqlNote.PROJECTION_NOTE, null, null, null);
if (c != null) {
c.moveToNext();
+ // 获取指针指向内容对应的gid
gid = c.getString(SqlNote.GTASK_ID_COLUMN);
+ // 获取该gid所代表的节点
node = mGTaskHashMap.get(gid);
if (node != null) {
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))
doContentSync(Node.SYNC_ACTION_UPDATE_REMOTE, node, c);
- } else {
+ } else { // 若非系统文件夹则在远程进行增加节点操作
doContentSync(Node.SYNC_ACTION_ADD_REMOTE, node, c);
}
- } else {
+ } else { // 警告,询问根目录文件夹失败
Log.w(TAG, "failed to query root folder");
}
- } finally {
+ } finally { // 结束操作之后,将指针指向内容关闭并将指针置空
if (c != null) {
c.close();
c = null;
@@ -391,8 +482,11 @@ public class GTaskManager {
}
// for call-note folder
+ // 对存放电话号码便签的文件夹的同步操作
try {
+ // 使指针指向文件夹的位置
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, "(_id=?)",
+ // 添加MIUI文件前缀
new String[] {
String.valueOf(Notes.ID_CALL_RECORD_FOLDER)
}, null);
@@ -406,18 +500,19 @@ public class GTaskManager {
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))
doContentSync(Node.SYNC_ACTION_UPDATE_REMOTE, node, c);
- } else {
+ } else { // 若非系统文件夹则在远程进行增加节点操作
doContentSync(Node.SYNC_ACTION_ADD_REMOTE, node, c);
}
}
- } else {
+ } else { // 警告,询问通讯便签文件夹失败
Log.w(TAG, "failed to query call note folder");
}
- } finally {
+ } finally { // 结束操作之后,将指针指向内容关闭并将指针置空
if (c != null) {
c.close();
c = null;
@@ -425,12 +520,15 @@ public class GTaskManager {
}
// for local existing folders
+ // 对于本地已存在的文件的操作
try {
+ // 使指针指向第一个文件夹的位置
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE,
"(type=? AND parent_id<>?)", new String[] {
String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER)
}, NoteColumns.TYPE + " DESC");
if (c != null) {
+ // 使指针遍历所有的文件夹
while (c.moveToNext()) {
gid = c.getString(SqlNote.GTASK_ID_COLUMN);
node = mGTaskHashMap.get(gid);
@@ -438,19 +536,21 @@ public class GTaskManager {
mGTaskHashMap.remove(gid);
mGidToNid.put(gid, c.getLong(SqlNote.ID_COLUMN));
mNidToGid.put(c.getLong(SqlNote.ID_COLUMN), gid);
+ // 更新同步类型
syncType = node.getSyncAction(c);
- } else {
+ } else { // 若本地增加了内容,则远程也要增加内容
if (c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == 0) {
// local add
syncType = Node.SYNC_ACTION_ADD_REMOTE;
- } else {
+ } else { // 若远程删除了内容,则本地也要删除内容
// remote delete
syncType = Node.SYNC_ACTION_DEL_LOCAL;
}
}
+ // 进行同步操作
doContentSync(syncType, node, c);
}
- } else {
+ } else { // 警告,询问已创建的文件夹失败
Log.w(TAG, "failed to query existing folder");
}
} finally {
@@ -461,6 +561,8 @@ public class GTaskManager {
}
// for remote add folders
+ // 对于在远程增添的内容,将其在本地同步
+ // 使用迭代器对远程增添的内容进行遍历
Iterator> iter = mGTaskListHashMap.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = iter.next();
@@ -468,14 +570,21 @@ public class GTaskManager {
node = entry.getValue();
if (mGTaskHashMap.containsKey(gid)) {
mGTaskHashMap.remove(gid);
+ // 进行本地增添操作
doContentSync(Node.SYNC_ACTION_ADD_LOCAL, node, null);
}
}
if (!mCancelled)
+ // 如果没有取消,在GTsk的客户端进行实例的提交更新
GTaskClient.getInstance().commitUpdate();
}
+ /**
+ * 功能:内容同步
+ * 方法:依据不同的同步类型去调用不同的函数,以达到本地与远程同步的实际操作
+ * @throws NetworkFailureException
+ */
private void doContentSync(int syncType, Node node, Cursor c) throws NetworkFailureException {
if (mCancelled) {
return;
@@ -483,13 +592,17 @@ public class GTaskManager {
MetaData meta;
if (c != null) {
+ // 根据不同的同步类型来选择不同的操作
switch (syncType) {
+ // 本地添加
case Node.SYNC_ACTION_ADD_LOCAL:
addLocalNode(node);
break;
+ // 远程添加
case Node.SYNC_ACTION_ADD_REMOTE:
addRemoteNode(node, c);
break;
+ // 本地删除
case Node.SYNC_ACTION_DEL_LOCAL:
meta = mMetaHashMap.get(c.getString(SqlNote.GTASK_ID_COLUMN));
if (meta != null) {
@@ -497,6 +610,7 @@ public class GTaskManager {
}
mLocalDeleteIdMap.add(c.getLong(SqlNote.ID_COLUMN));
break;
+ // 远程删除
case Node.SYNC_ACTION_DEL_REMOTE:
meta = mMetaHashMap.get(node.getGid());
if (meta != null) {
@@ -504,52 +618,72 @@ public class GTaskManager {
}
GTaskClient.getInstance().deleteNode(node);
break;
+ // 本地更新
case Node.SYNC_ACTION_UPDATE_LOCAL:
updateLocalNode(node, c);
break;
+ // 远程更新
case Node.SYNC_ACTION_UPDATE_REMOTE:
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:
break;
+ // 操作错误
case Node.SYNC_ACTION_ERROR:
+ // 抛出异常,未知的同步行为类型
default:
throw new ActionFailureException("unkown sync action type");
}
}
}
+ /**
+ * 功能:添加本地节点
+ * 参数:待添加的本地节点
+ */
private void addLocalNode(Node node) throws NetworkFailureException {
+ // 检查是否取消这次操作
if (mCancelled) {
return;
}
SqlNote sqlNote;
+ // 若待增添节点为任务列表中的节点,进一步操作
+ //(instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例。instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。)
if (node instanceof TaskList) {
+ // 在根目录中增加节点
if (node.getName().equals(
+ // 判断node节点的名字是否是MIUI系统文件夹的默认文件夹:preffix是访问页面的前缀,用来指定页面存放的文件夹,然后加上文件夹默认值。
GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT)) {
sqlNote = new SqlNote(mContext, Notes.ID_ROOT_FOLDER);
- } else if (node.getName().equals(
+ } else if (node.getName().equals( // 判断是否在存电话的文件夹里
GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_CALL_NOTE)) {
sqlNote = new SqlNote(mContext, Notes.ID_CALL_RECORD_FOLDER);
- } else {
+ } else { //若没有存放的文件夹,则将其放在根文件夹中
sqlNote = new SqlNote(mContext);
+ // 从本地任务列表中获取内容
sqlNote.setContent(node.getLocalJSONFromContent());
sqlNote.setParentId(Notes.ID_ROOT_FOLDER);
}
- } else {
+ } else { // 如果Node不在任务列表中,则删除不合法的节点和数据
sqlNote = new SqlNote(mContext);
+ // 从待增添节点中获取jsonobject对象
JSONObject js = node.getLocalJSONFromContent();
- try {
+ try { //异常判断
if (js.has(GTaskStringUtils.META_HEAD_NOTE)) {
+ // 获取对应便签的jsonobject对象
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
+ // 判断便签中是否有条目
if (note.has(NoteColumns.ID)) {
long id = note.getLong(NoteColumns.ID);
+ // 若便签条目的id已无效,在便签中将其删除
if (DataUtils.existInNoteDatabase(mContentResolver, id)) {
// the id is not available, have to create a new one
note.remove(NoteColumns.ID);
@@ -557,6 +691,7 @@ public class GTaskManager {
}
}
+ // 以下为判断便签中的数据条目
if (js.has(GTaskStringUtils.META_HEAD_DATA)) {
JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
for (int i = 0; i < dataArray.length(); i++) {
@@ -572,12 +707,15 @@ public class GTaskManager {
}
}
- } catch (JSONException e) {
+ } catch (JSONException e) { // 对于异常进行处理
+ // 获取异常类型和异常详细消息
Log.w(TAG, e.toString());
e.printStackTrace();
}
+ // 删除不合法的节点后,把js的内容更新到sqlNote中
sqlNote.setContent(js);
+ // 找到父任务的ID号,并作为sqlNote的父任务的ID,没有父任务则报错
Long parentId = mGidToNid.get(((Task) node).getParent().getGid());
if (parentId == null) {
Log.e(TAG, "cannot find task's parent id locally");
@@ -587,40 +725,59 @@ public class GTaskManager {
}
// create the local node
+ // 用getGid函数获取node节点的Gid,用于设置本地Gtask的ID
sqlNote.setGtaskId(node.getGid());
sqlNote.commit(false);
// update gid-nid mapping
+ // 更新gid与nid的映射表
mGidToNid.put(node.getGid(), sqlNote.getId());
mNidToGid.put(sqlNote.getId(), node.getGid());
// update meta
+ //更新远程的数据
updateRemoteMeta(node.getGid(), sqlNote);
}
+ /**
+ * 功能:更新本地节点
+ * 参数:一个是待更新的节点,一个是指向待增加位置的指针
+ * @throws NetworkFailureException
+ */
private void updateLocalNode(Node node, Cursor c) throws NetworkFailureException {
if (mCancelled) {
return;
}
+ // 新建一个sql节点并将内容存储进Node中
SqlNote sqlNote;
// update the note locally
sqlNote = new SqlNote(mContext, c);
+ // 利用待更新节点中的内容对数据库节点进行设置
sqlNote.setContent(node.getLocalJSONFromContent());
+ // 设置父任务的ID
Long parentId = (node instanceof Task) ? mGidToNid.get(((Task) node).getParent().getGid())
: new Long(Notes.ID_ROOT_FOLDER);
+ // 当不能找到父任务id时报错
if (parentId == null) {
Log.e(TAG, "cannot find task's parent id locally");
throw new ActionFailureException("cannot update local node");
}
+ // 把上面更新的父任务ID赋值给sqlNote
sqlNote.setParentId(parentId.longValue());
sqlNote.commit(true);
// update meta info
+ // 更新远程的节点信息
updateRemoteMeta(node.getGid(), sqlNote);
}
+ /**
+ * 功能:增加远程节点
+ * 参数:一个是待更新的节点,一个是指向待增加位置的指针
+ * @throws NetworkFailureException
+ */
private void addRemoteNode(Node node, Cursor c) throws NetworkFailureException {
if (mCancelled) {
return;
@@ -630,6 +787,7 @@ public class GTaskManager {
Node n;
// update remotely
+ // 如果sqlNote是节点类型,则设置好它的参数并更新哈希表,再把节点更新到远程数据里
if (sqlNote.isNoteType()) {
Task task = new Task();
task.setContentByLocalJSON(sqlNote.getContent());
@@ -650,6 +808,7 @@ public class GTaskManager {
TaskList tasklist = null;
// we need to skip folder if it has already existed
+ // 如果文件夹已经存在则需要跳过,否则根据sqlNote的ID创建新的文件夹
String folderName = GTaskStringUtils.MIUI_FOLDER_PREFFIX;
if (sqlNote.getId() == Notes.ID_ROOT_FOLDER)
folderName += GTaskStringUtils.FOLDER_DEFAULT;
@@ -658,12 +817,14 @@ public class GTaskManager {
else
folderName += sqlNote.getSnippet();
+ // 使用迭代器对gtasklist进行遍历
Iterator> iter = mGTaskListHashMap.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = iter.next();
String gid = entry.getKey();
TaskList list = entry.getValue();
+ // 若寻找到的任务列表已存在,则直接在里面更新
if (list.getName().equals(folderName)) {
tasklist = list;
if (mGTaskHashMap.containsKey(gid)) {
@@ -674,6 +835,7 @@ public class GTaskManager {
}
// no match we can add now
+ // 若找不到任务列表,则创建一个新的任务列表
if (tasklist == null) {
tasklist = new TaskList();
tasklist.setContentByLocalJSON(sqlNote.getContent());
@@ -684,42 +846,57 @@ public class GTaskManager {
}
// update local note
+ // 更新本地节点
sqlNote.setGtaskId(n.getGid());
sqlNote.commit(false);
sqlNote.resetLocalModified();
sqlNote.commit(true);
// gid-id mapping
+ // 更新gid与nid的映射表
mGidToNid.put(n.getGid(), sqlNote.getId());
mNidToGid.put(sqlNote.getId(), n.getGid());
}
+ /**
+ * 功能:更新远程结点
+ * 参数:node是要更新的结点,c是数据库的指针
+ * @throws NetworkFailureException
+ */
private void updateRemoteNode(Node node, Cursor c) throws NetworkFailureException {
if (mCancelled) {
return;
}
+ // 在指针指向处创建一个新的节点
SqlNote sqlNote = new SqlNote(mContext, c);
// update remotely
+ // 对远程GTask的节点进行更新
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();
+ // 获取上一级任务列表的gid
String curParentGid = mNidToGid.get(sqlNote.getParentId());
if (curParentGid == null) {
Log.e(TAG, "cannot find task's parent tasklist");
throw new ActionFailureException("cannot update remote task");
}
+ // 通过HashMap找到对应Gid的TaskList
TaskList curParentList = mGTaskListHashMap.get(curParentGid);
+ // 若两个上一级任务列表不一致,进行任务的移动,从之前的任务列表中移动到该列表中
if (preParentList != curParentList) {
preParentList.removeChildTask(task);
curParentList.addChildTask(task);
@@ -728,13 +905,23 @@ public class GTaskManager {
}
// clear local modified flag
+ // 清空本地已经被修改的标志
sqlNote.resetLocalModified();
sqlNote.commit(true);
}
+ /**
+ * 功能:更新远程结点的数据(与上一个函数不同的是这里只更新数据)
+ * 参数:gid是要更新的数据对应的在数据库中的结点id,sqlnote用于获得数据内容
+ * @throws NetworkFailureException
+ */
private void updateRemoteMeta(String gid, SqlNote sqlNote) throws NetworkFailureException {
+ // 对节点的类型进行判断,只有节点类型符合要求才进一步操作
if (sqlNote != null && sqlNote.isNoteType()) {
+ // 通过gid获取元数据
MetaData metaData = mMetaHashMap.get(gid);
+ // 如果数据不为空,则设置好元,从客户端获取更新元节点后的信息内容
+ // 否则新建一个元并设置好参数,设置好meta链表的子节点,更新哈希表,用户端获取用元数据创建任务后的信息内容
if (metaData != null) {
metaData.setMeta(gid, sqlNote.getContent());
GTaskClient.getInstance().addUpdateNode(metaData);
@@ -748,12 +935,17 @@ public class GTaskManager {
}
}
+ /**
+ * 功能:刷新本地同步的ID
+ * @throws NetworkFailureException
+ */
private void refreshLocalSyncId() throws NetworkFailureException {
if (mCancelled) {
return;
}
// get the latest gtask list
+ // 获取最新的gtask list
mGTaskHashMap.clear();
mGTaskListHashMap.clear();
mMetaHashMap.clear();
@@ -761,6 +953,7 @@ public class GTaskManager {
Cursor c = null;
try {
+ // c作为光标定位,用query进行查询
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE,
"(type<>? AND parent_id<>?)", new String[] {
String.valueOf(Notes.TYPE_SYSTEM), String.valueOf(Notes.ID_TRASH_FOLER)
@@ -782,9 +975,10 @@ public class GTaskManager {
}
}
} else {
+ // 警告,询问本地待同步更新的便签 id 失败
Log.w(TAG, "failed to query local note to refresh sync id");
}
- } finally {
+ } finally { // 结束操作之后,将指针指向内容关闭并将指针置空
if (c != null) {
c.close();
c = null;
@@ -792,10 +986,16 @@ public class GTaskManager {
}
}
+ /**
+ * 功能:获取同步账户,通过客户端调用函数获取名字作为信息返回
+ */
public String getSyncAccount() {
return GTaskClient.getInstance().getSyncAccount().name;
}
+ /**
+ * 功能:取消同步,置mCancelled为true
+ */
public void cancelSync() {
mCancelled = true;
}
diff --git a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/remote/GTaskSyncService.java b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/remote/GTaskSyncService.java
index cca36f7..e98b563 100644
--- a/src/Notes-master/app/src/main/java/net/micode/notes/gtask/remote/GTaskSyncService.java
+++ b/src/Notes-master/app/src/main/java/net/micode/notes/gtask/remote/GTaskSyncService.java
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+// Service是Android四大组件之一,通常用作在后台处理耗时的逻辑,不用与用户进行交互,即使应用被销毁依然可以继续工作。
+
package net.micode.notes.gtask.remote;
import android.app.Activity;
@@ -23,25 +25,48 @@ import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
+/**【1】定义:GTaskASyncService类继承于应用组件Service。
+ * 【2】功能:提供GTask的同步服务。
+ * 【3】主要方法:
+ * private void startSync () ——启动一个同步工作
+ * private void cancelSync () ——取消同步
+ * public void onCreate ()
+ * public int onStartCommand (Intent intent, int flags, int startId) ——service生命周期的组成部分,相当于重启service(比如在被暂停之后),而不是创建一个新的service
+ * public void onLowMemory ()—— 在没有内存的情况下,如果存在service则结束该service
+ * public IBinder onBind ()
+ * public void sendBroadcast (String msg)——发送同步的相关通知
+ * public static void startSync (Activity activity)
+ * public static void cancelSync (Context context)
+ * public static boolean isSyncing ()——判读是否在进行同步
+ * public static String getProgressString ()—— 获取当前进度的信息
+ */
public class GTaskSyncService extends Service {
+ // 定义了一系列静态变量,用来表示同步操作的状态。
+ //(1)同步行为类型
public final static String ACTION_STRING_NAME = "sync_action_type";
+ //(2)同步状态:用数字0、1、2分别表示开始同步、取消同步、同步无效
public final static int ACTION_START_SYNC = 0;
-
public final static int ACTION_CANCEL_SYNC = 1;
-
public final static int ACTION_INVALID = 2;
+ //(3)服务广播的名称
public final static String GTASK_SERVICE_BROADCAST_NAME = "net.micode.notes.gtask.remote.gtask_sync_service";
+ //(4)表示正在同步中
public final static String GTASK_SERVICE_BROADCAST_IS_SYNCING = "isSyncing";
+ //(5)进程消息
public final static String GTASK_SERVICE_BROADCAST_PROGRESS_MSG = "progressMsg";
private static GTaskASyncTask mSyncTask = null;
private static String mSyncProgress = "";
+ /**
+ * 功能:开始同步操作
+ * 方法:如果当前没有同步工作,则申请一个task并把指针指向新任务,广播并执行。如果有同步工作则不做操作。
+ */
private void startSync() {
if (mSyncTask == null) {
mSyncTask = new GTaskASyncTask(this, new GTaskASyncTask.OnCompleteListener() {
@@ -56,6 +81,10 @@ public class GTaskSyncService extends Service {
}
}
+ /**
+ * 功能:取消同步操作
+ * 方法: 判断同步的任务是否为空。如果正在同步,则取消同步工作。
+ */
private void cancelSync() {
if (mSyncTask != null) {
mSyncTask.cancelSync();
@@ -63,13 +92,22 @@ public class GTaskSyncService extends Service {
}
@Override
+ /**
+ * 功能:初始化任务
+ * 方法:直接把mSyncTask指针的值置空
+ */
public void onCreate() {
mSyncTask = null;
}
@Override
+ /**
+ * 功能:告诉系统如何重启服务,如判断是否异常终止后重新启动,在何种情况下异常终止等。
+ */
public int onStartCommand(Intent intent, int flags, int startId) {
+ // Bundle类可携带数据,用于存放key-value明值对应形式的值。
Bundle bundle = intent.getExtras();
+ // 判断当前的同步状态,根据开始或取消,执行对应操作
if (bundle != null && bundle.containsKey(ACTION_STRING_NAME)) {
switch (bundle.getInt(ACTION_STRING_NAME, ACTION_INVALID)) {
case ACTION_START_SYNC:
@@ -87,16 +125,26 @@ public class GTaskSyncService extends Service {
}
@Override
+ /**
+ * 功能:内存不足的处理函数
+ * 方法:如果当前有任务在执行,则调用cancelSync ()取消这个任务
+ */
public void onLowMemory() {
if (mSyncTask != null) {
mSyncTask.cancelSync();
}
}
+ /**
+ * 功能: service服务中的绑定操作
+ */
public IBinder onBind(Intent intent) {
return null;
}
+ /**
+ * 功能:执行发送广播内容的操作
+ */
public void sendBroadcast(String msg) {
mSyncProgress = msg;
Intent intent = new Intent(GTASK_SERVICE_BROADCAST_NAME);
@@ -105,6 +153,9 @@ public class GTaskSyncService extends Service {
sendBroadcast(intent);
}
+ /**
+ * 功能:开始同步
+ */
public static void startSync(Activity activity) {
GTaskManager.getInstance().setActivityContext(activity);
Intent intent = new Intent(activity, GTaskSyncService.class);
@@ -112,16 +163,25 @@ public class GTaskSyncService extends Service {
activity.startService(intent);
}
+ /**
+ * 功能:取消同步
+ */
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);
}
+ /**
+ * 功能:判断此时是否处在同步状态
+ */
public static boolean isSyncing() {
return mSyncTask != null;
}
+ /**
+ * 功能:返回当前的执行状态
+ */
public static String getProgressString() {
return mSyncProgress;
}
diff --git a/src/Notes-master/local.properties b/src/Notes-master/local.properties
index 11be78c..fd1d5d6 100644
--- a/src/Notes-master/local.properties
+++ b/src/Notes-master/local.properties
@@ -4,5 +4,5 @@
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
-#Sat Nov 21 11:26:00 CST 2020
-sdk.dir=D\:\\Sdk
+#Wed Dec 02 20:10:32 CST 2020
+sdk.dir=C\:\\Users\\95459\\AppData\\Local\\Android\\Sdk