（1）	类名：gtask>data>MetaData
      代码注释: 
       
         
/*
 * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// 包名，表示这个类属于gtask.data包
package net.micode.notes.gtask.data;

// 导入必要的类
import android.database.Cursor;
import android.util.Log;

import net.micode.notes.tool.GTaskStringUtils;

import org.json.JSONException;
import org.json.JSONObject;

// MetaData类继承自Task类
public class MetaData extends Task {
    // 类的简单名称，用于日志打印
    private final static String TAG = MetaData.class.getSimpleName();

    // 成员变量，用于存储与任务相关的gid
    private String mRelatedGid = null;

    // 设置元数据的方法，接收gid和metaInfo对象
    public void setMeta(String gid, JSONObject metaInfo) {
        try {
            // 将gid放入metaInfo对象中
            metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid);
        } catch (JSONException e) {
            // 如果发生错误，打印错误日志
            Log.e(TAG, "failed to put related gid");
        }
        // 将metaInfo对象转换为字符串并保存
        setNotes(metaInfo.toString());
        // 设置任务的名称
        setName(GTaskStringUtils.META_NOTE_NAME);
    }

    // 获取与任务相关的gid
    public String getRelatedGid() {
        return mRelatedGid;
    }

    // 重写方法，判断任务是否值得保存
    @Override
    public boolean isWorthSaving() {
        // 如果笔记内容不为空，则值得保存
        return getNotes() != null;
    }

    // 重写方法，根据远程JSON设置内容
    @Override
    public void setContentByRemoteJSON(JSONObject js) {
        // 调用父类的方法
        super.setContentByRemoteJSON(js);
        // 如果笔记内容不为空，则解析笔记内容
        if (getNotes() != null) {
            try {
                // 将笔记内容转换为JSONObject
                JSONObject metaInfo = new JSONObject(getNotes().trim());
                // 从JSONObject中获取相关的gid
                mRelatedGid = metaInfo.getString(GTaskStringUtils.META_HEAD_GTASK_ID);
            } catch (JSONException e) {
                // 如果发生错误，打印警告日志并设置mRelatedGid为null
                Log.w(TAG, "failed to get related gid");
                mRelatedGid = null;
            }
        }
    }

    // 重写方法，根据本地JSON设置内容
    // 此方法不应该被调用，如果被调用则抛出非法访问错误
    @Override
    public void setContentByLocalJSON(JSONObject js) {
        throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called");
    }

    // 重写方法，从内容中获取本地JSON
    // 此方法不应该被调用，如果被调用则抛出非法访问错误
    @Override
    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");
    }

    // 类定义结束
}
 

（2）	类名：gtask>data>Noda
        代码注释：
         
/*
 * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.micode.notes.gtask.data;

import android.database.Cursor;
import org.json.JSONObject;

// 定义一个抽象类Node，用于表示任务列表中的节点
public abstract class Node {
    // 定义同步操作常量
    public static final int SYNC_ACTION_NONE = 0; // 无需同步操作
    public static final int SYNC_ACTION_ADD_REMOTE = 1; // 添加远程操作
    public static final int SYNC_ACTION_ADD_LOCAL = 2; // 添加本地操作
    public static final int SYNC_ACTION_DEL_REMOTE = 3; // 删除远程操作
    public static final int SYNC_ACTION_DEL_LOCAL = 4; // 删除本地操作
    public static final int SYNC_ACTION_UPDATE_REMOTE = 5; // 更新远程操作
    public static final int SYNC_ACTION_UPDATE_LOCAL = 6; // 更新本地操作
    public static final int SYNC_ACTION_UPDATE_CONFLICT = 7; // 更新冲突操作
    public static final int SYNC_ACTION_ERROR = 8; // 同步错误操作

    // 节点属性
    private String mGid; // 节点的全局标识符
    private String mName; // 节点的名称
    private long mLastModified; // 节点最后修改时间
    private boolean mDeleted; // 节点是否被删除

    // Node类的构造函数
    public Node() {
        mGid = null;
        mName = "";
        mLastModified = 0;
        mDeleted = false;
    }

    // 抽象方法，用于获取创建操作的JSON对象
    public abstract JSONObject getCreateAction(int actionId);

    // 抽象方法，用于获取更新操作的JSON对象
    public abstract JSONObject getUpdateAction(int actionId);

    // 抽象方法，用于根据远程JSON设置内容
    public abstract void setContentByRemoteJSON(JSONObject js);

    // 抽象方法，用于根据本地JSON设置内容
    public abstract void setContentByLocalJSON(JSONObject js);

    // 抽象方法，用于从内容中获取本地JSON
    public abstract JSONObject getLocalJSONFromContent();

    // 抽象方法，用于获取同步操作类型
    public abstract int getSyncAction(Cursor c);

    // 设置节点的全局标识符
    public void setGid(String gid) {
        this.mGid = gid;
    }

    // 设置节点的名称
    public void setName(String name) {
        this.mName = name;
    }

    // 设置节点最后修改时间
    public void setLastModified(long lastModified) {
        this.mLastModified = lastModified;
    }

    // 设置节点是否被删除
    public void setDeleted(boolean deleted) {
        this.mDeleted = deleted;
    }

    // 获取节点的全局标识符
    public String getGid() {
        return this.mGid;
    }

    // 获取节点的名称
    public String getName() {
        return this.mName;
    }

    // 获取节点最后修改时间
    public long getLastModified() {
        return this.mLastModified;
    }

    // 获取节点是否被删除
    public boolean getDeleted() {
        return this.mDeleted;
    }

}
 
（3）	类名：gtask>data>sqlData
     代码注释：
/*
 * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// 包名
package net.micode.notes.gtask.data;

// 导入必要的类
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;

import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.DataConstants;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.NotesDatabaseHelper.TABLE;
import net.micode.notes.gtask.exception.ActionFailureException;

import org.json.JSONException;
import org.json.JSONObject;

// SqlData类，用于处理数据操作
public class SqlData {
    // 日志标签
    private static final String TAG = SqlData.class.getSimpleName();

    // 无效ID常量
    private static final int INVALID_ID = -99999;

    // 数据列数组
    public static final String[] PROJECTION_DATA = new String[] {
            DataColumns.ID, DataColumns.MIME_TYPE, DataColumns.CONTENT, DataColumns.DATA1,
            DataColumns.DATA3
    };

    // 数据列索引
    public static final int DATA_ID_COLUMN = 0;
    public static final int DATA_MIME_TYPE_COLUMN = 1;
    public static final int DATA_CONTENT_COLUMN = 2;
    public static final int DATA_CONTENT_DATA_1_COLUMN = 3;
    public static final int DATA_CONTENT_DATA_3_COLUMN = 4;

    // 成员变量
    private ContentResolver mContentResolver;
    private boolean mIsCreate;
    private long mDataId;
    private String mDataMimeType;
    private String mDataContent;
    private long mDataContentData1;
    private String mDataContentData3;
    private ContentValues mDiffDataValues;

    // 构造函数，用于创建新的SqlData实例
    public SqlData(Context context) {
        mContentResolver = context.getContentResolver();
        mIsCreate = true;
        mDataId = INVALID_ID;
        mDataMimeType = DataConstants.NOTE;
        mDataContent = "";
        mDataContentData1 = 0;
        mDataContentData3 = "";
        mDiffDataValues = new ContentValues();
    }

    // 构造函数，用于从Cursor加载现有数据
    public SqlData(Context context, Cursor c) {
        mContentResolver = context.getContentResolver();
        mIsCreate = false;
        loadFromCursor(c);
        mDiffDataValues = new ContentValues();
    }

    // 从Cursor加载数据到成员变量
    private void loadFromCursor(Cursor c) {
        mDataId = c.getLong(DATA_ID_COLUMN);
        mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN);
        mDataContent = c.getString(DATA_CONTENT_COLUMN);
        mDataContentData1 = c.getLong(DATA_CONTENT_DATA_1_COLUMN);
        mDataContentData3 = c.getString(DATA_CONTENT_DATA_3_COLUMN);
    }
}
public void setContent(JSONObject js) throws JSONException {
    // 从JSONObject中获取dataId，如果不存在则设置为INVALID_ID
    long dataId = js.has(DataColumns.ID) ? js.getLong(DataColumns.ID) : INVALID_ID;
    // 如果是创建新记录或者dataId有变化，则将新的dataId放入差异值集合中
    if (mIsCreate || mDataId != dataId) {
        mDiffDataValues.put(DataColumns.ID, dataId);
    }
    // 更新mDataId为新的dataId
    mDataId = dataId;

    // 从JSONObject中获取dataMimeType，如果不存在则设置为默认值
    String dataMimeType = js.has(DataColumns.MIME_TYPE) ? js.getString(DataColumns.MIME_TYPE)
            : DataConstants.NOTE;
    // 如果是创建新记录或者dataMimeType有变化，则将新的dataMimeType放入差异值集合中
    if (mIsCreate || !mDataMimeType.equals(dataMimeType)) {
        mDiffDataValues.put(DataColumns.MIME_TYPE, dataMimeType);
    }
    // 更新mDataMimeType为新的dataMimeType
    mDataMimeType = dataMimeType;

    // 从JSONObject中获取dataContent，如果不存在则设置为空字符串
    String dataContent = js.has(DataColumns.CONTENT) ? js.getString(DataColumns.CONTENT) : "";
    // 如果是创建新记录或者dataContent有变化，则将新的dataContent放入差异值集合中
    if (mIsCreate || !mDataContent.equals(dataContent)) {
        mDiffDataValues.put(DataColumns.CONTENT, dataContent);
    }
    // 更新mDataContent为新的dataContent
    mDataContent = dataContent;

    // 从JSONObject中获取dataContentData1，如果不存在则设置为0
    long dataContentData1 = js.has(DataColumns.DATA1) ? js.getLong(DataColumns.DATA1) : 0;
    // 如果是创建新记录或者dataContentData1有变化，则将新的dataContentData1放入差异值集合中
    if (mIsCreate || mDataContentData1 != dataContentData1) {
        mDiffDataValues.put(DataColumns.DATA1, dataContentData1);
    }
    // 更新mDataContentData1为新的dataContentData1
    mDataContentData1 = dataContentData1;

    // 从JSONObject中获取dataContentData3，如果不存在则设置为空字符串
    String dataContentData3 = js.has(DataColumns.DATA3) ? js.getString(DataColumns.DATA3) : "";
    // 如果是创建新记录或者dataContentData3有变化，则将新的dataContentData3放入差异值集合中
    if (mIsCreate || !mDataContentData3.equals(dataContentData3)) {
        mDiffDataValues.put(DataColumns.DATA3, dataContentData3);
    }
    // 更新mDataContentData3为新的dataContentData3
    mDataContentData3 = dataContentData3;
}

public JSONObject getContent() throws JSONException {
    // 如果正在创建新记录，则记录错误并返回null
    if (mIsCreate) {
        Log.e(TAG, "it seems that we haven't created this in database yet");
        return null;
    }
    // 创建一个新的JSONObject并填充当前对象的属性
    JSONObject js = new JSONObject();
    js.put(DataColumns.ID, mDataId);
    js.put(DataColumns.MIME_TYPE, mDataMimeType);
    js.put(DataColumns.CONTENT, mDataContent);
    js.put(DataColumns.DATA1, mDataContentData1);
    js.put(DataColumns.DATA3, mDataContentData3);
    return js;
}

public void commit(long noteId, boolean validateVersion, long version) {
    // 如果是创建新记录
    if (mIsCreate) {
        // 如果dataId无效且差异值集合中包含dataId，则移除它
        if (mDataId == INVALID_ID && mDiffDataValues.containsKey(DataColumns.ID)) {
            mDiffDataValues.remove(DataColumns.ID);
        }
        // 将noteId放入差异值集合中
        mDiffDataValues.put(DataColumns.NOTE_ID, noteId);
        // 插入新记录并获取URI
        Uri uri = mContentResolver.insert(Notes.CONTENT_DATA_URI, mDiffDataValues);
        // 从URI中提取noteId
        try {
            mDataId = Long.valueOf(uri.getPathSegments().get(1));
        } catch (NumberFormatException e) {
            // 记录错误并抛出异常
            Log.e(TAG, "Get note id error :" + e.toString());
            throw new ActionFailureException("create note failed");
        }
    } else {
        // 如果差异值集合不为空
        if (mDiffDataValues.size() > 0) {
            int result = 0;
            // 如果不需要验证版本，则更新记录
            if (!validateVersion) {
                result = mContentResolver.update(ContentUris.withAppendedId(
                        Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, null, null);
            } else {
                // 如果需要验证版本，则执行带条件的更新
                result = mContentResolver.update(ContentUris.withAppendedId(
                        Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues,
                        " ? in (SELECT " + NoteColumns.ID + " FROM " + TABLE.NOTE
                                + " WHERE " + NoteColumns.VERSION + "=?)", new String[] {
                                String.valueOf(noteId), String.valueOf(version)
                        });
            }
            // 如果更新结果为0，则记录警告信息
            if (result == 0) {
                Log.w(TAG, "there is no update. maybe user updates note when syncing");
            }
        }
    }

    // 清空差异值集合
    mDiffDataValues.clear();
    // 设置创建标志为false
    mIsCreate = false;
}

public long getId() {
    // 返回当前对象的dataId
    return mDataId;
}
（4）	类名：gtask>data>SqlNote
     代码注释：
      
package net.micode.notes.gtask.data;

import android.appwidget.AppWidgetManager;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.gtask.exception.ActionFailureException;
import net.micode.notes.tool.GTaskStringUtils;
import net.micode.notes.tool.ResourceParser;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;

public class SqlNote {
    private static final String TAG = SqlNote.class.getSimpleName(); // 日志标签，用于输出日志信息
    private static final int INVALID_ID = -99999; // 无效的ID常量，用于标识无效的笔记ID

    // 笔记投影数组，定义了从数据库中获取笔记信息时需要的列
    public static final String[] PROJECTION_NOTE = new String[]{
        NoteColumns.ID, NoteColumns.ALERTED_DATE, NoteColumns.BG_COLOR_ID,
        NoteColumns.CREATED_DATE, NoteColumns.HAS_ATTACHMENT, NoteColumns.MODIFIED_DATE,
        NoteColumns.NOTES_COUNT, NoteColumns.PARENT_ID, NoteColumns.SNIPPET, NoteColumns.TYPE,
        NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE, NoteColumns.SYNC_ID,
        NoteColumns.LOCAL_MODIFIED, NoteColumns.ORIGIN_PARENT_ID, NoteColumns.GTASK_ID,
        NoteColumns.VERSION
    };

    // 各列的索引常量
    public static final int ID_COLUMN = 0;
    public static final int ALERTED_DATE_COLUMN = 1;
    public static final int BG_COLOR_ID_COLUMN = 2;
    public static final int CREATED_DATE_COLUMN = 3;
    public static final int HAS_ATTACHMENT_COLUMN = 4;
    public static final int MODIFIED_DATE_COLUMN = 5;
    public static final int NOTES_COUNT_COLUMN = 6;
    public static final int PARENT_ID_COLUMN = 7;
    public static final int SNIPPET_COLUMN = 8;
    public static final int TYPE_COLUMN = 9;
    public static final int WIDGET_ID_COLUMN = 10;
    public static final int WIDGET_TYPE_COLUMN = 11;
    public static final int SYNC_ID_COLUMN = 12;
    public static final int LOCAL_MODIFIED_COLUMN = 13;
    public static final int ORIGIN_PARENT_ID_COLUMN = 14;
    public static final int GTASK_ID_COLUMN = 15;
    public static final int VERSION_COLUMN = 16;

    private Context mContext; // 上下文对象
    private ContentResolver mContentResolver; // 内容解析器，用于与数据库交互
    private boolean mlsCreate; // 标识是否为新创建的笔记
    private long mld; // 笔记ID
    private long mAlertDate; // 提醒日期
    private int mBgColorld; // 背景颜色ID
    private long mCreatedDate; // 创建日期
    private int mHasAttachment; // 是否有附件
    private long mModifiedDate; // 修改日期
    private long mParentld; // 父笔记ID
    private String msSnippet; // 笔记摘要
    private int mType; // 笔记类型
    private int mWidgetld; // 小部件ID
    private int mWidgetType; // 小部件类型
    private long moOriginParent; // 原始父笔记ID
    private long mVversion; // 版本号
    private ContentValues mDiffNoteValues; // 存储笔记差异的ContentValues对象
    private ArrayList<SqlData> mDataList; // 存储笔记数据的列表

    // 构造函数，用于创建一个新的笔记
    public SqlNote(Context context) {
        mContext = context;
        mContentResolver = context.getContentResolver();
        mlsCreate = true;
        mld = INVALID_ID;
        mAlertDate = 0;
        mBgColorld = ResourceParser.getDefaultBgld(context);
        mCreatedDate = System.currentTimeMillis();
        mHasAttachment = 0;
        mModifiedDate = System.currentTimeMillis();
        mParentld = 0;
        msSnippet = "";
        mType = Notes.TYPE_NOTE;
        mWidgetld = AppWidgetManager.INVALID_APPWIDGET_ID;
        mWidgetType = Notes.TYPE_WIDGET_INVALIDE;
        moOriginParent = 0;
        mVversion = 0;
        mDiffNoteValues = new ContentValues();
        mDataList = new ArrayList<>();
    }

    // 构造函数，用于从Cursor中加载笔记
    public SqlNote(Context context, Cursor c) {
        mContext = context;
        mContentResolver = context.getContentResolver();
        mlsCreate = false;
        loadFromCursor(c);
        mDataList = new ArrayList<>();
        if (mType == Notes.TYPE_NOTE) {
            loadDataContent();
        }
        mDiffNoteValues = new ContentValues();
    }

    // 构造函数，用于从ID加载笔记
    public SqlNote(Context context, long id) {
        mContext = context;
        mContentResolver = context.getContentResolver();
        mlsCreate = false;
        loadFromCursor(id);
        mDataList = new ArrayList<>();
        if (mType == Notes.TYPE_NOTE) {
            loadDataContent();
        }
        mDiffNoteValues = new ContentValues();
    }

    // 从Cursor中加载数据
    private void loadFromCursor(long id) {
        Cursor c = null;
        try {
            c = mContentResolver.query(Notes.CONTENT_NOTE_URI, PROJECTION_NOTE, "_id=?", new String[]{String.valueOf(id)}, null);
            if (c != null && c.moveToFirst()) {
                loadFromCursor(c);
            } else {
                Log.w(TAG, "loadFromCursor: cursor is null");
            }
        } finally {
            if (c != null) {
                c.close();
            }
        }
    }

    // 从Cursor中加载数据
    private void loadFromCursor(Cursor c) {
        mld = c.getLong(ID_COLUMN);
        mAlertDate = c.getLong(ALERTED_DATE_COLUMN);
        mBgColorld = c.getInt(BG_COLOR_ID_COLUMN);
        mCreatedDate = c.getLong(CREATED_DATE_COLUMN);
        mHasAttachment = c.getInt(HAS_ATTACHMENT_COLUMN);
        mModifiedDate = c.getLong(MODIFIED_DATE_COLUMN);
        mParentld = c.getLong(PARENT_ID_COLUMN);
        msSnippet = c.getString(SNIPPET_COLUMN);
        mType = c.getInt(TYPE_COLUMN);
        mWidgetld = c.getInt(WIDGET_ID_COLUMN);
        mWidgetType = c.getInt(WIDGET_TYPE_COLUMN);
        mVversion = c.getLong(VERSION_COLUMN);
    }

    // 加载数据内容
    private void loadDataContent() {
        Cursor c = null;
        mDataList.clear();
        try {
            c = mContentResolver.query(Notes.CONTENT_DATA_URI, SqlData.PROJECTION_DATA, "note_id=?", new String[]{String.valueOf(mld)}, null);
            if (c != null) {
                if (c.getCount() == 0) {
                    Log.w(TAG, "it seems that the note has no data");
                    return;
                }
                while (c.moveToNext()) {
                    SqlData data = new SqlData(mContext, c);
                    mDataList.add(data);
                }
            } else {
                Log.w(TAG, "loadDataContent: cursor is null");
            }
        } finally {
            if (c != null) {
                c.close();
            }
        }
    }

    // 设置笔记内容
    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");
                return false;
            } else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) {
                // For folder, we can only update the snippet and type
                String snippet = note.has(NoteColumns.SNIPPET) ? note.getString(NoteColumns.SNIPPET) : "";
                if (mlsCreate || !msSnippet.equals(snippet)) {
                    mDiffNoteValues.put(NoteColumns.SNIPPET, snippet);
                }
                mSnippet = snippet;
                int type = note.getInt(NoteColumns.TYPE) == Notes.TYPE_NOTE ? Notes.TYPE_NOTE : type;
                if (mlsCreate || mType != type) {
                    mDiffNoteValues.put(NoteColumns.TYPE, type);
                }
                mType = type;
            } 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 (mlsCreate || mld != id) {
                    mDiffNoteValues.put(NoteColumns.ID, id);
                }
                mld = id;
                long alertDate = note.has(NoteColumns.ALERTED_DATE) ? note.getLong(NoteColumns.ALERTED_DATE) : 0;
                if (mlsCreate || mAlertDate != alertDate) {
                    mDiffNoteValues.put(NoteColumns.ALERTED_DATE, alertDate);
                }
                mAlertDate = alertDate;
                int bgColorld = note.has(NoteColumns.BG_COLOR_ID) ? note.getInt(NoteColumns.BG_COLOR_ID) : ResourceParser.getDefaultBgld(mContext);
                if (mlsCreate || mBgColorld != bgColorld) {
                    mDiffNoteValues.put(NoteColumns.BG_COLOR_ID, bgColorld);
                }
                mBgcolorld = bgColorld;
                long createDate = note.has(NoteColumns.CREATED_DATE) ? note.getLong(NoteColumns.CREATED_DATE
                createDate = note.has(NoteColumns.CREATED_DATE) ? note.getLong(NoteColumns.CREATED_DATE) : System.currentTimeMillis();
                if (mlsCreate || mCreatedDate != createDate) {
                    mDiffNoteValues.put(NoteColumns.CREATED_DATE, createDate);
                }
                mCreatedDate = createDate;
                int hasAttachment = note.has(NoteColumns.HAS_ATTACHMENT) ? note.getInt(NoteColumns.HAS_ATTACHMENT) : 0;
                if (mlsCreate || mHasAttachment != hasAttachment) {
                    mDiffNoteValues.put(NoteColumns.HAS_ATTACHMENT, hasAttachment);
                }
                mHasAttachment = hasAttachment;
                long modifiedDate = note.has(NoteColumns.MODIFIED_DATE) ? note.getLong(NoteColumns.MODIFIED_DATE) : System.currentTimeMillis();
                if (mlsCreate || mModifiedDate != modifiedDate) {
                    mDiffNoteValues.put(NoteColumns.MODIFIED_DATE, modifiedDate);
                }
                mModifiedDate = modifiedDate;
                long parentld = note.has(NoteColumns.PARENT_ID) ? note.getLong(NoteColumns.PARENT_ID) : 0;
                if (mlsCreate || mParentld != parentld) {
                    mDiffNoteValues.put(NoteColumns.PARENT_ID, parentld);
                }
                mParentld = parentld;
                String snippet = note.has(NoteColumns.SNIPPET) ? note.getString(NoteColumns.SNIPPET) : "";
                if (mlsCreate || !msSnippet.equals(snippet)) {
                    mDiffNoteValues.put(NoteColumns.SNIPPET, snippet);
                }
                mSnippet = snippet;
                int type = note.getInt(NoteColumns.TYPE) == Notes.TYPE_NOTE ? Notes.TYPE_NOTE : type;
                if (mlsCreate || mType != type) {
                    mDiffNoteValues.put(NoteColumns.TYPE, type);
                }
                mType = type;
                int widgetld = note.has(NoteColumns.WIDGET_ID) ? note.getInt(NoteColumns.WIDGET_ID) : AppWidgetManager.INVALID_APPWIDGET_ID;
                if (mlsCreate || mWidgetld != widgetld) {
                    mDiffNoteValues.put(NoteColumns.WIDGET_ID, widgetld);
                }
                mWidgetld = widgetld;
                int widgetType = note.has(NoteColumns.WIDGET_TYPE) ? note.getInt(NoteColumns.WIDGET_TYPE) : Notes.TYPE_WIDGET_INVALIDE;
                if (mlsCreate || mWidgetType != widgetType) {
                    mDiffNoteValues.put(NoteColumns.WIDGET_TYPE, widgetType);
                }
                mWidgetType = widgetType;
                long originParent = note.has(NoteColumns.ORIGIN_PARENT_ID) ? note.getLong(NoteColumns.ORIGIN_PARENT_ID) : 0;
                if (mlsCreate || moOriginParent != originParent) {
                    mDiffNoteValues.put(NoteColumns.ORIGIN_PARENT_ID, originParent);
                }
                moOriginParent = originParent;
                for (int i = 0; i < dataArray.length(); i++) {
                    JSONObject data = dataArray.getJSONObject(i);
                    SqlData sqlData = null;
                    if (data.has(DataColumns.ID)) {
                        long datald = data.getLong(DataColumns.ID);
                        for (SqlData temp : mDataList) {
                            if (datald == temp.getld()) {
                                sqlData = temp;
                                break;
                            }
                        }
                    }
                    if (sqlData == null) {
                        sqlData = new SqlData(mContext);
                        mDataList.add(sqlData);
                    }
                    sqlData.setContent(data);
                }
            } catch (JSONException e) {
                Log.e(TAG, e.toString());
                e.printStackTrace();
                return false;
            }
        } catch (JSONException e) {
            Log.e(TAG, e.toString());
            e.printStackTrace();
            return false;
        }
        return true;
    }

    // 获取笔记内容
    public JSONObject getContent() {
        try {
            JSONObject js = new JSONObject();
            if (mlsCreate) {
                Log.e(TAG, "it seems that we haven't created this in database yet");
                return null;
            }
            JSONObject note = new JSONObject();
            if (mType == Notes.TYPE_NOTE) {
                note.put(NoteColumns.ID, mld);
                note.put(NoteColumns.ALERTED_DATE, mAlertDate);
                note.put(NoteColumns.BG_COLOR_ID, mBgColorld);
                note.put(NoteColumns.CREATED_DATE, mCreatedDate);
                note.put(NoteColumns.HAS_ATTACHMENT, mHasAttachment);
                note.put(NoteColumns.MODIFIED_DATE, mModifiedDate);
                note.put(NoteColumns.PARENT_ID, mParentld);
                note.put(NoteColumns.SNIPPET, mSnippet);
                note.put(NoteColumns.TYPE, mType);
                note.put(NoteColumns.WIDGET_ID, mWidgetld);
                note.put(NoteColumns.WIDGET_TYPE, mWidgetType);
                note.put(NoteColumns.ORIGIN_PARENT_ID, moOriginParent);
                js.put(GTaskStringUtils.META_HEAD_NOTE, note);
                JSONArray dataArray = new JSONArray();
                for (SqlData sqlData : mDataList) {
                    JSONObject data = sqlData.getContent();
                    if (data != null) {
                        dataArray.put(data);
                    }
                }
                js.put(GTaskStringUtils.META_HEAD_DATA, dataArray);
            } else if (mType == Notes.TYPE_FOLDER || mType == Notes.TYPE_SYSTEM) {
                note.put(NoteColumns.ID, mld);
                note.put(NoteColumns.TYPE, mType);
                note.put(NoteColumns.SNIPPET, mSnippet);
                js.put(GTaskStringUtils.META_HEAD_NOTE, note);
            }
            return js;
        } catch (JSONException e) {
            Log.e(TAG, e.toString());
            e.printStackTrace();
            return null;
        }
    }

    // 设置父笔记ID
    public void setParentld(long id) {
        mParentld = id;
        mDiffNoteValues.put(NoteColumns.PARENT_ID, id);
    }

    // 设置Gtask ID
    public void setGtaskld(String gid) {
        mDiffNoteValues.put(NoteColumns.GTASK_ID, gid);
    }

    // 设置同步ID
    public void setSyncld(long syncld) {
        mDiffNoteValues.put(NoteColumns.SYNC_ID, syncld);
    }

    // 重置本地修改标记
    public void resetLocalModified() {
        mDiffNoteValues.put(NoteColumns.LOCAL_MODIFIED, 0);
    }

    // 获取笔记ID
    public long getld() {
        return mld;
    }

    // 获取父笔记ID
    public long getParentld() {
        return mParentld;
    }

    // 获取笔记摘要
    public String getSnippet() {
        return mSnippet;
    }

    // 判断是否为笔记类型
    public boolean isNoteType() {
        return mType == Notes.TYPE_NOTE;
    }

    // 提交笔记到数据库
    public void commit(boolean validateVersion) {
        if (mlsCreate) {
            if (mld == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) {
                mDiffNoteValues.remove(NoteColumns.ID);
            }
            try {
                Uri uri = mContentResolver.insert(Notes.CONTENT_NOTE_URI, mDiffNoteValues);
                try {
                    mld = Long.valueOf(uri.getPathSegments().get(1));
                } catch (NumberFormatException e) {
                    Log.e(TAG, "Get note id error: " + e.toString());
                    throw new ActionFailureException("create note failed ");
                }
            } catch (IllegalStateException e) {
                Log.e(TAG, "Create thread id failed ");
                throw new ActionFailureException("create note failed ");
            }
            if (mld == 0) {
                throw new IllegalStateException("Create thread id failed ");
            }
            if (mType == Notes.TYPE_NOTE) {
                for (SqlData sqlData : mDataList) {
                    sqlData.commit(mld, false, -1);
                }
            }
        } else {
            if (mld <= 0 && mld != Notes.ID_ROOT_FOLDER && mld != 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) {
                mVversion++;
                int result = 0;
                if (validateVersion) {
                    result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "(" + NoteColumns.ID + "=? AND " + NoteColumns.VERSION + "<?)", new String[]{String.valueOf(mld), String.valueOf(mVversion)});
                } else {
                    result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "(" + NoteColumns.ID + "=? AND " + NoteColumns.VERSION + "<?)", new String[]{String.valueOf(mld), String.valueOf(mVversion)});
                }
                if (result == 0) {
                    Log.w(TAG, "there is no update. maybe user updates note when syncing");
                }
            }
            if (mType == Notes.TYPE_NOTE) {
                for (SqlData sqlData : mDataList) {
                    sqlData.commit(mld, validateVersion, mVversion);
                }
            }
            // Refresh local info
            loadFromCursor(mld);
            if (mType == Notes.TYPE_NOTE) {
                loadDataContent();
            }
            mDiffNoteValues.clear();
            mlsCreate = false;
        }
    }
}
（5）	类名：gtask>data>Task
     代码注释：
     package net.micode.notes.gtask.data;

import android.database.Cursor;
import android.text.TextUtils;
import android.util.Log;

import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.DataConstants;
import net.micode.notes.data.Notes.NoteColumns;

import net.micode.notes.gtask.exception.ActionFailureException;
import net.micode.notes.tool.GTaskStringUtils;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

// Task 类继承自 NodeT，表示一个任务节点
public class Task extends NodeT {
    private static final String TAG = Task.class.getSimpleName(); // 类名常量，用于日志输出

    // 成员变量
    private boolean mCompleted; // 任务是否完成
    private String mNotes; // 任务备注
    private JSONObject mMetaInfo; // 任务的元信息
    private Task mpPriorSibling; // 前一个同级任务节点
    private TaskList mParent; // 父任务列表

    // 构造函数
    public Task() {
        super(); // 调用父类构造函数
        mCompleted = false; // 默认未完成
        mNotes = null; // 默认没有备注
        mpPriorSibling = null; // 默认没有前一个同级任务
        mParent = null; // 默认没有父任务列表
        mMetaInfo = null; // 默认没有元信息
    }

    // 获取创建任务的 JSON 对象
    public JSJONObject getCreateAction(int actionld) {
        JSONObject js = new JSONObject(); // 创建 JSON 对象
        try {
            // 设置 action_type
            js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE);
            // 设置 action_id
            js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionld);
            // 设置 index
            js.put(GTaskStringUtils.GTASK_JSON_INDEX, mpParent.getChildTasklndex(this));
            // 设置 entity_delta
            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);
            if (getNotes() != nul) {
                entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes());
            }
            js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
            // 设置 parent_id
            js.put(GTaskStringUtils.GTASK_JSON_PARENT_ID, mParent.getGid());
            // 设置 dest_parent_type
            js.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT_TYPE, GTaskStringUtils.GTASK_JSON_TYPE_GROUP);
            // 设置 list_id
            js.put(GTaskStringUtils.GTASK_JSON_LIST_ID, mParent.getGid());
            // 设置 prior_sibling_id
            if (mPriorSibling != nul) {
                js.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, mpPriorSibling.getGid());
            }
        } catch (JSONException e) {
            Log.e(TAG, e.toString());
            e.printStackTrace();
            throw new ActionFailureException("fail to generate task-create jsonobject ");
        }
        return js;
    }

    // 获取更新任务的 JSON 对象
    public JSJONObject getUpdateAction(int actionld) {
        JSONObject js = new JSONObject(); // 创建 JSON 对象
        try {
            // 设置 action_type
            js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE);
            // 设置 action_id
            js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionld);
            // 设置 id
            js.put(GTaskStringUtils.GTASK_JSON_ID, getGid());
            // 设置 entity_delta
            JSONObject entity = new JSONObject();
            entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
            if (getNotes() := nul) {
                entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes());
            }
            entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted());
            js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
        } catch (JSONException e) {
            Log.e(TAG, e.toString());
            e.printStackTracel);
            throw new ActionFailureException("fail to generate task-update jsonobject ");
        }
        return js;
    }

    // 根据远程 JSON 设置任务内容
    public void setContentByRemoteJSON(JSONObject js) {
        if (js != null) {
            try {
                // 解析 id
                if (js.has(GTaskStringUtils.GTASK_JSON_ID)) {
                    setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID));
                }
                // 解析 last_modified
                if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) {
                    setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED));
                }
                // 解析 name
                if (js.has(GTaskStringuUtils.GTASK_JSON_NAME)) {
                    setNamel(js.getString(GTaskStringuUtils.GTASK_JSON_NAME));
                }
                // 解析 notes
                if (js.has(GTaskStringUtils.GTASK_JSON_NOTES)) {
                    setNotes(js.getString(GTaskStringUtils.GTASK_JSON_NOTES));
                }
                // 解析 deleted
                if (js.has(GTaskStringUtils.GTASK_JSON_DELETED)) {
                    setDeleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_DELETED));
                }
                // 解析 completed
                if (js.has(GTaskStringUtils.GTASK_JSON_COMPLETED)) {
                    setCompleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_COMPLETED));
                }
            } catch (JSONException e) {
                Log.e(TAG, e.toString());
                e.printStackTrace();
                throw new ActionFailureException("fail to get task content from jsonobject ");
            }
        }
    }

    // 根据本地 JSON 设置任务内容
    public void setContentByLocalJSON(JSONObject js) {
        if (js == null || js.has(GTaskStringUtils.META_HEAD_NOTE) || js.has(GTaskStringuUtils.META_HEAD_DATA)) {
            Log.w(TAG, "setContentByLocalJSON: nothing is available ");
        }
        try {
            JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
            JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
            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)) {
                    setName(data.getString(DataColumns.CONTENT));
                    break;
                }
            }
        } catch (JSONException e) {
            Log.e(TAG, e.toString());
            e.printStackTrace();
        }
    }

    // 从内容获取本地 JSON 对象
    public JSJONObject getLocalJSONFromContent() {
        String name = getName();
        try {
            if (mMetalnfo == nulbD {
                // 新任务从网页创建
                if (name == nul) {
                    Log.w(TAG, "the note seems to be an empty one ");
                    return null;
                }
                JSONObject js = new JSONObject();
                JSONObject note = new JSONObject();
                JSONArray dataArray = new JSONArray();
                JSONObject data = new JSONObject();
                data.put(DataColumns.CONTENT, name);
                dataArray.put(data);
                js.put(GTaskStringUtils.META_HEAD_DATA, dataArray);
                note.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
                js.put(GTaskStringUtils.META_HEAD_NOTE, note);
                return js;
            } else {
                // 同步的任务
                JSONObject note = mMetalnfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
                JSONArray dataArray = mMetalnfo.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)) {
                        data.put(DataColumns.CONTENT, getName());
                        break;
                    }
                }
                note.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
                return mMetalnfo;
            }
        } catch (JSONException e) {
            Log.e(TAG, e.toString());
            e.printStackTrace();
            return null;
        }
    }

    // 设置元信息
    public void setMetalnfo(MetaData metaData) {
        if (metaData != null && metaData.getNotes() != nu山) {
            try {
                mMetalnfo = new JSONObject(metaData.getNotes());
            } catch (JSONException ef) {
                Log.w(TAG, e.toString());
                mMetalnfo = null;
            }
        }
    }

    // 获取同步动作
    public int getSyncAction(Cursor cj) {
        try {
            JSONObject notelnfo = null;
            if (mMetalnfo != null && mMetalnfo.has(GTaskStringUtils.META_HEAD_NOTE)) {
                notelnfo = mMetalnfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
            }
            if (notelnfo == nul) {
                Log.w(TAG， "it seems that note meta has been deleted ");
                return SYNC_ACTION_UPDATE_REMOTE;
            }
            if (notelnfo.has(NoteColumns.ID)) {
                Log.w(TAG, "remote note id seems to be deleted");
                return SYNC_ACTION_UPDATE_LOCAL;
            }
            // 验证 note id
            if (c.getLong(SqlNote.ID__COLUMN) != notelnfo.getLong(NoteColumns.ID)) {
                Log.w(TAG, "note id doesn't match ");
                return SYNC_ACTION_UPDATE_LOCAL;
            }
            if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN)
                        if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) {
                // there is no local update
                if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
                    // no update both side
                    return SYNC_ACTION_NONE;
                } else {
                    // apply remote to local
                    return SYNC_ACTION_UPDATE_LOCAL;
                }
            } else {
                // validate gtask id
                if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) {
                    Log.e(TAG, "gtask id doesn't match ");
                    return SYNC_ACTION_ERROR;
                }
                if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
                    // local modification only
                    return SYNC_ACTION_UPDATE_REMOTE;
                } else {
                    return SYNC_ACTION_UPDATE_CONFLICT;
                }
            }
        } catch (Exception e) {
            Log.e(TAG, e.toString());
            e.printStackTrace();
            return SYNC_ACTION_ERROR;
        }
    }

    // 判断任务是否值得保存
    public boolean isWorthSaving() {
        return mMetalnfo != null || (getName() != null && getName().trim().length() > 0)
                || (getNotes() != null && getNotes().trim().length() > 0);
    }

    // 设置任务完成状态
    public void setCompleted(boolean completed) {
        this.mCompleted = completed;
    }

    // 设置任务备注
    public void setNotes(String notes) {
        this.mNotes = notes;
    }

    // 设置前一个同级任务节点
    public void setPriorSibling(Task priorSibling) {
        this.mPriorSibling = priorSibling;
    }

    // 设置父任务列表
    public void setParent(TaskList parent) {
        this.mParent = parent;
    }

    // 获取任务完成状态
    public boolean getCompleted() {
        return this.mCompleted;
    }

    // 获取任务备注
    public String getNotes() {
        return this.mNotes;
    }

    // 获取前一个同级任务节点
    public Task getPriorSibling() {
        return this.mPriorSibling;
    }

    // 获取父任务列表
    public TaskList getParent() {
        return this.mParent;
    }
}
（6）	类名：gtask>data>TaskList
代码注释：package net.micode.notes.gtask.data;

import android.database.Cursor;
import android.util.Log;

import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.gtask.exception.ActionFailureException;

import net.micode.notes.tool.GTaskStringUtils;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;

public class TaskList extends Node {
    private static final String TAG = TaskList.class.getSimpleName();
    private int mIndex;
    private ArrayList<Task> mChildren;

    public TaskList() {
        super();
        mChildren = new ArrayList<Task>();
        mIndex = 1;
    }

    public JSONObject getCreateAction(int actionId) {
        JSONObject js = new JSONObject();
        try {
            js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE);
            js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
            js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex);

            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_GROUP);
            js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
        } catch (JSONException e) {
            Log.e(TAG, e.toString());
            e.printStackTrace();
            throw new ActionFailureException("fail to generate tasklist-create jsonobject");
        }
        return js;
    }

    public JSONObject getUpdateAction(int actionId) {
        JSONObject js = new JSONObject();
        try {
            js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE);
            js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
            js.put(GTaskStringUtils.GTASK_JSON_ID, getGid());

            JSONObject entity = new JSONObject();
            entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
            entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted());
            js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
        } catch (JSONException e) {
            Log.e(TAG, e.toString());
            e.printStackTrace();
            throw new ActionFailureException("fail to generate tasklist-update jsonobject");
        }
        return js;
    }

    public void setContentByRemoteJSON(JSONObject js) {
        if (js != null) {
            try {
                if (js.has(GTaskStringUtils.GTASK_JSON_ID)) {
                    setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID));
                }
                if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) {
                    setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED));
                }
                if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) {
                    setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME));
                }
            } catch (JSONException e) {
                Log.e(TAG, e.toString());
                e.printStackTrace();
                throw new ActionFailureException("fail to get tasklist content from jsonobject");
            }
        }
    }

    public void setContentByLocalJSON(JSONObject js) {
        if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)) {
            Log.w(TAG, "setContentByLocalJSON: nothing is available");
        }
        try {
            JSONObject folder = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
            if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) {
                String name = folder.getString(NoteColumns.SNIPPET);
                setName(GTaskStringUtils.MIUI_FOLDER_PREFIX + name);
            } else if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) {
                if (folder.getLong(NoteColumns.ID) == Notes.ID_ROOT_FOLDER) {
                    setName(GTaskStringUtils.MIUI_FOLDER_PREFIX + GTaskStringUtils.FOLDER_DEFAULT);
                } else if (folder.getLong(NoteColumns.ID) == Notes.ID_CALL_RECORD_FOLDER) {
                    setName(GTaskStringUtils.MIUI_FOLDER_PREFIX + GTaskStringUtils.FOLDER_CALL_NOTE);
                } else {
                    Log.e(TAG, "invalid system folder");
                }
            } else {
                Log.e(TAG, "error type");
            }
        } catch (JSONException e) {
            Log.e(TAG, e.toString());
            e.printStackTrace();
        }
    }

    public JSONObject getLocalJSONFromContent() {
        try {
            JSONObject js = new JSONObject();
            JSONObject folder = new JSONObject();
            String folderName = getName();
            if (getName().startsWith(GTaskStringUtils.MIUI_FOLDER_PREFIX)) {
                folderName = folderName.substring(GTaskStringUtils.MIUI_FOLDER_PREFIX.length(), folderName.length());
            }
            folder.put(NoteColumns.SNIPPET, folderName);
            if (folderName.equals(GTaskStringUtils.FOLDER_DEFAULT) || folderName.equals(GTaskStringUtils.FOLDER_CALL_NOTE)) {
                folder.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
            } else {
                folder.put(NoteColumns.TYPE, Notes.TYPE_FOLDER);
            }
            js.put(GTaskStringUtils.META_HEAD_NOTE, folder);
            return js;
        } catch (JSONException e) {
            Log.e(TAG, e.toString());
            e.printStackTrace();
            return null;
        }
    }

    public int getSyncAction(Cursor c) {
        try {
            if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) {
                // there is no local update
                if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
                    // no update both side
                    return SYNC_ACTION_NONE;
                } else {
                    // apply remote to local
                    return SYNC_ACTION_UPDATE_LOCAL;
                }
            } else {
                // validate gtask id
                if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) {
                    Log.e(TAG, "gtask id doesn't match ");
                    return SYNC_ACTION_ERROR;
                }
                if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
                    // local modification only
                    return SYNC_ACTION_UPDATE_REMOTE;
                } else {
                    return SYNC_ACTION_UPDATE_CONFLICT;
                }
            }
        } catch (Exception e) {
            Log.e(TAG, e.toString());
            e.printStackTrace();
            return SYNC_ACTION_ERROR;
        }
    }

    // 判断任务是否值得保存
    public boolean isWorthSaving() {
        return mMetalnfo != null || (getName() != null && getName().trim().length() > 0)
                || (getNotes() != null && getNotes().trim().length() > 0);
    }

    // 设置任务完成状态
    public void setCompleted(boolean completed) {
        this.mCompleted = completed;
    }

    // 设置任务备注
    public void setNotes(String notes) {
        this.mNotes = notes;
    }

    // 设置前一个同级任务节点
    public void setPriorSibling(Task priorSibling) {
        this.mPriorSibling = priorSibling;
    }

    // 设置父任务列表
    public void setParent(TaskList parent) {
        this.mParent = parent;
    }

    // 获取任务完成状态
    public boolean getCompleted() {
        return this.mCompleted;
    }

    // 获取任务备注
    public String getNotes() {
        return this.mNotes;
    }

    // 获取前一个同级任务节点
    public Task getPriorSibling() {
        return this.mPriorSibling;
    }

    // 获取父任务列表
    public TaskList getParent() {
        return this.mParent;
    }
}

（7）	类名：gtask>exception>ActionFailureException
代码注释：
/*
 * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.micode.notes.gtask.exception; // 定义异常类所在的包

public class ActionFailureException extends RuntimeException { // 定义异常类，继承自RuntimeException
    private static final long serialVersionUID = 4425249765923293627L; // 定义序列化版本ID，用于序列化和反序列化

    public ActionFailureException() { // 无参构造函数
        super(); // 调用父类的无参构造函数
    }

    public ActionFailureException(String paramString) { // 带有一个字符串参数的构造函数
        super(paramString); // 调用父类的构造函数，传入字符串参数作为异常信息
    }

    public ActionFailureException(String paramString, Throwable paramThrowable) { // 带有字符串和Throwable参数的构造函数
        super(paramString, paramThrowable); // 调用父类的构造函数，传入字符串和Throwable参数作为异常信息和异常原因
    }
}
（8）	类名：gtask>exception>NetworkFailureExcepyion
代码注释：
package net.micode.notes.gtask.exception; // 定义异常类所在的包

public class NetworkFailureException extends Exception { // 定义异常类，继承自Exception
    private static final long serialVersionUID = 2107610287180234136L; // 定义序列化版本ID，用于序列化和反序列化

    public NetworkFailureException() { // 无参构造函数
        super(); // 调用父类的无参构造函数
    }

    public NetworkFailureException(String paramString) { // 带有一个字符串参数的构造函数
        super(paramString); // 调用父类的构造函数，传入字符串参数作为异常信息
    }

    public NetworkFailureException(String paramString, Throwable paramThrowable) { // 带有字符串和Throwable参数的构造函数
        super(paramString, paramThrowable); // 调用父类的构造函数，传入字符串和Throwable参数作为异常信息和异常原因
    }
}

（9）	类名：weight>NoteWidgetProvider
代码注释：
package net.micode.notes.widget;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.util.Log;
import android.widget.RemoteViews;

import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.tool.ResourceParser;
import net.micode.notes.ui.NoteEditActivity;
import net.micode.notes.ui.NotesListActivity;

// 定义一个名为 NoteWidgetProvider 的抽象类，继承自 AppWidgetProvider
public abstract class NoteWidgetProvider extends AppWidgetProvider {
    // 定义查询列数组，包括笔记ID、背景颜色ID和笔记片段
    public static final String[] PROJECTION = new String[] {
        NoteColumns.ID,
        NoteColumns.BG_COLOR_ID,
        NoteColumns.SNIPPET
    };

    // 定义列索引常量
    public static final int COLUMN_ID = 0;
    public static final int COLUMN_BG_COLOR_ID = 1;
    public static final int COLUMN_SNIPPET = 2;

    // 定义日志标签
    private static final String TAG = "NoteWidgetProvider";

    // 当小部件被删除时调用
    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
        ContentValues values = new ContentValues();
        values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
        for (int i = 0; i < appWidgetIds.length; i++) {
            context.getContentResolver().update(Notes.CONTENT_NOTE_URI, values,
                    NoteColumns.WIDGET_ID + "=?", new String[] { String.valueOf(appWidgetIds[i]) });
        }
    }

    // 获取小部件笔记信息
    private Cursor getNoteWidgetInfo(Context context, int widgetId) {
        return context.getContentResolver().query(Notes.CONTENT_NOTE_URI,
                PROJECTION, NoteColumns.WIDGET_ID + "=? AND " + NoteColumns.PARENT_ID + "=?",
                new String[] { String.valueOf(widgetId), String.valueOf(Notes.ID_TRASH_FOLDER) }, null);
    }

    // 更新小部件
    protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        update(context, appWidgetManager, appWidgetIds, false);
    }

    // 更新小部件，可以设置隐私模式
    private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds, boolean privacyMode) {
        for (int i = 0; i < appWidgetIds.length; i++) {
            if (appWidgetIds[i] != AppWidgetManager.INVALID_APPWIDGET_ID) {
                int bgId = ResourceParser.getDefaultBgId(context);
                String snippet = "";
                Intent intent = new Intent(context, NoteEditActivity.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
                intent.putExtra(Notes.INTENT_EXTRA_WIDGET_ID, appWidgetIds[i]);
                intent.putExtra(Notes.INTENT_EXTRA_WIDGET_TYPE, getWidgetType());

                Cursor c = getNoteWidgetInfo(context, appWidgetIds[i]);
                if (c != null && c.moveToFirst()) {
                    if (c.getCount() > 1) {
                        Log.e(TAG, "Multiple messages with same widget id: " + appWidgetIds[i]);
                        c.close();
                        return;
                    }
                    snippet = c.getString(COLUMN_SNIPPET);
                    bgId = c.getInt(COLUMN_BG_COLOR_ID);
                    intent.putExtra(Intent.EXTRA_UID, c.getLong(COLUMN_ID));
                    intent.setAction(Intent.ACTION_VIEW);
                } else {
                    snippet = context.getResources().getString(R.string.widget_have_no_content);
                    intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
                }
                if (c != null) {
                    c.close();
                }

                RemoteViews rv = new RemoteViews(context.getPackageName(), getLayoutId());
                rv.setImageViewResource(R.id.widget_bg_image, getBgResourceId(bgId));
                intent.putExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, bgId);

                PendingIntent pendingIntent = null;
                if (privacyMode) {
                    rv.setTextViewText(R.id.widget_text, context.getString(R.string.widget_under_visit_mode));
                    pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], new Intent(context, NotesListActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
                } else {
                    rv.setTextViewText(R.id.widget_text, snippet);
                    pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], intent, PendingIntent.FLAG_UPDATE_CURRENT);
                }

                rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent);
                appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
            }
        }
    }

    // 抽象方法：获取背景资源ID
    protected abstract int getBgResourceId(int bgId);
    // 抽象方法：获取布局ID
    protected abstract int getLayoutId();
    // 抽象方法：获取小部件类型
    protected abstract int getWidgetType();
}
（10）	类名：weight>NoteWidgetProvider
代码注释：
public class NoteWidgetProvider_2x extends NoteWidgetProvider { // 定义一个名为 NoteWidgetProvider_2x 的类，继承自 NoteWidgetProvider
    @Override // 重写父类的 onUpdate 方法
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        super.update(context, appWidgetManager, appWidgetIds); // 调用父类的 update 方法
    }

    @Override // 重写父类的 getLayoutId 方法
    protected int getLayoutId() {
        return R.layout.widget_2x; // 返回 2x 小部件的布局资源ID
    }

    @Override // 重写父类的 getBgResourceId 方法
    protected int getBgResourceId(int bgId) {
        return ResourceParser.WidgetBgResources.getWidget2xBgResource(bgId); // 返回 2x 小部件的背景资源ID
    }

    @Override // 重写父类的 getWidgetType 方法
    protected int getWidgetType() {
        return Notes.TYPE_WIDGET_2X; // 返回 2x 小部件的类型
    }
}
（11）	类名：weight>NoteWidgetProvider
代码注释：
public class NoteWidgetProvider_4x extends NoteWidgetProvider { // 定义一个名为 NoteWidgetProvider_4x 的类，继承自 NoteWidgetProvider
    @Override // 重写父类的 onUpdate 方法
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        super.update(context, appWidgetManager, appWidgetIds); // 调用父类的 update 方法
    }

    protected int getLayoutId() { // 重写父类的 getLayoutId 方法
        return R.layout.widget_4x; // 返回 4x 小部件的布局资源ID
    }

    @Override // 重写父类的 getBgResourceId 方法
    protected int getBgResourceId(int bgId) {
        return ResourceParser.WidgetBgResources.getWidget4xBgResource(bgId); // 返回 4x 小部件的背景资源ID
    }

    @Override // 重写父类的 getWidgetType 方法
    protected int getWidgetType() {
        return Notes.TYPE_WIDGET_4X; // 返回 4x 小部件的类型
    }
}
（12）	类名：weight>MainActivity
代码注释：public class MainActivity extends AppCompatActivity { // 定义一个名为 MainActivity 的类，继承自 AppCompatActivity
    @Override // 重写父类的 onCreate 方法
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState); // 调用父类的 onCreate 方法
        EdgeToEdge.enable(this); // 启用边缘到边缘的功能
        setContentView(R.layout.activity_main); // 设置活动内容视图为 activity_main 布局

        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { // 设置视图的 OnApplyWindowInsetsListener
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); // 获取系统栏的边距
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); // 设置视图的边距
            return insets; // 返回边距对象
        });
    }
}
