/* * 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;//包名为“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;//导入“Notes”类; import net.micode.notes.data.Notes.DataColumns;//导入“Notes”类的“DataColumns”内部类; import net.micode.notes.data.Notes.NoteColumns;//导入“Notes”类的“NoteColumns”内部类; import net.micode.notes.gtask.exception.ActionFailureException;//导入“gtask 操作失败异常”; import net.micode.notes.tool.GTaskStringUtils;//导入“Notes 工具类的字符串操作工具”; import net.micode.notes.tool.ResourceParser;//导入资源解析器; import org.json.JSONArray;//导入 JSON 数组; import org.json.JSONException;//导入 JSON 异常; import org.json.JSONObject;//导入 JSON 对象; import java.util.ArrayList;//导入数组列表。 public class SqlNote {//:定义一个名为“SqlNote”的公共类; private static final String TAG = SqlNote.class.getSimpleName();//定义一个静态字符串变量“tag”,其值为当前类的简单名称; private static final int INVALID_ID = -99999;//定义一个静态整型常量“INVALID_ID”,其值为-99999; public static final String[] PROJECTION_NOTE = new String[] {//定义一个公共静态字符串数组“PROJECTION_NOTE”,其中包含了一些列名; NoteColumns.ID, NoteColumns.ALERTED_DATE, NoteColumns.BG_COLOR_ID,//“PROJECTION_NOTE”数组中的元素,包括“NoteColumns.ID”、“NoteColumns.ALERTED_DATE”和“NoteColumns.BG_COLOR_ID”; NoteColumns.CREATED_DATE, NoteColumns.HAS_ATTACHMENT, NoteColumns.MODIFIED_DATE,//定义“PROJECTION_NOTE”数组中的元素,包括“NoteColumns.CREATED_DATE”、“NoteColumns.HAS_ATTACHMENT”和“NoteColumns.MODIFIED_DATE”; NoteColumns.NOTES_COUNT, NoteColumns.PARENT_ID, NoteColumns.SNIPPET, NoteColumns.TYPE,//定义“PROJECTION_NOTE”数组中的元素,包括“NoteColumns.NOTES_COUNT”、“NoteColumns.PARENT_ID”、“NoteColumns.SNIPPET”和“NoteColumns.TYPE”; NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE, NoteColumns.SYNC_ID,//定义“PROJECTION_NOTE”数组中的元素,包括“NoteColumns.WIDGET_ID”、“NoteColumns.WIDGET_TYPE”和“NoteColumns.SYNC_ID”; NoteColumns.LOCAL_MODIFIED, NoteColumns.ORIGIN_PARENT_ID, NoteColumns.GTASK_ID,//定义“PROJECTION_NOTE”数组中的元素,包括“NoteColumns.LOCAL_MODIFIED”、“NoteColumns.ORIGIN_PARENT_ID”和“NoteColumns.GTASK_ID”; NoteColumns.VERSION//定义“PROJECTION_NOTE”数组中的元素,包括“NoteColumns.VERSION”; }; public static final int ID_COLUMN = 0;//定义一个公共静态整型常量“ID_COLUMN”,其值为 0; public static final int ALERTED_DATE_COLUMN = 1;//定义一个公共静态整型常量“ALERTED_DATE_COLUMN”,其值为 1; public static final int BG_COLOR_ID_COLUMN = 2;//定义一个公共静态整型常量“BG_COLOR_ID_COLUMN”,其值为 2; public static final int CREATED_DATE_COLUMN = 3;//定义一个公共静态整型常量“CREATED_DATE_COLUMN”,其值为 3; public static final int HAS_ATTACHMENT_COLUMN = 4;//定义一个公共静态整型常量“HAS_ATTACHMENT_COLUMN”,其值为 4; public static final int MODIFIED_DATE_COLUMN = 5;//定义一个公共静态整型常量“MODIFIED_DATE_COLUMN”,其值为 5; public static final int NOTES_COUNT_COLUMN = 6;//定义一个公共静态整型常量“NOTES_COUNT_COLUMN”,其值为 6; public static final int PARENT_ID_COLUMN = 7;//定义一个公共静态整型常量“PARENT_ID_COLUMN”,其值为 7; public static final int SNIPPET_COLUMN = 8;//定义一个公共静态整型常量“SNIPPET_COLUMN”,其值为 8; public static final int TYPE_COLUMN = 9;//定义一个公共静态整型常量“TYPE_COLUMN”,其值为 9; public static final int WIDGET_ID_COLUMN = 10;//定义一个公共静态整型常量“WIDGET_ID_COLUMN”,其值为 10; public static final int WIDGET_TYPE_COLUMN = 11;//定义一个公共静态整型常量“WIDGET_TYPE_COLUMN”,其值为 11; public static final int SYNC_ID_COLUMN = 12;//定义一个公共静态整型常量“SYNC_ID_COLUMN”,其值为 12; public static final int LOCAL_MODIFIED_COLUMN = 13;//定义一个公共静态整型常量“LOCAL_MODIFIED_COLUMN”,其值为 13; public static final int ORIGIN_PARENT_ID_COLUMN = 14;//定义一个公共静态整型常量“ORIGIN_PARENT_ID_COLUMN”,其值为 14; public static final int GTASK_ID_COLUMN = 15;//定义一个公共静态整型常量“GTASK_ID_COLUMN”,其值为 15; public static final int VERSION_COLUMN = 16;//定义一个公共静态整型常量“VERSION_COLUMN”,其值为 16; private Context mContext;//定义一个私有成员变量“mContext”,其类型为“Context”; private ContentResolver mContentResolver;//定义一个私有成员变量“mContentResolver”,其类型为“ContentResolver”; private boolean mIsCreate;//定义一个私有成员变量“mIsCreate”,其类型为“boolean”; private long mId;//定义一个私有成员变量“mId”,其类型为“long”; private long mAlertDate;//定义一个私有成员变量“mAlertDate”,其类型为“long”; private int mBgColorId;//定义一个私有成员变量“mBgColorId”,其类型为“int”; private long mCreatedDate;//定义一个私有成员变量“mCreatedDate”,其类型为“long”; private int mHasAttachment;//定义一个私有成员变量“mHasAttachment”,其类型为“int”; private long mModifiedDate;//定义一个私有成员变量“mModifiedDate”,其类型为“long”; private long mParentId;//定义一个私有成员变量“mParentId”,其类型为“long”; private String mSnippet;//定义一个私有成员变量“mSnippet”,其类型为“String”; private int mType;//定义一个私有成员变量“mType”,其类型为“int”; private int mWidgetId;//定义一个私有成员变量“mWidgetId”,其类型为“int”; private int mWidgetType;//定义一个私有成员变量“mWidgetType”,其类型为“int”; private long mOriginParent;//定义一个私有成员变量“mOriginParent”,其类型为“long”; private long mVersion;//定义一个私有成员变量“mVersion”,其类型为“long”; private ContentValues mDiffNoteValues;//定义一个私有成员变量“mDiffNoteValues”,其类型为“ContentValues”; private ArrayList mDataList;//定义一个私有成员变量“mDataList”,其类型为“ArrayList”; public SqlNote(Context context) {//定义类的构造函数,接收一个“Context”类型的参数; mContext = context;//在构造函数中,将传入的“context”赋值给成员变量“mContext”; mContentResolver = context.getContentResolver();//获取“context”的内容解析器,并赋值给成员变量“mContentResolver”; mIsCreate = true;//将成员变量“mIsCreate”设置为“true”,表示当前是创建新的笔记; mId = INVALID_ID;//将成员变量“mId”设置为“INVALID_ID”,表示笔记的 ID 无效; mAlertDate = 0;//将成员变量“mAlertDate”设置为 0,表示笔记的提醒日期为 0; mBgColorId = ResourceParser.getDefaultBgId(context);//获取默认的背景颜色 ID,并赋值给成员变量“mBgColorId”; mCreatedDate = System.currentTimeMillis();//获取当前系统时间,并赋值给成员变量“mCreatedDate”,表示笔记的创建日期; mHasAttachment = 0;//将成员变量“mHasAttachment”设置为 0,表示笔记没有附件; mModifiedDate = System.currentTimeMillis();//获取当前系统时间,并赋值给成员变量“mModifiedDate”,表示笔记的修改日期; mParentId = 0;//“mParentId”设置为 0,表示笔记的父 ID 为 0; mSnippet = "";//将成员变量“mSnippet”设置为空字符串,表示笔记的片段为空; mType = Notes.TYPE_NOTE;//Notes.TYPE_NOTE”,表示笔记的类型为普通笔记; mWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;//将成员变量“mWidgetId”设置为“AppWidgetManager.INVALID_APPWIDGET_ID”,表示笔记的小部件 ID 无效; mWidgetType = Notes.TYPE_WIDGET_INVALIDE;//将成员变量“mWidgetType”设置为“Notes.TYPE_WIDGET_INVALIDE”,表示笔记的小部件类型无效; mOriginParent = 0;//将成员变量“mOriginParent”设置为 0,表示笔记的原始父 ID 为 0; mVersion = 0;//将成员变量“mVersion”设置为 0,表示笔记的版本号为 0; mDiffNoteValues = new ContentValues();//创建一个新的“ContentValues”对象,并赋值给成员变量“mDiffNoteValues”; mDataList = new ArrayList();//创建一个新的“ArrayList”对象,并赋值给成员变量“mDataList”; } public SqlNote(Context context, Cursor c) {//定义类的另一个构造函数,接收一个“Context”类型的参数和一个“Cursor”类型的参数; mContext = context;//在构造函数中,将传入的“context”赋值给成员变量“mContext”; mContentResolver = context.getContentResolver();//获取“context”的内容解析器,并赋值给成员变量“mContentResolver”; mIsCreate = false;//将成员变量“mIsCreate”设置为“false”,表示当前不是创建新的笔记; loadFromCursor(c);//调用“loadFromCursor”方法,从“Cursor”中加载笔记的数据; mDataList = new ArrayList();//创建一个新的“ArrayList”对象,并赋值给成员变量“mDataList”; if (mType == Notes.TYPE_NOTE)//如果笔记的类型为普通笔记,则调用“loadDataContent”方法加载笔记的数据内容; loadDataContent(); mDiffNoteValues = new ContentValues();//创建一个新的“ContentValues”对象,并赋值给成员变量“mDiffNoteValues” } public SqlNote(Context context, long id) {//定义类的另一个构造函数,接收一个“Context”类型的参数和一个“long”类型的参数; mContext = context;//在构造函数中,将传入的“context”赋值给成员变量“mContext”; mContentResolver = context.getContentResolver();//获取“context”的内容解析器,并赋值给成员变量“mContentResolver”; mIsCreate = false;//:将成员变量“mIsCreate”设置为“false”,表示当前不是创建新的笔记; loadFromCursor(id);//调用“loadFromCursor”方法,根据“id”从数据库中加载笔记的数据; mDataList = new ArrayList();//创建一个新的“ArrayList”对象,并赋值给成员变量“mDataList”; if (mType == Notes.TYPE_NOTE)//如果笔记的类型为普通笔记,则调用“loadDataContent”方法加载笔记的数据内容; loadDataContent(); mDiffNoteValues = new ContentValues();//创建一个新的“ContentValues”对象,并赋值给成员变量“mDiffNoteValues” } private void loadFromCursor(long id) {//定义一个私有方法“loadFromCursor”,接收一个“long”类型的参数; Cursor c = null;//声明一个“Cursor”类型的变量“c”,并初始化为“null”; try { c = mContentResolver.query(Notes.CONTENT_NOTE_URI, PROJECTION_NOTE, "(_id=?)",//使用“mContentResolver”查询“Notes.CONTENT_NOTE_URI”表,获取指定“id”的笔记数据,并将结果存储在“c”中; new String[] {//设置查询条件的参数值; String.valueOf(id)//将“id”转换为字符串,并作为查询条件的参数值; }, null);//设置查询的排序方式为“null”; if (c != null) {//如果“c”不为“null”,则执行以下操作; c.moveToNext();//将游标移动到下一条记录; loadFromCursor(c);//调用“loadFromCursor”方法,从游标中加载笔记的数据; } else {//如果“c”为“null”,则执行以下操作; Log.w(TAG, "loadFromCursor: cursor = null");//输出日志信息,提示游标为空; } } finally {//V在“finally”代码块中,执行以下操作; if (c != null)//如果“c”不为“null”,则执行以下操作; c.close();//关闭游标; } } private void loadFromCursor(Cursor c) {//定义一个私有方法“loadFromCursor”,接收一个“Cursor”类型的参数; mId = c.getLong(ID_COLUMN);//从游标中获取“ID_COLUMN”列的值,并赋值给成员变量“mId”; mAlertDate = c.getLong(ALERTED_DATE_COLUMN);//从游标中获取“ALERTED_DATE_COLUMN”列的值,并赋值给成员变量“mAlertDate”; mBgColorId = c.getInt(BG_COLOR_ID_COLUMN);//从游标中获取“BG_COLOR_ID_COLUMN”列的值,并赋值给成员变量“mBgColorId”; mCreatedDate = c.getLong(CREATED_DATE_COLUMN);//从游标中获取“CREATED_DATE_COLUMN”列的值,并赋值给成员变量“mCreatedDate”; mHasAttachment = c.getInt(HAS_ATTACHMENT_COLUMN);//从游标中获取“HAS_ATTACHMENT_COLUMN”列的值,并赋值给成员变量“mHasAttachment”; mModifiedDate = c.getLong(MODIFIED_DATE_COLUMN);//从游标中获取“MODIFIED_DATE_COLUMN”列的值,并赋值给成员变量“mModifiedDate”; mParentId = c.getLong(PARENT_ID_COLUMN);//从游标中获取“PARENT_ID_COLUMN”列的值,并赋值给成员变量“mParentId”; mSnippet = c.getString(SNIPPET_COLUMN);//从游标中获取“SNIPPET_COLUMN”列的值,并赋值给成员变量“mSnippet”; mType = c.getInt(TYPE_COLUMN);//:从游标中获取“TYPE_COLUMN”列的值,并赋值给成员变量“mType”; mWidgetId = c.getInt(WIDGET_ID_COLUMN);//从游标中获取“WIDGET_ID_COLUMN”列的值,并赋值给成员变量“mWidgetId”; mWidgetType = c.getInt(WIDGET_TYPE_COLUMN);//从游标中获取“WIDGET_TYPE_COLUMN”列的值,并赋值给成员变量“mWidgetType” mVersion = c.getLong(VERSION_COLUMN);//从游标中获取“VERSION_COLUMN”列的值,并赋值给成员变量“mVersion”; } private void loadDataContent() {//定义一个私有方法“loadDataContent”; Cursor c = null;//明一个“Cursor”类型的变量“c”,并初始化为“null”; mDataList.clear();//清空“mDataList”列表; try {在“try”代码块中,执行以下操作; c = mContentResolver.query(Notes.CONTENT_DATA_URI, SqlData.PROJECTION_DATA,//使用“mContentResolver”查询“Notes.CONTENT_DATA_URI”表,获取指定笔记的“SqlData”数据,并将结果存储在“c”中; "(note_id=?)", new String[] { String.valueOf(mId)// //是一个字符串数组,用于在数据库查询中指定条件。其中, note_id=?  是查询条件,表示要查找的笔记的 ID 为指定的值; new String[] { String.valueOf(mId) }  是条件的值,将当前笔记的 ID 转换为字符串并作为查询条件的值; null  表示不指定排序方式。 }, null); if (c != null) {//如果游标不为空,则执行以下操作。 if (c.getCount() == 0) {//如果游标中的行数为 0,则表示该笔记似乎没有数据。 Log.w(TAG, "it seems that the note has not data");//:输出一条警告日志,提示该笔记似乎没有数据。 return; } while (c.moveToNext()) {//当游标可以向下移动时,执行以下循环。 SqlData data = new SqlData(mContext, c);//创建一个新的  SqlData  对象,用于表示当前游标指向的数据。 mDataList.add(data);//将新创建的  SqlData  对象添加到  mDataList  列表中。 } } else {//如果游标为空,则执行以下操作。 Log.w(TAG, "loadDataContent: cursor = null");//输出一条警告日志,提示游标为空。 } } finally {//无论游标是否为空,都执行以下操作。 if (c != null) c.close();//如果游标不为空,则关闭游标。 } } public boolean setContent(JSONObject js) { try { JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);//从传入的  JSONObject  中获取名为  GTaskStringUtils.META_HEAD_NOTE  的子对象,并将其赋值给  note  变量。 if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) {//如果  note  对象的  type  字段的值为  Notes.TYPE_SYSTEM ,则表示这是一个系统文件夹,不能进行设置操作。 Log.w(TAG, "cannot set system folder");//输出一条警告日志,提示不能设置系统文件夹。 } else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) {//如果  note  对象的  type  字段的值为  Notes.TYPE_FOLDER ,则表示这是一个文件夹,可以进行设置操作,但只能更新  snippet  和  type  字段。 // for folder we can only update the snnipet and type String snippet = note.has(NoteColumns.SNIPPET) ? note .getString(NoteColumns.SNIPPET) : "";//获取  note  对象的  snippet  字段的值,如果该字段不存在,则使用空字符串作为默认值。 if (mIsCreate || !mSnippet.equals(snippet)) {//如果当前是创建新笔记,或者当前的  snippet  值与从  note  对象中获取的  snippet  值不相等,则执行以下操作。 mDiffNoteValues.put(NoteColumns.SNIPPET, snippet);//将  snippet  值添加到  mDiffNoteValues  对象中,以便在提交笔记时进行更新。 } mSnippet = snippet;//将从  note  对象中获取的  snippet  值赋值给当前笔记的  snippet  字段。 int type = note.has(NoteColumns.TYPE) ? note.getInt(NoteColumns.TYPE) : Notes.TYPE_NOTE;//Notes.TYPE_NOTE; :获取  note  对象的  type  字段的值,如果该字段不存在,则使用  Notes.TYPE_NOTE  作为默认值。 if (mIsCreate || mType != type) {//如果当前是创建新笔记,或者当前的  type  值与从  note  对象中获取的  type  值不相等,则执行以下操作。 mDiffNoteValues.put(NoteColumns.TYPE, type);//将  type  值添加到  mDiffNoteValues  对象中,以便在提交笔记时进行更新。 } mType = type;//将从  note  对象中获取的  type  值赋值给当前笔记的  type  字段。 } else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_NOTE) {//如果  note  对象的  type  字段的值为  Notes.TYPE_NOTE ,则表示这是一个普通笔记,可以进行设置操作。 JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);//从传入的  JSONObject  中获取名为  GTaskStringUtils.META_HEAD_DATA  的子对象,并将其转换为  JSONArray  类型。 long id = note.has(NoteColumns.ID) ? note.getLong(NoteColumns.ID) : INVALID_ID;//获取  note  对象的  id  字段的值,如果该字段不存在,则使用  INVALID_ID  作为默认值。 if (mIsCreate || mId != id) {//如果当前是创建新笔记,或者当前的  id  值与从  note  对象中获取的  id  值不相等,则执行以下操作。 mDiffNoteValues.put(NoteColumns.ID, id);//将  id  值添加到  mDiffNoteValues  对象中,以便在提交笔记时进行更新。 } mId = id;//将从  note  对象中获取的  id  值赋值给当前笔记的  id  字段。 long alertDate = note.has(NoteColumns.ALERTED_DATE) ? note .getLong(NoteColumns.ALERTED_DATE) : 0;//获取  note  对象的  alertDate  字段的值,如果该字段不存在,则使用 0 作为默认值。 if (mIsCreate || mAlertDate != alertDate) {//如果当前是创建新笔记,或者当前的  alertDate  值与从  note  对象中获取的  alertDate  值不相等,则执行以下操作。 mDiffNoteValues.put(NoteColumns.ALERTED_DATE, alertDate);//将  alertDate  值添加到  mDiffNoteValues  对象中,以便在提交笔记时进行更新。 3 } mAlertDate = alertDate;//将从  note  对象中获取的  alertDate  值赋值给当前笔记的  alertDate  字段。 int bgColorId = note.has(NoteColumns.BG_COLOR_ID) ? note .getInt(NoteColumns.BG_COLOR_ID) : ResourceParser.getDefaultBgId(mContext);//获取  note  对象的  bgColorId  字段的值,如果该字段不存在,则使用默认的背景颜色 ID。 if (mIsCreate || mBgColorId != bgColorId) {//如果当前是创建新笔记,或者当前的  bgColorId  值与从  note  对象中获取的  bgColorId  值不相等,则执行以下操作。 mDiffNoteValues.put(NoteColumns.BG_COLOR_ID, bgColorId);//将  bgColorId  值添加到  mDiffNoteValues  对象中,以便在提交笔记时进行更新。 。 } mBgColorId = bgColorId;//将从  note  对象中获取的  bgColorId  值赋值给当前笔记的  bgColorId  字段。 long createDate = note.has(NoteColumns.CREATED_DATE) ? note .getLong(NoteColumns.CREATED_DATE) : System.currentTimeMillis();//获取  note  对象的  createDate  字段的值,如果该字段不存在,则使用当前时间作为默认值。 if (mIsCreate || mCreatedDate != createDate) {//如果当前是创建新笔记,或者当前的  createdDate  值与从  note  对象中获取的  createdDate  值不相等,则执行以下操作。 mDiffNoteValues.put(NoteColumns.CREATED_DATE, createDate);//将  createdDate  值添加到  mDiffNoteValues  对象中,以便在提交笔记时进行更新。 } mCreatedDate = createDate;//将从  note  对象中获取的  createdDate  值赋值给当前笔记的  createdDate  字段。 int hasAttachment = note.has(NoteColumns.HAS_ATTACHMENT) ? note .getInt(NoteColumns.HAS_ATTACHMENT) : 0;//获取  note  对象的  hasAttachment  字段的值,如果该字段不存在,则使用 0 作为默认值。 if (mIsCreate || mHasAttachment != hasAttachment) {//如果当前是创建新笔记,或者当前的  hasAttachment  值与从  note  对象中获取的  hasAttachment  值不相等,则执行以下操作。 mDiffNoteValues.put(NoteColumns.HAS_ATTACHMENT, hasAttachment);//将  hasAttachment  值添加到  mDiffNoteValues  对象中,以便在提交笔记时进行更新。 } mHasAttachment = hasAttachment;//将从  note  对象中获取的  hasAttachment  值赋值给当前笔记的  hasAttachment  字段。 long modifiedDate = note.has(NoteColumns.MODIFIED_DATE) ? note .getLong(NoteColumns.MODIFIED_DATE) : System.currentTimeMillis();//获取  note  对象的  modifiedDate  字段的值,如果该字段不存在,则使用当前时间作为默认值。 if (mIsCreate || mModifiedDate != modifiedDate) {//如果当前是创建新笔记,或者当前的  modifiedDate  值与从  note  对象中获取的  modifiedDate  值不相等,则执行以下操作。 mDiffNoteValues.put(NoteColumns.MODIFIED_DATE, modifiedDate);//将  modifiedDate  值添加到  mDiffNoteValues  对象中,以便在提交笔记时进行更新。 } mModifiedDate = modifiedDate;//将从  note  对象中获取的  modifiedDate  值赋值给当前笔记的  modifiedDate  字段。 long parentId = note.has(NoteColumns.PARENT_ID) ? note .getLong(NoteColumns.PARENT_ID) : 0;//获取  note  对象的  parentId  字段的值,如果该字段不存在,则使用 0 作为默认值。 if (mIsCreate || mParentId != parentId) {//如果当前是创建新笔记,或者当前的  parentId  值与从  note  对象中获取的  parentId  值不相等,则执行以下操作。 mDiffNoteValues.put(NoteColumns.PARENT_ID, parentId);//将  parentId  值添加到  mDiffNoteValues  对象中,以便在提交笔记时进行更新。 } mParentId = parentId;//将从  note  对象中获取的  parentId  值赋值给当前笔记的  parentId  字段。 String snippet = note.has(NoteColumns.SNIPPET) ? note .getString(NoteColumns.SNIPPET) : "";//获取  note  对象的  snippet  字段的值,如果该字段不存在,则使用空字符串作为默认值。 if (mIsCreate || !mSnippet.equals(snippet)) {//如果当前是创建新笔记,或者当前的  snippet  值与从  note  对象中获取的  snippet  值不相等,则执行以下操作。 mDiffNoteValues.put(NoteColumns.SNIPPET, snippet);//将  snippet  值添加到  mDiffNoteValues  对象中,以便在提交笔记时进行更新。 } mSnippet = snippet;//将从  note  对象中获取的  snippet  值赋值给当前笔记的  snippet  字段。 int type = note.has(NoteColumns.TYPE) ? note.getInt(NoteColumns.TYPE) : Notes.TYPE_NOTE;//获取  note  对象的  type  字段的值,如果该字段不存在,则使用  Notes.TYPE_NOTE  作为默认值。 if (mIsCreate || mType != type) {//如果当前是创建新笔记,或者当前的  type  值与从  note  对象中获取的  type  值不相等,则执行以下操作。 mDiffNoteValues.put(NoteColumns.TYPE, type);//将  type  值添加到  mDiffNoteValues  对象中,以便在提交笔记时进行更新。 } mType = type;//从  note  对象中获取的  type  值赋值给当前笔记的  type  字段。 int widgetId = note.has(NoteColumns.WIDGET_ID) ? note.getInt(NoteColumns.WIDGET_ID) : AppWidgetManager.INVALID_APPWIDGET_ID;.//获取  note  对象的  widgetId  字段的值,如果该字段不存在,则使用无效的小部件 ID 作为默认值。 if (mIsCreate || mWidgetId != widgetId) {//如果当前是创建新笔记,或者当前的  widgetId  值与从  note  对象中获取的  widgetId  值不相等,则执行以下操作。 mDiffNoteValues.put(NoteColumns.WIDGET_ID, widgetId);//将  widgetId  值添加到  mDiffNoteValues  对象中,以便在提交笔记时进行更新。 } mWidgetId = widgetId;//将从  note  对象中获取的  widgetId  值赋值给当前笔记的  widgetId  字段。 int widgetType = note.has(NoteColumns.WIDGET_TYPE) ? note .getInt(NoteColumns.WIDGET_TYPE) : Notes.TYPE_WIDGET_INVALIDE;//获取  note  对象的  widgetType  字段的值,如果该字段不存在,则使用无效的小部件类型作为默认值。 if (mIsCreate || mWidgetType != widgetType) {//如果当前是创建新笔记,或者当前的  widgetType  值与从  note  对象中获取的  widgetType  值不相等,则执行以下操作。 mDiffNoteValues.put(NoteColumns.WIDGET_TYPE, widgetType);//将  widgetType  值添加到  mDiffNoteValues  对象中,以便在提交笔记时进行更新。 } mWidgetType = widgetType;//将从  note  对象中获取的  widgetType  值赋值给当前笔记的  widgetType  字段。 long originParent = note.has(NoteColumns.ORIGIN_PARENT_ID) ? note .getLong(NoteColumns.ORIGIN_PARENT_ID) : 0;//获取  note  对象的  originParent  字段的值,如果该字段不存在,则使用 0 作为默认值。 if (mIsCreate || mOriginParent != originParent) {//如果当前是创建新笔记,或者当前的  originParent  值与从  note  对象中获取的  originParent  值不相等,则执行以下操作。 mDiffNoteValues.put(NoteColumns.ORIGIN_PARENT_ID, originParent);//将  originParent  值添加到  mDiffNoteValues  对象中,以便在提交笔记时进行更新。 } mOriginParent = originParent;//将从  note  对象中获取的  originParent  值赋值给当前笔记的  originParent  字段。 for (int i = 0; i < dataArray.length(); i++) {//遍历  dataArray  数组,对每个元素执行以下操作。 JSONObject data = dataArray.getJSONObject(i);//获取当前元素,并将其转换为  JSONObject  类型。 SqlData sqlData = null;.//创建一个  SqlData  对象,并将其初始化为  null 。 if (data.has(DataColumns.ID)) {//如果  data  对象包含名为  DataColumns.ID  的字段,则执行以下操作 long dataId = data.getLong(DataColumns.ID);//获取该字段的值,并将其转换为  long  类型。 for (SqlData temp : mDataList) {//遍历  mDataList  列表,对每个元素执行以下操作。 if (dataId == temp.getId()) {//如果当前元素的  id  值与  dataId  相等,则执行以下操作。 sqlData = temp;//将当前元素赋值给  sqlData  变量。 } } } if (sqlData == null) {//如果  sqlData  变量仍然为  null ,则执行以下操作。 sqlData = new SqlData(mContext);//创建一个新的  SqlData  对象,并将其赋值给  sqlData  变量。 mDataList.add(sqlData);//新创建的  SqlData  对象添加到  mDataList  列表中。 } sqlData.setContent(data);//将 data 的内容设置到 sqlData 中。 } } } catch (JSONException e) {//如果在解析 JSONObject 时发生 JSONException 异常,则执行以下操作。 Log.e(TAG, e.toString());//使用 Log.e 方法输出错误日志,其中包含异常的详细信息。 e.printStackTrace();//打印异常的堆栈跟踪信息。 return false;//返回 false ,表示设置内容失败。 } return true;//返回 true ,表示设置内容成功。 } public JSONObject getContent() {//定义一个公共方法 getContent ,用于获取笔记的内容。 try {//在 try 代码块中执行以下操作。 JSONObject js = new JSONObject();//创建一个新的 JSONObject 对象 js 。 if (mIsCreate) {//如果笔记是新创建的,则执行以下操作。 Log.e(TAG, "it seems that we haven't created this in database yet");//输出一条错误日志,提示笔记似乎还没有在数据库中创建。 return null;//返回 null ,表示获取内容失败。 } JSONObject note = new JSONObject();//创建一个新的 JSONObject 对象 note 。 if (mType == Notes.TYPE_NOTE) {//如果笔记的类型是普通笔记,则执行以下操作。 note.put(NoteColumns.ID, mId);//将笔记的 ID 添加到 note 对象中。 note.put(NoteColumns.ALERTED_DATE, mAlertDate);//将笔记的提醒日期添加到 note 对象中。 note.put(NoteColumns.BG_COLOR_ID, mBgColorId);//将笔记的背景颜色 ID 添加到 note 对象中。 note.put(NoteColumns.CREATED_DATE, mCreatedDate);//将笔记的创建日期添加到 note 对象中。 note.put(NoteColumns.HAS_ATTACHMENT, mHasAttachment);//将笔记是否有附件添加到 note 对象中。 note.put(NoteColumns.MODIFIED_DATE, mModifiedDate);//将笔记的修改日期添加到 note 对象中。 note.put(NoteColumns.PARENT_ID, mParentId);//将笔记的父 ID 添加到 note 对象中。 note.put(NoteColumns.SNIPPET, mSnippet);//将笔记的片段添加到 note 对象中。 note.put(NoteColumns.TYPE, mType);//将笔记的类型添加到 note 对象中。 note.put(NoteColumns.WIDGET_ID, mWidgetId);//将笔记的小部件 ID 添加到 note 对象中。 note.put(NoteColumns.WIDGET_TYPE, mWidgetType);//将笔记的小部件类型添加到 note 对象中。 note.put(NoteColumns.ORIGIN_PARENT_ID, mOriginParent);//将笔记的原始父 ID 添加到 note 对象中。 js.put(GTaskStringUtils.META_HEAD_NOTE, note);//将 note 对象添加到 js 对象中,键为 GTaskStringUtils.META_HEAD_NOTE 。 JSONArray dataArray = new JSONArray();//创建一个新的 JSONArray 对象 dataArray 。 for (SqlData sqlData : mDataList) {//遍历 mDataList 列表中的每个 SqlData 对象。 JSONObject data = sqlData.getContent();//获取当前 SqlData 对象的内容,并将其转换为 JSONObject 对象。 if (data != null) {//如果 data 对象不为 null ,则执行以下操作。 dataArray.put(data);//将 data 对象添加到 dataArray 对象中。 } } js.put(GTaskStringUtils.META_HEAD_DATA, dataArray);//将 dataArray 对象添加到 js 对象中,键为 GTaskStringUtils.META_HEAD_DATA 。 } else if (mType == Notes.TYPE_FOLDER || mType == Notes.TYPE_SYSTEM) {//如果笔记的类型是文件夹或系统文件夹,则执行以下操作。 note.put(NoteColumns.ID, mId);//将笔记的 ID 添加到 note 对象中。 note.put(NoteColumns.TYPE, mType);//将笔记的类型添加到 note 对象中。 note.put(NoteColumns.SNIPPET, mSnippet);//将笔记的片段添加到 note 对象中。 js.put(GTaskStringUtils.META_HEAD_NOTE, note);//:将 note 对象添加到 js 对象中,键为 GTaskStringUtils.META_HEAD_NOTE 。 } return js;//返回 js 对象,其中包含笔记的内容。 } catch (JSONException e) {//如果在创建 JSONObject 或 JSONArray 时发生 JSONException 异常,则执行以下操作。 Log.e(TAG, e.toString());//使用 Log.e 方法输出错误日志,其中包含异常的详细信息。 e.printStackTrace();//打印异常的堆栈跟踪信息。 } return null;//返回 null ,表示获取内容失败。 } public void setParentId(long id) {//定义一个公共方法 setParentId ,用于设置笔记的父 ID 。 mParentId = id;//将 id 赋值给成员变量 mParentId 。 mDiffNoteValues.put(NoteColumns.PARENT_ID, id);//将 id 添加到 mDiffNoteValues 对象中,以便在提交更改时更新数据库中的父 ID  } public void setGtaskId(String gid) {//定义一个公共方法 setGtaskId ,用于设置笔记的 gtask_id 。 mDiffNoteValues.put(NoteColumns.GTASK_ID, gid);//将 gid 添加到 mDiffNoteValues 对象中,以便在提交更改时更新数据库中的 gtask_id 。 } public void setSyncId(long syncId) {//定义一个公共方法 setSyncId ,用于设置笔记的同步 ID 。 mDiffNoteValues.put(NoteColumns.SYNC_ID, syncId);//将 syncId 添加到 mDiffNoteValues 对象中,以便在提交更改时更新数据库中的同步 ID 。 } public void resetLocalModified() {//定义一个公共方法 resetLocalModified ,用于重置笔记的本地修改状态。 mDiffNoteValues.put(NoteColumns.LOCAL_MODIFIED, 0);//将 0 添加到 mDiffNoteValues 对象中,以便在提交更改时将本地修改状态重置为 false 。 } public long getId() {//定义一个公共方法 getId ,用于获取笔记的 ID 。 return mId;//返回成员变量 mId 的值,即笔记的 ID 。 } public long getParentId() {//定义一个公共方法 getParentId ,用于获取笔记的父 ID 。 return mParentId;//返回成员变量 mParentId 的值,即笔记的父 ID 。 } public String getSnippet() {//定义一个公共方法 getSnippet ,用于获取笔记的片段。 return mSnippet;//返回成员变量 mSnippet 的值,即笔记的片段。 } public boolean isNoteType() {//定义一个公共方法 isNoteType ,用于判断笔记是否为普通笔记。 return mType == Notes.TYPE_NOTE;//返回一个布尔值,表示笔记的类型是否为普通笔记。 } public void commit(boolean validateVersion) {//定义一个公共方法 commit ,用于提交笔记的更改。 if (mIsCreate) {//如果笔记是新创建的,则执行以下操作。 if (mId == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) {//如果笔记的 ID 为无效值( INVALID_ID ),并且 mDiffNoteValues 对象中包含 NoteColumns.ID 键,则执行以下操作。 mDiffNoteValues.remove(NoteColumns.ID);//从 mDiffNoteValues 对象中删除 NoteColumns.ID 键及其对应的值。 } Uri uri = mContentResolver.insert(Notes.CONTENT_NOTE_URI, mDiffNoteValues);//使用 mContentResolver 对象的 insert 方法将 mDiffNoteValues 对象中的数据插入到数据库中,并获取插入后生成的 Uri 对象。 try {//在 try 代码块中执行以下操作。 mId = Long.valueOf(uri.getPathSegments().get(1));//从 uri 对象中获取路径段的第二个元素,并将其转换为 long 类型,然后赋值给成员变量 mId 。 } catch (NumberFormatException e) {//如果在将路径段元素转换为 long 类型时发生 NumberFormatException 异常,则执行以下操作 Log.e(TAG, "Get note id error :" + e.toString());//使用 Log.e 方法输出错误日志,其中包含异常的详细信息。 throw new ActionFailureException("create note failed");//抛出一个 ActionFailureException 异常,提示创建笔记失败。 } if (mId == 0) {//如果笔记的 ID 为 0,则执行以下操作。 throw new IllegalStateException("Create thread id failed");//出一个 IllegalStateException 异常,提示创建线程 ID 失败。 } if (mType == Notes.TYPE_NOTE) {//果笔记的类型是普通笔记,则执行以下操作。 for (SqlData sqlData : mDataList) {//遍历 mDataList 列表中的每个 SqlData 对象。 sqlData.commit(mId, false, -1);//调用 sqlData 对象的 commit 方法,将笔记的 ID 、是否验证版本和版本号作为参数传递给该方法。 } } } else {//如果笔记不是新创建的,则执行以下操作。 if (mId <= 0 && mId != Notes.ID_ROOT_FOLDER && mId != Notes.ID_CALL_RECORD_FOLDER) {//如果笔记的 ID 小于等于 0,并且不等于根文件夹 ID 和通话记录文件夹 ID ,则执行以下操作。 Log.e(TAG, "No such note");//使用 Log.e 方法输出错误日志,提示没有找到这样的笔记。 throw new IllegalStateException("Try to update note with invalid id");//抛出一个 IllegalStateException 异常,提示尝试使用无效的 ID 更新笔记。 } if (mDiffNoteValues.size() > 0) {//如果 mDiffNoteValues 对象中包含的键值对数量大于 0,则执行以下操作。 mVersion ++;//将成员变量 mVersion 的值加 1。 int result = 0;//定义一个整型变量 result ,并将其初始化为 0。 if (!validateVersion) {//如果不验证版本,则执行以下操作。 result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "(" + NoteColumns.ID + "=?)", new String[] { String.valueOf(mId) });//使用 mContentResolver 对象的 update 方法更新数据库中的笔记数据,将 mDiffNoteValues 对象中的键值对作为更新的数据, NoteColumns.ID 作为条件, mId 作为条件的值。 } else { result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "(" + NoteColumns.ID + "=?) AND (" + NoteColumns.VERSION + "<=?)", new String[] { String.valueOf(mId), String.valueOf(mVersion) });//使用 mContentResolver 对象的 update 方法更新数据库中的笔记数据,将 mDiffNoteValues 对象中的键值对作为更新的数据, NoteColumns.ID 和 NoteColumns.VERSION 作为条件, mId 和 mVersion 作为条件的值。 } if (result == 0) {//如果更新操作没有成功执行(即更新的行数为 0),则执行以下操作。 Log.w(TAG, "there is no update. maybe user updates note when syncing");//使用 Log.w 方法输出警告日志,提示没有更新笔记,可能是用户在同步时更新了笔记。 } } if (mType == Notes.TYPE_NOTE) {//如果笔记的类型是普通笔记,则执行以下操作。 for (SqlData sqlData : mDataList) {//遍历 mDataList 列表中的每个 SqlData 对象。 sqlData.commit(mId, validateVersion, mVersion);//调用 sqlData 对象的 commit 方法,将笔记的 ID 、是否验证版本和版本号作为参数传递给该方法。 } } } // refresh local info loadFromCursor(mId);//从数据库中加载笔记的最新信息。 if (mType == Notes.TYPE_NOTE)//如果笔记的类型是普通笔记,则执行以下操作。 loadDataContent();//加载笔记的数据内容。 mDiffNoteValues.clear();//清空 mDiffNoteValues 对象中的键值对。 mIsCreate = false;//将成员变量 mIsCreate 的值设置为 false ,表示笔记不再是新创建的。 } }