代码合并 #1

Merged
pc9tmerpu merged 13 commits from 罗文浩 into main 1 year ago

@ -1,39 +0,0 @@
/*
* 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;
//这行代码声明了这个类所在的包名是net.micode.notes.gtask.exception表明这个类是用于处理特定软件模块中与任务相关的
//异常情况。
public class ActionFailureException extends RuntimeException {
//这行代码定义了一个名为ActionFailureException的公共类它继承自RuntimeException意味着它是一种运行时异常可以
//在程序运行过程中被抛出而不需要在方法签名中进行声明。
private static final long serialVersionUID = 4425249765923293627L;
//这是一个用于序列化和反序列化的版本号标识,确保在类的结构发生变化时,序列化和反序列化的兼容性。
public ActionFailureException() {
super();
}
//这是一个无参构造方法它调用了父类RuntimeException的无参构造方法创建一个没有特定错误消息的异常对象。
public ActionFailureException(String paramString) {
super(paramString);
}
//这是一个带一个字符串参数的构造方法它接受一个错误消息并将其传递给父类RuntimeException的构造方法创建一个带
//有特定错误消息的异常对象。
public ActionFailureException(String paramString, Throwable paramThrowable) {
super(paramString, paramThrowable);
}
}
//这是一个带两个参数的构造方法第一个参数是错误消息第二个参数是一个Throwable类型的对象代表导致这个异常的原
//因。它将这两个参数传递给父类RuntimeException的构造方法创建一个带有特定错误消息和原因的异常对象。

@ -0,0 +1,98 @@
/*
* 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.
*/
// 这是一个多行注释,用来说明这个文件的版权信息和许可协议。它指出这个文件是由 MiCode 开源社区版权所有,并在 Apache License 2.0 下授权。它还提供了获取许可证的链接,并说明了许可证的条款和条件。
package net.micode.notes.data;
// 声明这个类属于哪个包。在这个例子中,它属于`net.micode.notes.data`包。
import android.content.Context;
// 导入 Android 的 Context 类,用于获取应用上下文。
import android.database.Cursor;
// 导入 Cursor 类,用于在数据库查询结果中进行遍历。
import android.provider.ContactsContract.CommonDataKinds.Phone;
// 导入 Android Contacts Provider 中与电话号码相关的常量类。
import android.provider.ContactsContract.Data;
// 导入 Android Contacts Provider 的数据访问类。
import android.telephony.PhoneNumberUtils;
// 导入用于处理电话号码的工具类。
import android.util.Log;
// 导入 Android 的日志工具类。
import java.util.HashMap;
// 导入 Java 的 HashMap 类,用于存储电话号码和联系人名称的映射关系。
public class Contact {
// 定义一个静态的 HashMap用来缓存电话号码和对应的联系人名称。
private static HashMap<String, String> sContactCache;
// 定义一个静态常量 TAG用于日志输出时标记来源。
private static final String TAG = "Contact";
// 定义一个 SQL 查询语句模板,用于查询电话号码。
// 这个查询语句使用了 Android Contacts Provider 的内容 URI 和一些过滤条件。
private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL(" + Phone.NUMBER
+ ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'"
+ " AND " + Data.RAW_CONTACT_ID + " IN "
+ "(SELECT raw_contact_id "
+ " FROM phone_lookup"
+ " WHERE min_match = '+')";
// 定义一个静态方法 getContact它接受一个 Context 对象和一个电话号码作为参数。
// 这个方法主要用于根据电话号码查询对应的联系人名称。
public static String getContact(Context context, String phoneNumber) {
// 如果缓存不存在,则初始化一个空的 HashMap 作为缓存。
if(sContactCache == null) {
sContactCache = new HashMap<String, String>();
}
// 如果电话号码已经在缓存中,则直接返回缓存中的联系人名称,避免重复查询。
if(sContactCache.containsKey(phoneNumber)) {
return sContactCache.get(phoneNumber);
}
// 将查询语句中的"+"替换为电话号码的最小匹配模式。
String selection = CALLER_ID_SELECTION.replace("+",
PhoneNumberUtils.toCallerIDMinMatch(phoneNumber));
// 使用设备的 ContentResolver 执行查询,查询目标是获取联系人的显示名称。
Cursor cursor = context.getContentResolver().query(
Data.CONTENT_URI,
new String [] { Phone.DISPLAY_NAME },
selection,
new String[] { phoneNumber },
null);
// 如果查询结果不为空并且可以移动到第一条记录。
if (cursor!= null && cursor.moveToFirst()) {
try {
// 获取查询结果中的联系人名称。
String name = cursor.getString(0);
// 将电话号码和联系人名称存入缓存。
sContactCache.put(phoneNumber, name);
// 返回联系人名称。
return name;
} catch (IndexOutOfBoundsException e) {
// 如果发生索引越界异常,记录错误日志并返回 null。
Log.e(TAG, " Cursor get string error " + e.toString());
return null;
} finally {
// 无论是否发生异常,都关闭游标。
cursor.close();
}
} else {
// 如果查询结果为空,记录日志并返回 null。
Log.d(TAG, "No contact matched with number:" + phoneNumber);
return null;
}
}
}

@ -0,0 +1,127 @@
/*
* Copyright (c) 2010 - 2011, The MiCode Open Source Community (www.micode.net)
* c2010 - 2011MiCode www.micode.net
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Apache License 2.0
* 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
* 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;(包名为 net.micode.notes.gtask.data
import android.database.Cursor;
// 导入 android.database.Cursor导入 Android 的数据库游标类;)
import android.util.Log;
// 导入 android.util.Log导入 Android 的日志工具类;)
import net.micode.notes.tool.GTaskStringUtils;
// 导入 net.micode.notes.tool.GTaskStringUtils导入来自 net.micode.notes.tool 的 GTaskStringUtils 类;)
import org.json.JSONException;
// 导入 org.json.JSONException导入 JSON 处理的异常类;)
import org.json.JSONObject;
// 导入 org.json.JSONObject导入 JSON 对象类;)
public class MetaData extends Task {
// 公共类 MetaData 继承自 Task定义一个名为 MetaData 的公共类,它继承自 Task 类;)
private final static String TAG = MetaData.class.getSimpleName();
// 私有最终静态字符串变量 TAG赋值为 MetaData 类的简单名称;(定义一个私有最终静态的字符串变量 TAG值为 MetaData 类的简单名称;)
private String mRelatedGid = null;
// 私有字符串变量 mRelatedGid初始值为 null定义一个私有字符串变量 mRelatedGid初始值为 null
public void setMeta(String gid, JSONObject metaInfo) {
// 公共方法 setMeta接收字符串 gid 和 JSON 对象 metaInfo定义一个名为 setMeta 的公共方法,接收一个字符串 gid 和一个 JSONObject 对象 metaInfo
try {
// 尝试执行以下代码块;(开始 try 代码块;)
metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid);
// 将 gid 放入 metaInfo 的特定键中;(尝试将 gid 放入 metaInfo 对象中,键为 GTaskStringUtils.META_HEAD_GTASK_ID
} catch (JSONException e) {
// 如果发生 JSON 异常,进入此代码块;(捕获 JSONException 异常;)
Log.e(TAG, "failed to put related gid");
// 输出错误日志打印错误日志提示“failed to put related gid”
}
setNotes(metaInfo.toString());
// 设置 notes 属性;(设置当前对象的 notes 属性为 metaInfo 的字符串表示形式;)
setName(GTaskStringUtils.META_NOTE_NAME);
// 设置 name 属性;(设置当前对象的 name 属性为 GTaskStringUtils.META_NOTE_NAME
}
public String getRelatedGid() {
// 公共方法 getRelatedGid定义一个名为 getRelatedGid 的公共方法;)
return mRelatedGid;
// 返回 mRelatedGid返回 mRelatedGid 的值;)
}
@Override
public boolean isWorthSaving() {
// 重写方法 isWorthSaving重写父类的 isWorthSaving 方法;)
return getNotes()!= null;
// 返回 notes 属性不为 null 的判断结果;(返回当前对象的 notes 属性不为 null 的判断结果;)
}
@Override
public void setContentByRemoteJSON(JSONObject js) {
// 重写方法 setContentByRemoteJSON重写父类的 setContentByRemoteJSON 方法;)
super.setContentByRemoteJSON(js);
// 调用父类的同名方法;(先调用父类的 setContentByRemoteJSON 方法;)
if (getNotes()!= null) {
// 如果 notes 属性不为 null如果当前对象的 notes 属性不为 null
try {
// 尝试执行以下代码块;(开始 try 代码块;)
JSONObject metaInfo = new JSONObject(getNotes().trim());
// 创建一个新的 JSON 对象,从 notes 属性的字符串表示形式中获取;(从当前对象的 notes 属性的字符串表示形式中创建一个新的 JSONObject 对象;)
mRelatedGid = metaInfo.getString(GTaskStringUtils.META_HEAD_GTASK_ID);
// 获取相关的 gid从新创建的 JSONObject 对象中获取特定键的值,并赋值给 mRelatedGid
} catch (JSONException e) {
// 如果发生 JSON 异常,进入此代码块;(捕获 JSONException 异常;)
Log.w(TAG, "failed to get related gid");
// 输出警告日志打印警告日志提示“failed to get related gid”
mRelatedGid = null;
// 将 mRelatedGid 设为 null将 mRelatedGid 设为 null
}
}
}
@Override
public void setContentByLocalJSON(JSONObject js) {
// 重写方法 setContentByLocalJSON重写父类的 setContentByLocalJSON 方法;)
// this function should not be called
// 此函数不应被调用;(注释说明这个函数不应该被调用;)
throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called");
// 抛出非法访问错误;(抛出 IllegalAccessError 异常提示“MetaData:setContentByLocalJSON should not be called”
}
@Override
public JSONObject getLocalJSONFromContent() {
// 重写方法 getLocalJSONFromContent重写父类的 getLocalJSONFromContent 方法;)
throw new IllegalAccessError("MetaData:getLocalJSONFromContent should not be called");
// 抛出非法访问错误;(抛出 IllegalAccessError 异常提示“MetaData:getLocalJSONFromContent should not be called”
}
@Override
public int getSyncAction(Cursor c) {
// 重写方法 getSyncAction重写父类的 getSyncAction 方法;)
throw new IllegalAccessError("MetaData:getSyncAction should not be called");
// 抛出非法访问错误;(抛出 IllegalAccessError 异常提示“MetaData:getSyncAction should not be called”
}
}

@ -0,0 +1,154 @@
/*
* Copyright (c) 2010 - 2011, The MiCode Open Source Community (www.micode.net)
* c2010 - 2011MiCode www.micode.net
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Apache License 2.0
* 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
* 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;(包名为 net.micode.notes.gtask.data
import android.database.Cursor;
// 导入 android.database.Cursor导入 Android 的数据库游标类;)
import org.json.JSONObject;
// 导入 org.json.JSONObject导入 JSON 对象类;)
public abstract class Node {
// 公共抽象类 Node定义一个名为 Node 的公共抽象类;)
public static final int SYNC_ACTION_NONE = 0;
// 公共静态最终整型变量 SYNC_ACTION_NONE赋值为 0定义一个公共静态最终的整型变量 SYNC_ACTION_NONE值为 0
public static final int SYNC_ACTION_ADD_REMOTE = 1;
// 公共静态最终整型变量 SYNC_ACTION_ADD_REMOTE赋值为 1定义一个公共静态最终的整型变量 SYNC_ACTION_ADD_REMOTE值为 1
public static final int SYNC_ACTION_ADD_LOCAL = 2;
// 公共静态最终整型变量 SYNC_ACTION_ADD_LOCAL赋值为 2定义一个公共静态最终的整型变量 SYNC_ACTION_ADD_LOCAL值为 2
public static final int SYNC_ACTION_DEL_REMOTE = 3;
// 公共静态最终整型变量 SYNC_ACTION_DEL_REMOTE赋值为 3定义一个公共静态最终的整型变量 SYNC_ACTION_DEL_REMOTE值为 3
public static final int SYNC_ACTION_DEL_LOCAL = 4;
// 公共静态最终整型变量 SYNC_ACTION_DEL_LOCAL赋值为 4定义一个公共静态最终的整型变量 SYNC_ACTION_DEL_LOCAL值为 4
public static final int SYNC_ACTION_UPDATE_REMOTE = 5;
// 公共静态最终整型变量 SYNC_ACTION_UPDATE_REMOTE赋值为 5定义一个公共静态最终的整型变量 SYNC_ACTION_UPDATE_REMOTE值为 5
public static final int SYNC_ACTION_UPDATE_LOCAL = 6;
// 公共静态最终整型变量 SYNC_ACTION_UPDATE_LOCAL赋值为 6定义一个公共静态最终的整型变量 SYNC_ACTION_UPDATE_LOCAL值为 6
public static final int SYNC_ACTION_UPDATE_CONFLICT = 7;
// 公共静态最终整型变量 SYNC_ACTION_UPDATE_CONFLICT赋值为 7定义一个公共静态最终的整型变量 SYNC_ACTION_UPDATE_CONFLICT值为 7
public static final int SYNC_ACTION_ERROR = 8;
// 公共静态最终整型变量 SYNC_ACTION_ERROR赋值为 8定义一个公共静态最终的整型变量 SYNC_ACTION_ERROR值为 8
private String mGid;
// 私有字符串变量 mGid定义一个私有字符串变量 mGid
private String mName;
// 私有字符串变量 mName定义一个私有字符串变量 mName
private long mLastModified;
// 私有长整型变量 mLastModified定义一个私有长整型变量 mLastModified
private boolean mDeleted;
// 私有布尔型变量 mDeleted定义一个私有布尔型变量 mDeleted
public Node() {
// 公共构造函数;(定义一个公共的构造函数;)
mGid = null;
// 初始化 mGid 为 null将 mGid 初始化为 null
mName = "";
// 初始化 mName 为空字符串;(将 mName 初始化为空字符串;)
mLastModified = 0;
// 初始化 mLastModified 为 0将 mLastModified 初始化为 0
mDeleted = false;
// 初始化 mDeleted 为 false将 mDeleted 初始化为 false
}
public abstract JSONObject getCreateAction(int actionId);
// 公共抽象方法 getCreateAction接收整型参数 actionId定义一个公共抽象方法 getCreateAction接收一个整型参数 actionId返回一个 JSONObject 对象;)
public abstract JSONObject getUpdateAction(int actionId);
// 公共抽象方法 getUpdateAction接收整型参数 actionId定义一个公共抽象方法 getUpdateAction接收一个整型参数 actionId返回一个 JSONObject 对象;)
public abstract void setContentByRemoteJSON(JSONObject js);
// 公共抽象方法 setContentByRemoteJSON接收 JSONObject 参数 js定义一个公共抽象方法 setContentByRemoteJSON接收一个 JSONObject 参数 js
public abstract void setContentByLocalJSON(JSONObject js);
// 公共抽象方法 setContentByLocalJSON接收 JSONObject 参数 js定义一个公共抽象方法 setContentByLocalJSON接收一个 JSONObject 参数 js
public abstract JSONObject getLocalJSONFromContent();
// 公共抽象方法 getLocalJSONFromContent定义一个公共抽象方法 getLocalJSONFromContent返回一个 JSONObject 对象;)
public abstract int getSyncAction(Cursor c);
// 公共抽象方法 getSyncAction接收 Cursor 参数 c定义一个公共抽象方法 getSyncAction接收一个 Cursor 参数 c返回一个整型值
public void setGid(String gid) {
// 公共方法 setGid接收字符串参数 gid定义一个名为 setGid 的公共方法,接收一个字符串参数 gid
this.mGid = gid;
// 设置 mGid 的值;(将 this.mGid 赋值为 gid
}
public void setName(String name) {
// 公共方法 setName接收字符串参数 name定义一个名为 setName 的公共方法,接收一个字符串参数 name
this.mName = name;
// 设置 mName 的值;(将 this.mName 赋值为 name
}
public void setLastModified(long lastModified) {
// 公共方法 setLastModified接收长整型参数 lastModified定义一个名为 setLastModified 的公共方法,接收一个长整型参数 lastModified
this.mLastModified = lastModified;
// 设置 mLastModified 的值;(将 this.mLastModified 赋值为 lastModified
}
public void setDeleted(boolean deleted) {
// 公共方法 setDeleted接收布尔型参数 deleted定义一个名为 setDeleted 的公共方法,接收一个布尔型参数 deleted
this.mDeleted = deleted;
// 设置 mDeleted 的值;(将 this.mDeleted 赋值为 deleted
}
public String getGid() {
// 公共方法 getGid定义一个名为 getGid 的公共方法;)
return this.mGid;
// 返回 mGid 的值;(返回 this.mGid 的值;)
}
public String getName() {
// 公共方法 getName定义一个名为 getName 的公共方法;)
return this.mName;
// 返回 mName 的值;(返回 this.mName 的值;)
}
public long getLastModified() {
// 公共方法 getLastModified定义一个名为 getLastModified 的公共方法;)
return this.mLastModified;
// 返回 mLastModified 的值;(返回 this.mLastModified 的值;)
}
public boolean getDeleted() {
// 公共方法 getDeleted定义一个名为 getDeleted 的公共方法;)
return this.mDeleted;
// 返回 mDeleted 的值;(返回 this.mDeleted 的值;)
}
}

@ -0,0 +1,373 @@
/*
* 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.
*/
// 版权声明2010 - 2011 年MiCode 开源社区www.micode.net
// 在 Apache License 2.0 协议下授权你不得在不符合该协议的情况下使用此文件。你可以在以下地址获取该协议的副本http://www.apache.org/licenses/LICENSE-2.0。
// 除非适用法律要求或书面同意,否则根据本许可证分发的软件是基于“按原样”基础提供的,不附带任何明示或暗示的保证或条件。请参阅许可证以了解管理权限和限制的特定语言。
package net.micode.notes.data;
// 包名为 net.micode.notes.data。
import android.net.Uri;
// 导入安卓网络包中的 Uri 类。
public class Notes {
// 定义公共类 Notes。
public static final String AUTHORITY = "micode_notes";
// 定义静态常量 AUTHORITY值为“micode_notes”。
public static final String TAG = "Notes";
// 定义静态常量 TAG值为“Notes”。
public static final int TYPE_NOTE = 0;
// 定义静态常量 TYPE_NOTE值为 0。
public static final int TYPE_FOLDER = 1;
// 定义静态常量 TYPE_FOLDER值为 1。
public static final int TYPE_SYSTEM = 2;
// 定义静态常量 TYPE_SYSTEM值为 2。
/**
* ID
* {@link Notes#ID_ROOT_FOLDER}
* {@link Notes#ID_TEMPARAY_FOLDER}
* {@link Notes#ID_CALL_RECORD_FOLDER}
*/
// 注释解释了后续常量的用途。
public static final int ID_ROOT_FOLDER = 0;
// 定义静态常量 ID_ROOT_FOLDER值为 0。
public static final int ID_TEMPARAY_FOLDER = -1;
// 定义静态常量 ID_TEMPARAY_FOLDER值为 -1。
public static final int ID_CALL_RECORD_FOLDER = -2;
// 定义静态常量 ID_CALL_RECORD_FOLDER值为 -2。
public static final int ID_TRASH_FOLER = -3;
// 定义静态常量 ID_TRASH_FOLER值为 -3。
public static final String INTENT_EXTRA_ALERT_DATE = "net.micode.notes.alert_date";
// 定义静态常量 INTENT_EXTRA_ALERT_DATE值为“net.micode.notes.alert_date”。
public static final String INTENT_EXTRA_BACKGROUND_ID = "net.micode.notes.background_color_id";
// 定义静态常量 INTENT_EXTRA_BACKGROUND_ID值为“net.micode.notes.background_color_id”。
public static final String INTENT_EXTRA_WIDGET_ID = "net.micode.notes.widget_id";
// 定义静态常量 INTENT_EXTRA_WIDGET_ID值为“net.micode.notes.widget_id”。
public static final String INTENT_EXTRA_WIDGET_TYPE = "net.micode.notes.widget_type";
// 定义静态常量 INTENT_EXTRA_WIDGET_TYPE值为“net.micode.notes.widget_type”。
public static final String INTENT_EXTRA_FOLDER_ID = "net.micode.notes.folder_id";
// 定义静态常量 INTENT_EXTRA_FOLDER_ID值为“net.micode.notes.folder_id”。
public static final String INTENT_EXTRA_CALL_DATE = "net.micode.notes.call_date";
// 定义静态常量 INTENT_EXTRA_CALL_DATE值为“net.micode.notes.call_date”。
public static final int TYPE_WIDGET_INVALIDE = -1;
// 定义静态常量 TYPE_WIDGET_INVALIDE值为 -1。
public static final int TYPE_WIDGET_2X = 0;
// 定义静态常量 TYPE_WIDGET_2X值为 0。
public static final int TYPE_WIDGET_4X = 1;
// 定义静态常量 TYPE_WIDGET_4X值为 1。
public static class DataConstants {
// 定义静态内部类 DataConstants。
public static final String NOTE = TextNote.CONTENT_ITEM_TYPE;
// 定义静态常量 NOTE值为 TextNote 类中的 CONTENT_ITEM_TYPE。
public static final String CALL_NOTE = CallNote.CONTENT_ITEM_TYPE;
// 定义静态常量 CALL_NOTE值为 CallNote 类中的 CONTENT_ITEM_TYPE。
}
/**
* Uri
*/
public static final Uri CONTENT_NOTE_URI = Uri.parse("content://" + AUTHORITY + "/note");
// 定义静态常量 CONTENT_NOTE_URI通过解析字符串“content://micode_notes/note”得到 Uri 对象。
/**
* Uri
*/
public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data");
// 定义静态常量 CONTENT_DATA_URI通过解析字符串“content://micode_notes/data”得到 Uri 对象。
public interface NoteColumns {
// 定义公共接口 NoteColumns。
/**
* ID
*/
public static final String ID = "_id";
// 定义静态常量 ID值为“_id”。
/**
* ID
*/
public static final String PARENT_ID = "parent_id";
// 定义静态常量 PARENT_ID值为“parent_id”。
/**
*
*/
public static final String CREATED_DATE = "created_date";
// 定义静态常量 CREATED_DATE值为“created_date”。
/**
*
*/
public static final String MODIFIED_DATE = "modified_date";
// 定义静态常量 MODIFIED_DATE值为“modified_date”。
/**
*
*/
public static final String ALERTED_DATE = "alert_date";
// 定义静态常量 ALERTED_DATE值为“alert_date”。
/**
*
*/
public static final String SNIPPET = "snippet";
// 定义静态常量 SNIPPET值为“snippet”。
/**
* ID
*/
public static final String WIDGET_ID = "widget_id";
// 定义静态常量 WIDGET_ID值为“widget_id”。
/**
*
*/
public static final String WIDGET_TYPE = "widget_type";
// 定义静态常量 WIDGET_TYPE值为“widget_type”。
/**
* ID
*/
public static final String BG_COLOR_ID = "bg_color_id";
// 定义静态常量 BG_COLOR_ID值为“bg_color_id”。
/**
*
*/
public static final String HAS_ATTACHMENT = "has_attachment";
// 定义静态常量 HAS_ATTACHMENT值为“has_attachment”。
/**
*
*/
public static final String NOTES_COUNT = "notes_count";
// 定义静态常量 NOTES_COUNT值为“notes_count”。
/**
*
*/
public static final String TYPE = "type";
// 定义静态常量 TYPE值为“type”。
/**
* ID
*/
public static final String SYNC_ID = "sync_id";
// 定义静态常量 SYNC_ID值为“sync_id”。
/**
*
*/
public static final String LOCAL_MODIFIED = "local_modified";
// 定义静态常量 LOCAL_MODIFIED值为“local_modified”。
/**
* ID
*/
public static final String ORIGIN_PARENT_ID = "origin_parent_id";
// 定义静态常量 ORIGIN_PARENT_ID值为“origin_parent_id”。
/**
* gtask ID
*/
public static final String GTASK_ID = "gtask_id";
// 定义静态常量 GTASK_ID值为“gtask_id”。
/**
*
*/
public static final String VERSION = "version";
// 定义静态常量 VERSION值为“version”。
}
public interface DataColumns {
// 定义公共接口 DataColumns。
/**
* ID
*/
public static final String ID = "_id";
// 定义静态常量 ID值为“_id”。
/**
* MIME
*/
public static final String MIME_TYPE = "mime_type";
// 定义静态常量 MIME_TYPE值为“mime_type”。
/**
* ID
*/
public static final String NOTE_ID = "note_id";
// 定义静态常量 NOTE_ID值为“note_id”。
/**
*
*/
public static final String CREATED_DATE = "created_date";
// 定义静态常量 CREATED_DATE值为“created_date”。
/**
*
*/
public static final String MODIFIED_DATE = "modified_date";
// 定义静态常量 MODIFIED_DATE值为“modified_date”。
/**
*
*/
public static final String CONTENT = "content";
// 定义静态常量 CONTENT值为“content”。
/**
* {@link #MIMETYPE}
*/
public static final String DATA1 = "data1";
// 定义静态常量 DATA1值为“data1”。
/**
* {@link #MIMETYPE}
*/
public static final String DATA2 = "data2";
// 定义静态常量 DATA2值为“data2”。
/**
* {@link #MIMETYPE}
*/
public static final String DATA3 = "data3";
// 定义静态常量 DATA3值为“data3”。
/**
* {@link #MIMETYPE}
*/
public static final String DATA4 = "data4";
// 定义静态常量 DATA4值为“data4”。
/**
* {@link #MIMETYPE}
*/
public static final String DATA5 = "data5";
// 定义静态常量 DATA5值为“data5”。
}
public static final class TextNote implements DataColumns {
// 定义静态内部类 TextNote实现 DataColumns 接口。
/**
* 1 0
*/
public static final String MODE = DATA1;
// 定义静态常量 MODE值为 DATA1。
public static final int MODE_CHECK_LIST = 1;
// 定义静态常量 MODE_CHECK_LIST值为 1。
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/text_note";
// 定义静态常量 CONTENT_TYPE值为“vnd.android.cursor.dir/text_note”。
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/text_note";
// 定义静态常量 CONTENT_ITEM_TYPE值为“vnd.android.cursor.item/text_note”。
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/text_note");
// 定义静态常量 CONTENT_URI通过解析字符串“content://micode_notes/text_note”得到 Uri 对象。
}
public static final class CallNote implements DataColumns {
// 定义静态内部类 CallNote实现 DataColumns 接口。
/**
*
*/
public static final String CALL_DATE = DATA1;
// 定义静态常量 CALL_DATE值为 DATA1。
/**
*
*/
public static final String PHONE_NUMBER = DATA3;
// 定义静态常量 PHONE_NUMBER值为 DATA3。
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/call_note";
// 定义静态常量 CONTENT_TYPE值为“vnd.android.cursor.dir/call_note”。
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/call_note";
// 定义静态常量 CONTENT_ITEM_TYPE值为“vnd.android.cursor.item/call_note”。
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/call_note");
// 定义静态常量 CONTENT_URI通过解析字符串“content://micode_notes/call_note”得到 Uri 对象。
}
}

@ -0,0 +1,492 @@
/*
* 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.
*/
// 版权声明2010 - 2011 年MiCode 开源社区www.micode.net
// 遵循 Apache License 2.0 许可协议若不遵守该协议则不可使用此文件。可在以下地址获取许可证副本http://www.apache.org/licenses/LICENSE-2.0。
// 除非法律要求或书面同意,否则在该许可证下发布的软件基于“现状”发布,不提供任何形式的保证和条件。
// 许可证具体条款规定了权限和限制。
package net.micode.notes.data;
// 包声明:这个类属于 net.micode.notes.data 包。
import android.content.ContentValues;
// 导入用于存储键值对的数据容器类,通常用于向数据库中插入或更新数据。
import android.content.Context;
// 导入用于获取应用上下文的类。
import android.database.sqlite.SQLiteDatabase;
// 导入用于操作 SQLite 数据库的类。
import android.database.sqlite.SQLiteOpenHelper;
// 导入用于创建和管理 SQLite 数据库的帮助类,继承此类可以方便地创建和升级数据库。
import android.util.Log;
// 导入 Android 的日志工具类,用于在开发过程中输出调试信息和错误信息。
import net.micode.notes.data.Notes.DataColumns;
// 导入 Notes 类中的 DataColumns 内部类,可能包含与数据相关的常量或方法。
import net.micode.notes.data.Notes.DataConstants;
// 导入 Notes 类中的 DataConstants 内部类,可能包含一些常量定义。
import net.micode.notes.data.Notes.NoteColumns;
// 导入 Notes 类中的 NoteColumns 内部类,可能包含与笔记相关的常量或方法。
public class NotesDatabaseHelper extends SQLiteOpenHelper {
// 定义一个名为 NotesDatabaseHelper 的类,继承自 SQLiteOpenHelper用于创建和管理笔记数据库。
private static final String DB_NAME = "note.db";
// 定义数据库名称为“note.db”。
private static final int DB_VERSION = 4;
// 定义数据库版本号为 4。
public interface TABLE {
// 定义一个内部接口 TABLE用于表示数据库中的表名。
public static final String NOTE = "note";
// 定义名为“note”的表名常量。
public static final String DATA = "data";
// 定义名为“data”的表名常量。
}
private static final String TAG = "NotesDatabaseHelper";
// 用于日志输出的标记。
private static NotesDatabaseHelper mInstance;
// 单例实例。
private static final String CREATE_NOTE_TABLE_SQL =
"CREATE TABLE " + TABLE.NOTE + "(" +
NoteColumns.ID + " INTEGER PRIMARY KEY," +
NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.BG_COLOR_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.HAS_ATTACHMENT + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.NOTES_COUNT + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.SNIPPET + " TEXT NOT NULL DEFAULT ''," +
NoteColumns.TYPE + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," +
NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," +
NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" +
")";
// 创建“note”表的 SQL 语句。
private static final String CREATE_DATA_TABLE_SQL =
"CREATE TABLE " + TABLE.DATA + "(" +
DataColumns.ID + " INTEGER PRIMARY KEY," +
DataColumns.MIME_TYPE + " TEXT NOT NULL," +
DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
DataColumns.CONTENT + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA1 + " INTEGER," +
DataColumns.DATA2 + " INTEGER," +
DataColumns.DATA3 + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" +
")";
// 创建“data”表的 SQL 语句。
private static final String CREATE_DATA_NOTE_ID_INDEX_SQL =
"CREATE INDEX IF NOT EXISTS note_id_index ON " +
TABLE.DATA + "(" + DataColumns.NOTE_ID + ");";
// 创建“data”表中“note_id”索引的 SQL 语句。
/**
* Increase folder's note count when move note to the folder
*/
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER increase_folder_count_on_update "+
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END";
// 当将笔记移动到文件夹时增加文件夹的笔记数量的触发器 SQL。
/**
* Decrease folder's note count when move note from folder
*/
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_update " +
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0" + ";" +
" END";
// 当从文件夹中移动笔记时减少文件夹的笔记数量的触发器 SQL。
/**
* Increase folder's note count when insert new note to the folder
*/
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER =
"CREATE TRIGGER increase_folder_count_on_insert " +
" AFTER INSERT ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END";
// 当向文件夹中插入新笔记时增加文件夹的笔记数量的触发器 SQL。
/**
* Decrease folder's note count when delete note from the folder
*/
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0;" +
" END";
// 当从文件夹中删除笔记时减少文件夹的笔记数量的触发器 SQL。
/**
* Update note's content when insert data with type {@link DataConstants#NOTE}
*/
private static final String DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER =
"CREATE TRIGGER update_note_content_on_insert " +
" AFTER INSERT ON " + TABLE.DATA +
" WHEN new." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END";
// 当插入数据类型为 DataConstants.NOTE 的数据时更新笔记内容的触发器 SQL。
/**
* Update note's content when data with {@link DataConstants#NOTE} type has changed
*/
private static final String DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER update_note_content_on_update " +
" AFTER UPDATE ON " + TABLE.DATA +
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END";
// 当数据类型为 DataConstants.NOTE 的数据发生变化时更新笔记内容的触发器 SQL。
/**
* Update note's content when data with {@link DataConstants#NOTE} type has deleted
*/
private static final String DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER =
"CREATE TRIGGER update_note_content_on_delete " +
" AFTER delete ON " + TABLE.DATA +
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=''" +
" WHERE " + NoteColumns.ID + "=old." + DataColumns.NOTE_ID + ";" +
" END";
// 当数据类型为 DataConstants.NOTE 的数据被删除时更新笔记内容为空的触发器 SQL。
/**
* Delete datas belong to note which has been deleted
*/
private static final String NOTE_DELETE_DATA_ON_DELETE_TRIGGER =
"CREATE TRIGGER delete_data_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN" +
" DELETE FROM " + TABLE.DATA +
" WHERE " + DataColumns.NOTE_ID + "=old." + NoteColumns.ID + ";" +
" END";
// 当笔记被删除时删除属于该笔记的数据的触发器 SQL。
/**
* Delete notes belong to folder which has been deleted
*/
private static final String FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER =
"CREATE TRIGGER folder_delete_notes_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN" +
" DELETE FROM " + TABLE.NOTE +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END";
// 当文件夹被删除时删除属于该文件夹的笔记的触发器 SQL。
/**
* Move notes belong to folder which has been moved to trash folder
*/
private static final String FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER =
"CREATE TRIGGER folder_move_notes_on_trash " +
" AFTER UPDATE ON " + TABLE.NOTE +
" WHEN new." + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END";
// 当文件夹被移动到垃圾桶时,将属于该文件夹的笔记也移动到垃圾桶的触发器 SQL。
public NotesDatabaseHelper(Context context) {
// 构造函数,传入上下文对象。
super(context, DB_NAME, null, DB_VERSION);
// 调用父类构造函数,传入数据库名称、游标工厂和版本号。
}
public void createNoteTable(SQLiteDatabase db) {
// 创建“note”表的方法。
db.execSQL(CREATE_NOTE_TABLE_SQL);
// 执行创建“note”表的 SQL 语句。
reCreateNoteTableTriggers(db);
// 重新创建“note”表的触发器。
createSystemFolder(db);
// 创建系统文件夹。
Log.d(TAG, "note table has been created");
// 输出日志表明“note”表已创建。
}
private void reCreateNoteTableTriggers(SQLiteDatabase db) {
// 重新创建“note”表触发器的方法。
db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_update");
// 删除可能已存在的特定触发器。
db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_update");
// 删除可能已存在的特定触发器。
db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_delete");
// 删除可能已存在的特定触发器。
db.execSQL("DROP TRIGGER IF EXISTS delete_data_on_delete");
// 删除可能已存在的特定触发器。
db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_insert");
// 删除可能已存在的特定触发器。
db.execSQL("DROP TRIGGER IF EXISTS folder_delete_notes_on_delete");
// 删除可能已存在的特定触发器。
db.execSQL("DROP TRIGGER IF EXISTS folder_move_notes_on_trash");
// 删除可能已存在的特定触发器。
db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER);
// 执行创建新的触发器的 SQL 语句。
db.execSQL(NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER);
// 执行创建新的触发器的 SQL 语句。
db.execSQL(NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER);
// 执行创建新的触发器的 SQL 语句。
db.execSQL(NOTE_DELETE_DATA_ON_DELETE_TRIGGER);
// 执行创建新的触发器的 SQL 语句。
db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER);
// 执行创建新的触发器的 SQL 语句。
db.execSQL(FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER);
// 执行创建新的触发器的 SQL 语句。
db.execSQL(FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER);
// 执行创建新的触发器的 SQL 语句。
}
private void createSystemFolder(SQLiteDatabase db) {
// 创建系统文件夹的方法。
ContentValues values = new ContentValues();
// 创建一个 ContentValues 对象,用于存储要插入数据库的值。
/**
* call record foler for call notes
*/
values.put(NoteColumns.ID, Notes.ID_CALL_RECORD_FOLDER);
// 将特定值放入 ContentValues 中,用于插入记录文件夹。
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
// 将特定值放入 ContentValues 中,用于插入记录文件夹。
db.insert(TABLE.NOTE, null, values);
// 将数据插入“note”表。
/**
* root folder which is default folder
*/
values.clear();
// 清空 ContentValues。
values.put(NoteColumns.ID, Notes.ID_ROOT_FOLDER);
// 将特定值放入 ContentValues 中,用于插入根文件夹。
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
// 将特定值放入 ContentValues 中,用于插入根文件夹。
db.insert(TABLE.NOTE, null, values);
// 将数据插入“note”表。
/**
* temporary folder which is used for moving note
*/
values.clear();
// 清空 ContentValues。
values.put(NoteColumns.ID, Notes.ID_TEMPARAY_FOLDER);
// 将特定值放入 ContentValues 中,用于插入临时文件夹。
values.put values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
// 将特定值放入 ContentValues 中,用于插入临时文件夹的类型为系统类型。
db.insert(TABLE.NOTE, null, values);
// 将数据插入“note”表。
/**
* create trash folder
*/
values.clear();
// 清空 ContentValues。
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
// 将特定值放入 ContentValues 中,用于插入垃圾桶文件夹的 ID。
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
// 将特定值放入 ContentValues 中,用于插入垃圾桶文件夹的类型为系统类型。
db.insert(TABLE.NOTE, null, values);
// 将数据插入“note”表。
}
public void createDataTable(SQLiteDatabase db) {
// 创建“data”表的方法。
db.execSQL(CREATE_DATA_TABLE_SQL);
// 执行创建“data”表的 SQL 语句。
reCreateDataTableTriggers(db);
// 重新创建“data”表的触发器。
db.execSQL(CREATE_DATA_NOTE_ID_INDEX_SQL);
// 创建“data”表中“note_id”索引。
Log.d(TAG, "data table has been created");
// 输出日志表明“data”表已创建。
}
private void reCreateDataTableTriggers(SQLiteDatabase db) {
// 重新创建“data”表触发器的方法。
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_insert");
// 删除可能已存在的特定触发器。
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_update");
// 删除可能已存在的特定触发器。
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_delete");
// 删除可能已存在的特定触发器。
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER);
// 执行创建新的触发器的 SQL 语句。
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER);
// 执行创建新的触发器的 SQL 语句。
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER);
// 执行创建新的触发器的 SQL 语句。
}
static synchronized NotesDatabaseHelper getInstance(Context context) {
// 获取单例实例的静态方法。
if (mInstance == null) {
// 如果单例实例为空。
mInstance = new NotesDatabaseHelper(context);
// 创建一个新的 NotesDatabaseHelper 实例并赋值给单例实例。
}
return mInstance;
// 返回单例实例。
}
@Override
public void onCreate(SQLiteDatabase db) {
// 重写 onCreate 方法,在数据库首次创建时被调用。
createNoteTable(db);
// 创建“note”表。
createDataTable(db);
// 创建“data”表。
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// 重写 onUpgrade 方法,在数据库版本升级时被调用。
boolean reCreateTriggers = false;
// 标记是否需要重新创建触发器。
boolean skipV2 = false;
// 标记是否跳过版本 2 的升级步骤。
if (oldVersion == 1) {
// 如果当前数据库版本为 1。
upgradeToV2(db);
// 执行升级到版本 2 的方法。
skipV2 = true; // this upgrade including the upgrade from v2 to v3
// 设置跳过版本 2 的标记为 true表示这个升级包含了从版本 2 到版本 3 的升级步骤。
oldVersion++;
// 将旧版本号加 1。
}
if (oldVersion == 2 &&!skipV2) {
// 如果当前数据库版本为 2 且没有跳过版本 2 的升级步骤。
upgradeToV3(db);
// 执行升级到版本 3 的方法。
reCreateTriggers = true;
// 设置需要重新创建触发器的标记为 true。
oldVersion++;
// 将旧版本号加 1。
}
if (oldVersion == 3) {
// 如果当前数据库版本为 3。
upgradeToV4(db);
// 执行升级到版本 4 的方法。
oldVersion++;
// 将旧版本号加 1。
}
if (reCreateTriggers) {
// 如果需要重新创建触发器。
reCreateNoteTableTriggers(db);
// 重新创建“note”表的触发器。
reCreateDataTableTriggers(db);
// 重新创建“data”表的触发器。
}
if (oldVersion!= newVersion) {
// 如果旧版本号与新版本号不相等。
throw new IllegalStateException("Upgrade notes database to version " + newVersion
+ "fails");
// 抛出异常,表示数据库升级失败。
}
}
private void upgradeToV2(SQLiteDatabase db) {
// 升级到版本 2 的方法。
db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE);
// 如果存在“note”表则删除它。
db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA);
// 如果存在“data”表则删除它。
createNoteTable(db);
// 创建“note”表。
createDataTable(db);
// 创建“data”表。
}
private void upgradeToV3(SQLiteDatabase db) {
// 升级到版本 3 的方法。
// drop unused triggers
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_insert");
// 删除未使用的触发器(如果存在)。
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_delete");
// 删除未使用的触发器(如果存在)。
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_update");
// 删除未使用的触发器(如果存在)。
// add a column for gtask id
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.GTASK_ID
+ " TEXT NOT NULL DEFAULT ''");
// 在“note”表中添加一个用于存储 gtask id 的列。
// add a trash system folder
ContentValues values = new ContentValues();
// 创建一个 ContentValues 对象,用于存储要插入数据库的值。
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
// 将垃圾桶文件夹的 ID 放入 ContentValues 中。
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
// 将垃圾桶文件夹的类型为系统类型放入 ContentValues 中。
db.insert(TABLE.NOTE, null, values);
// 将数据插入“note”表。
}
private void upgradeToV4(SQLiteDatabase db) {
// 升级到版本 4 的方法。
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION
+ " INTEGER NOT NULL DEFAULT 0");
// 在“note”表中添加一个版本号列。
}
}

@ -0,0 +1,547 @@
/*
* 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.
*/
// 版权声明2010 - 2011 年MiCode 开源社区www.micode.net
// 在 Apache License 2.0 协议下授权你不得在不符合该协议的情况下使用此文件。你可以在以下地址获取该协议的副本http://www.apache.org/licenses/LICENSE-2.0。
// 除非适用法律要求或书面同意,否则根据本许可证分发的软件是基于“按原样”基础提供的,不附带任何明示或暗示的保证或条件。请参阅许可证以了解管理权限和限制的特定语言。
package net.micode.notes.data;
import android.app.SearchManager;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Intent;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import net.micode.notes.R;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.NotesDatabaseHelper.TABLE;
// 导入相关的包和类。
public class NotesProvider extends ContentProvider {
// 定义公共类 NotesProvider继承自 ContentProvider。
private static final UriMatcher mMatcher;
// 定义静态的 UriMatcher 对象 mMatcher。
private NotesDatabaseHelper mHelper;
// 定义 NotesDatabaseHelper 对象 mHelper。
private static final String TAG = "NotesProvider";
// 定义静态常量 TAG值为“NotesProvider”。
private static final int URI_NOTE = 1;
// 定义常量 URI_NOTE值为 1。
private static final int URI_NOTE_ITEM = 2;
// 定义常量 URI_NOTE_ITEM值为 2。
private static final int URI_DATA = 3;
// 定义常量 URI_DATA值为 3。
private static final int URI_DATA_ITEM = 4;
// 定义常量 URI_DATA_ITEM值为 4。
private static final int URI_SEARCH = 5;
// 定义常量 URI_SEARCH值为 5。
private static final int URI_SEARCH_SUGGEST = 6;
// 定义常量 URI_SEARCH_SUGGEST值为 6。
static {
// 静态初始化块。
mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
// 创建一个新的 UriMatcher 对象,并设置初始匹配结果为 UriMatcher.NO_MATCH。
mMatcher.addURI(Notes.AUTHORITY, "note", URI_NOTE);
// 将 Uri “content://micode_notes/note” 与常量 URI_NOTE 关联。
mMatcher.addURI(Notes.AUTHORITY, "note/#", URI_NOTE_ITEM);
// 将 Uri “content://micode_notes/note/[ID]” 与常量 URI_NOTE_ITEM 关联。
mMatcher.addURI(Notes.AUTHORITY, "data", URI_DATA);
// 将 Uri “content://micode_notes/data” 与常量 URI_DATA 关联。
mMatcher.addURI(Notes.AUTHORITY, "data/#", URI_DATA_ITEM);
// 将 Uri “content://micode_notes/data/[ID]” 与常量 URI_DATA_ITEM 关联。
mMatcher.addURI(Notes.AUTHORITY, "search", URI_SEARCH);
// 将 Uri “content://micode_notes/search” 与常量 URI_SEARCH 关联。
mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, URI_SEARCH_SUGGEST);
// 将 Uri “content://micode_notes/search_query”根据 SearchManager.SUGGEST_URI_PATH_QUERY与常量 URI_SEARCH_SUGGEST 关联。
mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", URI_SEARCH_SUGGEST);
// 将 Uri “content://micode_notes/search_query/[SEARCH_STRING]”(根据 SearchManager.SUGGEST_URI_PATH_QUERY 和通配符)与常量 URI_SEARCH_SUGGEST 关联。
}
/**
* x'0A' represents the '\n' character in sqlite. For title and content in the search result,
* we will trim '\n' and white space in order to show more information.
*/
// 注释说明以下字符串常量的用途。
private static final String NOTES_SEARCH_PROJECTION = NoteColumns.ID + ","
+ NoteColumns.ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA + ","
+ "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_1 + ","
+ "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_2 + ","
+ R.drawable.search_result + " AS " + SearchManager.SUGGEST_COLUMN_ICON_1 + ","
+ "'" + Intent.ACTION_VIEW + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_ACTION + ","
+ "'" + Notes.TextNote.CONTENT_TYPE + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA;
// 定义常量 NOTES_SEARCH_PROJECTION用于搜索结果中的投影列。
private static String NOTES_SNIPPET_SEARCH_QUERY = "SELECT " + NOTES_SEARCH_PROJECTION
+ " FROM " + TABLE.NOTE
+ " WHERE " + NoteColumns.SNIPPET + " LIKE?"
+ " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER
+ " AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE;
// 定义常量 NOTES_SNIPPET_SEARCH_QUERY用于搜索笔记片段的查询语句。
@Override
public boolean onCreate() {
// 重写 onCreate 方法。
mHelper = NotesDatabaseHelper.getInstance(getContext());
// 获取 NotesDatabaseHelper 的实例。
return true;
// 返回 true表示创建成功。
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
// 重写 query 方法,用于查询数据。
Cursor c = null;
// 定义游标对象 c并初始化为 null。
SQLiteDatabase db = mHelper.getReadableDatabase();
// 获取可读的 SQLiteDatabase 对象。
String id = null;
// 定义字符串 id初始化为 null。
switch (mMatcher.match(uri)) {
// 根据 Uri 匹配结果进行分支处理。
case URI_NOTE:
c = db.query(TABLE.NOTE, projection, selection, selectionArgs, null, null,
sortOrder);
// 查询所有笔记。
break;
case URI_NOTE_ITEM:
id = uri.getPathSegments().get(1);
// 获取笔记的 ID。
c = db.query(TABLE.NOTE, projection, NoteColumns.ID + "=" + id
+ parseSelection(selection), selectionArgs, null, null, sortOrder);
// 根据 ID 查询单个笔记。
break;
case URI_DATA:
c = db.query(TABLE.DATA, projection, selection, selectionArgs, null, null,
sortOrder);
// 查询所有数据。
break;
case URI_DATA_ITEM:
id = uri.getPathSegments().get(1);
// 获取数据的 ID。
c = db.query(TABLE.DATA, projection, DataColumns.ID + "=" + id
+ parseSelection(selection), selectionArgs, null, null, sortOrder);
// 根据 ID 查询单个数据。
break;
case URI_SEARCH:
case URI_SEARCH_SUGGEST:
if (sortOrder!= null || projection!= null) {
// 如果排序顺序或投影不为空,则抛出异常。
throw new IllegalArgumentException(
"do not specify sortOrder, selection, selectionArgs, or projection" + "with this query");
}
String searchString = null;
// 定义字符串 searchString初始化为 null。
if (mMatcher.match(uri) == URI_SEARCH_SUGGEST) {
// 如果是搜索建议的 Uri。
if (uri.getPathSegments().size() > 1) {
// 如果路径段数量大于 1。
searchString = uri.getPathSegments().get(1);
// 获取搜索字符串。
}
} else {
// 否则是普通搜索的 Uri。
searchString = uri.getQueryParameter("pattern");
// 从查询参数中获取搜索字符串。
}
if (TextUtils.isEmpty(searchString)) {
// 如果搜索字符串为空。
return null;
// 返回 null。
}
try {
// 尝试执行查询。
searchString = String.format("%%%s%%", searchString);
// 格式化搜索字符串。
c = db.rawQuery(NOTES_SNIPPET_SEARCH_QUERY,
new String[]{searchString});
// 执行查询。
} catch (IllegalStateException ex) {
// 捕获异常。
Log.e(TAG, "got exception: " + ex.toString());
// 记录错误日志。
}
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
// 如果 Uri 不匹配任何已知的情况,抛出异常。
}
if (c!= null) {
// 如果游标不为 null。
c.setNotificationUri(getContext().getContentResolver(), uri);
// 设置通知 Uri。
}
return c;
// 返回游标。
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// 重写 insert 方法,用于插入数据。
SQLiteDatabase db = mHelper.getWritableDatabase();
// 获取可写的 SQLiteDatabase 对象。
long dataId = 0, noteId = 0, insertedId = 0;
// 定义长整型变量 dataId、noteId 和 insertedId并初始化为 0。
switch (mMatcher.match(uri)) {
// 根据 Uri 匹配结果进行分支处理。
case URI_NOTE:
insertedId = noteId = db.insert(TABLE.NOTE, null, values);
// 插入笔记。
break;
case URI_DATA:
if (values.containsKey(DataColumns.NOTE_ID)) {
// 如果 ContentValues 中包含 NOTE_ID。
noteId = values.getAsLong(DataColumns.NOTE_ID);
// 获取笔记 ID。
} else {
// 否则。
Log.d(TAG, "Wrong data format without note id:" + values.toString());
// 记录错误日志。
}
insertedId = dataId = db.insert(TABLE.DATA, null, values);
// 插入数据。
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
// 如果 Uri 不匹配任何已知的情况,抛出异常。
}
// Notify the note uri
if (noteId > 0) {
// 如果笔记 ID 大于 0。
getContext().getContentResolver().notifyChange(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null);
// 通知笔记 Uri 的更改。
}
// Notify the data uri
if (dataId > 0) {
// 如果数据 ID 大于 0。
getContext().getContentResolver().notifyChange(
ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), null);
// 通知数据 Uri 的更改。
}
return ContentUris.withAppendedId(uri, insertedId);
// 返回插入后的 Uri。
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// 重写 delete 方法,用于删除数据。
int count = 0;
// 定义整型变量 count初始化为 0。
String id = null;
// 定义字符串 id初始化为 null。
SQLiteDatabase db = mHelper.getWritableDatabase();
// 获取可写的 SQLiteDatabase 对象。
boolean deleteData = false;
// 定义布尔变量 deleteData初始化为 false。
switch (mMatcher.match(uri)) {
// 根据 Uri 匹配结果进行分支处理。
case URI_NOTE:
selection = "(" + selection + ") AND " + NoteColumns.ID + ">0 ";
count = db.delete(TABLE.NOTE, selection, selectionArgs);
// 删除笔记,添加条件 ID 大于 0。
break;
case URI_NOTE_ITEM:
id = uri.getPathSegments().get(1);
// 获取笔记的 ID。
/**
* ID that smaller than 0 is system folder which is not allowed to
* trash
*/
// 注释说明小于 0 的 ID 是系统文件夹,不允许删除。
long noteId = Long.valueOf(id);
// 将 ID 转换为长整型。
if (noteId <= 0) {
// 如果笔记 ID 小于等于 0。
break;
// 跳出循环。
}
count = db.delete(TABLE.NOTE,
NoteColumns.ID + "=" + id + parseSelection(selection), selectionArgs);
// 删除单个笔记。
break;
case URI_DATA:
count = db.delete(TABLE.DATA, selection, selectionArgs);
deleteData = true;
// 删除数据,设置 deleteData 为 true。
break;
case URI_DATA_ITEM:
id = uri.getPathSegments().get(1);
// 获取数据的 ID。
count = db.delete(TABLE.DATA,
DataColumns.ID + "=" + id + parseSelection(selection), selectionArgs);
deleteData = true;
// 删除单个数据,设置 deleteData 为 true。
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
// 如果 Uri 不匹配任何已知的情况,抛出异常。
}
if (count > 0) {
// 如果删除的数量大于 0。
if (deleteData) {
// 如果删除的是数据。
getContext().getContentResolver().notifyChange(Notes.CONTENT_NOTE_URI, null);
// 通知笔记 Uri 的更改。
}
getContext().getContentResolver().notifyChange(uri, null);
// 通知当前 Uri 的更改。
}
return count;
// 返回删除的数量。
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
// 重写 update 方法,用于更新数据。
int count = 0;
// 定义整型变量 count初始化为 0。
String id = null;
// 定义字符串 id初始化为 null。
SQLiteDatabase db = mHelper.getWritableDatabase();
// 获取可写的 SQLiteDatabase 对象。
boolean updateData = false;
// 定义布尔变量 updateData初始化为 false。
switch (mMatcher.match(uri)) {
// 根据 Uri 匹配结果进行分支处理。
case URI_NOTE:
increaseNoteVersion(-1, selection, selectionArgs);
// 更新所有笔记的版本号。
count = db.update(TABLE.NOTE, values, selection, selectionArgs);
// 更新笔记。
break;
case URI_NOTE_ITEM:
id = uri.getPathSegments().get(1);
// 获取笔记的 ID。
increaseNoteVersion(Long.valueOf(id), selection, selectionArgs);
// 更新指定笔记的版本号。
count = db.update(TABLE.NOTE, values, NoteColumns.ID + "=" + id
+ parseSelection(selection), selectionArgs);
// 更新单个笔记。
break;
case URI_DATA:
count = db.update(TABLE.DATA, values, selection, selectionArgs);
updateData = true;
// 更新数据,设置 updateData 为 true。
break;
case URI_DATA_ITEM:
id = uri.getPathSegments().get(1);
// 获取数据的 ID。
count = db.update(TABLE.DATA, values, DataColumns.ID + "=" + id
+ parseSelection(selection), selectionArgs);
updateData = true;
// 更新单个数据,设置 updateData 为 true。
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
// 如果 Uri 不匹配任何已知的情况,抛出
}
if (count > 0) {
// 如果更新操作影响的记录数大于 0。
if (updateData) {
// 如果更新了数据记录。
// 如果更新了数据记录,则通知监听器。
getContext().getContentResolver().notifyChange(Notes.CONTENT_NOTE_URI, null);
// 获取上下文环境通过内容解析器通知与笔记内容相关的监听器Notes.CONTENT_NOTE_URI数据发生了变化第二个参数为 null 表示没有额外的通知数据。
}
// 通知监听器指定的 URI 发生了变化。
getContext().getContentResolver().notifyChange(uri, null);
// 获取上下文环境,通过内容解析器通知本次更新操作对应的 URIuri的数据发生了变化第二个参数为 null 表示没有额外的通知数据。
}
return count;
// 返回更新操作所影响的记录数。
}
// 解析选择条件的方法。
private String parseSelection(String selection) {
// 定义一个私有方法,接收一个选择条件字符串参数。
return (!TextUtils.isEmpty(selection)? " AND (" + selection + ')' : "");
// 如果选择条件字符串不为空,返回在其前后加上“ AND (”和“)”的字符串;如果为空,返回空字符串。
}
// 增加笔记版本号的方法。
private void increaseNoteVersion(long id, String selection, String[] selectionArgs) {
// 定义一个私有方法,接收笔记的 ID、选择条件字符串和选择条件参数数组。
StringBuilder sql = new StringBuilder(120);
// 创建一个 StringBuilder 对象,用于构建 SQL 语句,初始容量为 120。
sql.append("UPDATE ");
// 在 StringBuilder 中添加“UPDATE ”。
sql.append(TABLE.NOTE);
// 添加表名 TABLE.NOTE。
sql.append(" SET ");
// 添加“ SET ”。
sql.append(NoteColumns.VERSION);
// 添加版本号列名 NoteColumns.VERSION。
sql.append("=" + NoteColumns.VERSION + "+1 ");
// 添加版本号设置的 SQL 片段,将版本号设置为当前版本号加 1。
if (id > 0 ||!TextUtils.isEmpty(selection)) {
// 如果传入的 ID 大于 0 或者选择条件字符串不为空。
sql.append(" WHERE ");
// 在 StringBuilder 中添加“ WHERE ”。
}
if (id > 0) {
// 如果传入的 ID 大于 0。
sql.append(NoteColumns.ID + "=" + String.valueOf(id));
// 添加笔记 ID 的条件到 StringBuilder 中。
}
if (!TextUtils.isEmpty(selection)) {
// 如果选择条件字符串不为空。
String selectString = id > 0? parseSelection(selection) : selection;
// 如果 ID 大于 0调用 parseSelection 方法处理选择条件字符串;否则直接使用选择条件字符串。
for (String args : selectionArgs) {
// 遍历选择条件参数数组。
selectString = selectString.replaceFirst("\\?", args);
// 将选择条件字符串中的第一个占位符替换为当前参数值。
}
sql.append(selectString);
// 将处理后的选择条件字符串添加到 StringBuilder 中。
}
mHelper.getWritableDatabase().execSQL(sql.toString());
// 使用数据库帮助类 mHelper 的可写数据库执行构建好的 SQL 语句。
}
// 内容提供器的 getType 方法,用于返回指定 URI 的 MIME 类型。
@Override
public String getType(Uri uri) {
// 重写内容提供器的 getType 方法,接收一个 URI 参数。
// TODO Auto-generated method stub
// 这里是一个待实现的方法注释。
return null;
// 返回 null表示当前未实现该方法。
}
}

@ -0,0 +1,304 @@
/*
* Copyright (c) 2010 - 2011, The MiCode Open Source Community (www.micode.net)
* c2010 - 2011MiCode www.micode.net
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Apache License 2.0
* 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
* 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这个包的名字是 net.micode.notes.gtask.data。
import android.content.ContentResolver;
// 导入 android.content.ContentResolver导入 Android 的内容解析器类。)
import android.content.ContentUris;
// 导入 android.content.ContentUris导入 Android 的内容 URI 工具类。)
import android.content.ContentValues;
// 导入 android.content.ContentValues导入 Android 的内容值类。)
import android.content.Context;
// 导入 android.content.Context导入 Android 的上下文类。)
import android.database.Cursor;
// 导入 android.database.Cursor导入 Android 的数据库游标类。)
import android.net.Uri;
// 导入 android.net.Uri导入 Android 的统一资源标识符类。)
import android.util.Log;
// 导入 android.util.Log导入 Android 的日志工具类。)
import net.micode.notes.data.Notes;
// 导入 net.micode.notes.data.Notes导入来自 net.micode.notes.data 的 Notes 类。)
import net.micode.notes.data.Notes.DataColumns;
// 导入 net.micode.notes.data.Notes.DataColumns导入 Notes 类中的数据列类。)
import net.micode.notes.data.Notes.DataConstants;
// 导入 net.micode.notes.data.Notes.DataConstants导入 Notes 类中的数据常量类。)
import net.micode.notes.data.Notes.NoteColumns;
// 导入 net.micode.notes.data.Notes.NoteColumns导入 Notes 类中的笔记列类。)
import net.micode.notes.data.NotesDatabaseHelper.TABLE;
// 导入 net.micode.notes.data.NotesDatabaseHelper.TABLE导入 Notes 数据库助手类中的表枚举。)
import net.micode.notes.gtask.exception.ActionFailureException;
// 导入 net.micode.notes.gtask.exception.ActionFailureException导入特定的异常类。
import org.json.JSONException;
// 导入 org.json.JSONException导入 JSON 处理的异常类。)
import org.json.JSONObject;
// 导入 org.json.JSONObject导入 JSON 对象类。)
public class SqlData {
// 公共类 SqlData定义一个名为 SqlData 的公共类。)
private static final String TAG = SqlData.class.getSimpleName();
// 私有静态最终字符串变量 TAG赋值为 SqlData 类的简单名称;(定义一个私有静态最终的字符串变量 TAG值为 SqlData 类的简单名称。)
private static final int INVALID_ID = -99999;
// 私有静态最终整型变量 INVALID_ID赋值为 -99999定义一个私有静态最终的整型变量 INVALID_ID值为 -99999。
public static final String[] PROJECTION_DATA = new String[] {
DataColumns.ID, DataColumns.MIME_TYPE, DataColumns.CONTENT, DataColumns.DATA1,
DataColumns.DATA3
};
// 公共静态最终字符串数组变量 PROJECTION_DATA定义一个公共静态最终的字符串数组变量 PROJECTION_DATA包含特定的数据列名称。
public static final int DATA_ID_COLUMN = 0;
// 公共静态最终整型变量 DATA_ID_COLUMN赋值为 0定义一个公共静态最终的整型变量 DATA_ID_COLUMN值为 0。
public static final int DATA_MIME_TYPE_COLUMN = 1;
// 公共静态最终整型变量 DATA_MIME_TYPE_COLUMN赋值为 1定义一个公共静态最终的整型变量 DATA_MIME_TYPE_COLUMN值为 1。
public static final int DATA_CONTENT_COLUMN = 2;
// 公共静态最终整型变量 DATA_CONTENT_COLUMN赋值为 2定义一个公共静态最终的整型变量 DATA_CONTENT_COLUMN值为 2。
public static final int DATA_CONTENT_DATA_1_COLUMN = 3;
// 公共静态最终整型变量 DATA_CONTENT_DATA_1_COLUMN赋值为 3定义一个公共静态最终的整型变量 DATA_CONTENT_DATA_1_COLUMN值为 3。
public static final int DATA_CONTENT_DATA_3_COLUMN = 4;
// 公共静态最终整型变量 DATA_CONTENT_DATA_3_COLUMN赋值为 4定义一个公共静态最终的整型变量 DATA_CONTENT_DATA_3_COLUMN值为 4。
private ContentResolver mContentResolver;
// 私有 ContentResolver 变量 mContentResolver定义一个私有变量 mContentResolver类型为 ContentResolver。
private boolean mIsCreate;
// 私有布尔型变量 mIsCreate定义一个私有布尔型变量 mIsCreate。
private long mDataId;
// 私有长整型变量 mDataId定义一个私有长整型变量 mDataId。
private String mDataMimeType;
// 私有字符串变量 mDataMimeType定义一个私有字符串变量 mDataMimeType。
private String mDataContent;
// 私有字符串变量 mDataContent定义一个私有字符串变量 mDataContent。
private long mDataContentData1;
// 私有长整型变量 mDataContentData1定义一个私有长整型变量 mDataContentData1。
private String mDataContentData3;
// 私有字符串变量 mDataContentData3定义一个私有字符串变量 mDataContentData3。
private ContentValues mDiffDataValues;
// 私有 ContentValues 变量 mDiffDataValues定义一个私有变量 mDiffDataValues类型为 ContentValues。
public SqlData(Context context) {
// 公共构造函数,接收 Context 参数;(定义一个公共构造函数,接收一个 Context 参数。)
mContentResolver = context.getContentResolver();
// 获取内容解析器;(将 context 的内容解析器赋值给 mContentResolver。
mIsCreate = true;
// 设置创建标志;(将 mIsCreate 设置为 true。
mDataId = INVALID_ID;
// 初始化数据 ID将 mDataId 初始化为 INVALID_ID。
mDataMimeType = DataConstants.NOTE;
// 初始化数据 MIME 类型;(将 mDataMimeType 初始化为 DataConstants.NOTE。
mDataContent = "";
// 初始化数据内容;(将 mDataContent 初始化为空字符串。)
mDataContentData1 = 0;
// 初始化数据内容数据 1将 mDataContentData1 初始化为 0。
mDataContentData3 = "";
// 初始化数据内容数据 3将 mDataContentData3 初始化为空字符串。)
mDiffDataValues = new ContentValues();
// 创建新的 ContentValues 对象;(创建一个新的 ContentValues 对象并赋值给 mDiffDataValues。
}
public SqlData(Context context, Cursor c) {
// 公共构造函数,接收 Context 和 Cursor 参数;(定义一个公共构造函数,接收一个 Context 参数和一个 Cursor 参数。)
mContentResolver = context.getContentResolver();
// 获取内容解析器;(将 context 的内容解析器赋值给 mContentResolver。
mIsCreate = false;
// 设置创建标志;(将 mIsCreate 设置为 false。
loadFromCursor(c);
// 从游标加载数据;(调用 loadFromCursor 方法,从传入的游标中加载数据。)
mDiffDataValues = new ContentValues();
// 创建新的 ContentValues 对象;(创建一个新的 ContentValues 对象并赋值给 mDiffDataValues。
}
private void loadFromCursor(Cursor c) {
// 私有方法 loadFromCursor接收 Cursor 参数;(定义一个私有方法 loadFromCursor接收一个 Cursor 参数。)
mDataId = c.getLong(DATA_ID_COLUMN);
// 获取数据 ID从游标中获取指定列的数据 ID并赋值给 mDataId。
mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN);
// 获取数据 MIME 类型;(从游标中获取指定列的数据 MIME 类型,并赋值给 mDataMimeType。
mDataContent = c.getString(DATA_CONTENT_COLUMN);
// 获取数据内容;(从游标中获取指定列的数据内容,并赋值给 mDataContent。
mDataContentData1 = c.getLong(DATA_CONTENT_DATA_1_COLUMN);
// 获取数据内容数据 1从游标中获取指定列的数据内容数据 1并赋值给 mDataContentData1。
mDataContentData3 = c.getString(DATA_CONTENT_DATA_3_COLUMN);
// 获取数据内容数据 3从游标中获取指定列的数据内容数据 3并赋值给 mDataContentData3。
}
public void setContent(JSONObject js) throws JSONException {
// 公共方法 setContent接收 JSONObject 参数;(定义一个公共方法 setContent接收一个 JSONObject 参数。)
long dataId = js.has(DataColumns.ID)? js.getLong(DataColumns.ID) : INVALID_ID;
// 获取数据 ID如果 JSONObject 中包含指定键,则获取对应的值作为数据 ID否则设置为 INVALID_ID。
if (mIsCreate || mDataId!= dataId) {
// 判断是否创建或数据 ID 不一致;(如果正在创建或者当前数据 ID 与新的数据 ID 不一致。)
mDiffDataValues.put(DataColumns.ID, dataId);
// 更新差异数据值;(将新的数据 ID 放入差异数据值的对应键中。)
}
mDataId = dataId;
// 更新数据 ID将 dataId 赋值给 mDataId。
String dataMimeType = js.has(DataColumns.MIME_TYPE)? js.getString(DataColumns.MIME_TYPE)
: DataConstants.NOTE;
// 获取数据 MIME 类型;(如果 JSONObject 中包含指定键,则获取对应的值作为数据 MIME 类型,否则设置为 DataConstants.NOTE。
if (mIsCreate ||!mDataMimeType.equals(dataMimeType)) {
// 判断是否创建或数据 MIME 类型不一致;(如果正在创建或者当前数据 MIME 类型与新的数据 MIME 类型不一致。)
mDiffDataValues.put(DataColumns.MIME_TYPE, dataMimeType);
// 更新差异数据值;(将新的数据 MIME 类型放入差异数据值的对应键中。)
}
mDataMimeType = dataMimeType;
// 更新数据 MIME 类型;(将 dataMimeType 赋值给 mDataMimeType。
String dataContent = js.has(DataColumns.CONTENT)? js.getString(DataColumns.CONTENT) : "";
// 获取数据内容;(如果 JSONObject 中包含指定键,则获取对应的值作为数据内容,否则设置为空字符串。)
if (mIsCreate ||!mDataContent.equals(dataContent)) {
// 判断是否创建或数据内容不一致;(如果正在创建或者当前数据内容与新的数据内容不一致。)
mDiffDataValues.put(DataColumns.CONTENT, dataContent);
// 更新差异数据值;(将新的数据内容放入差异数据值的对应键中。)
}
mDataContent = dataContent;
// 更新数据内容;(将 dataContent 赋值给 mDataContent。
long dataContentData1 = js.has(DataColumns.DATA1)? js.getLong(DataColumns.DATA1) : 0;
// 获取数据内容数据 1如果 JSONObject 中包含指定键,则获取对应的值作为数据内容数据 1否则设置为 0。
if (mIsCreate || mDataContentData1!= dataContentData1) {
// 判断是否创建或数据内容数据 1 不一致;(如果正在创建或者当前数据内容数据 1 与新的数据内容数据 1 不一致。)
mDiffDataValues.put(DataColumns.DATA1, dataContentData1);
// 更新差异数据值;(将新的数据内容数据 1 放入差异数据值的对应键中。)
}
mDataContentData1 = dataContentData1;
// 更新数据内容数据 1将 dataContentData1 赋值给 mDataContentData1。
String dataContentData3 = js.has(DataColumns.DATA3)? js.getString(DataColumns.DATA3) : "";
// 获取数据内容数据 3如果 JSONObject 中包含指定键,则获取对应的值作为数据内容数据 3否则设置为空字符串。
if (mIsCreate ||!mDataContentData3.equals(dataContentData3)) {
// 判断是否创建或数据内容数据 3 不一致;(如果正在创建或者当前数据内容数据 3 与新的数据内容数据 3 不一致。)
mDiffDataValues.put(DataColumns.DATA3, dataContentData3);
// 更新差异数据值;(将新的数据内容数据 3 放入差异数据值的对应键中。)
}
mDataContentData3 = dataContentData3;
// 更新数据内容数据 3将 dataContentData3 赋值给 mDataContentData3。
}
public JSONObject getContent() throws JSONException {
// 公共方法 getContent定义一个公共方法 getContent。
if (mIsCreate) {
// 判断是否正在创建;(如果正在创建。)
Log.e(TAG, "it seems that we haven't created this in database yet");
// 输出错误日志;(打印错误日志,提示“看起来我们还没有在数据库中创建这个。”)
return null;
// 返回 null返回 null。
}
JSONObject js = new JSONObject();
// 创建新的 JSONObject 对象;(创建一个新的 JSONObject 对象。)
js.put(DataColumns.ID, mDataId);
// 设置数据 ID将 mDataId 放入 JSONObject 的对应键中。)
js.put(DataColumns.MIME_TYPE, mDataMimeType);
// 设置数据 MIME 类型;(将 mDataMimeType 放入 JSONObject 的对应键中。)
js.put(DataColumns.CONTENT, mDataContent);
// 设置数据内容;(将 mDataContent 放入 JSONObject 的对应键中。)
js.put(DataColumns.DATA1, mDataContentData1);
// 设置数据内容数据 1将 mDataContentData1 放入 JSONObject 的对应键中。)
js.put(DataColumns.DATA3, mDataContentData3);
// 设置数据内容数据 3将 mDataContentData3 放入 JSONObject 的对应键中。)
return js;
// 返回 JSONObject 对象;(返回创建好的 JSONObject 对象。)
}
public void commit(long noteId, boolean validateVersion, long version) {
// 公共方法 commit接收长整型、布尔型和长整型参数定义一个公共方法 commit接收一个长整型 noteId、一个布尔型 validateVersion 和一个长整型 version 参数。)
if (mIsCreate) {
// 判断是否正在创建;(如果正在创建。)
if (mDataId == INVALID_ID && mDiffDataValues.containsKey(DataColumns.ID)) {
// 判断数据 ID 是否无效且差异数据值包含特定键;(如果数据 ID 无效且差异数据值中包含指定键。)
mDiffDataValues.remove(DataColumns.ID);
// 移除该键值对;(从差异数据值中移除该键值对。)
}
mDiffDataValues.put(DataColumns.NOTE_ID, noteId);
// 设置笔记 ID将 noteId 放入差异数据值的对应键中。)
Uri uri = mContentResolver.insert(Notes.CONTENT_DATA_URI, mDiffDataValues);
// 插入数据;(向 Notes 的内容数据 URI 中插入差异数据值,获取返回的 URI。
try {
// 尝试执行以下代码块;(开始 try 代码块。)
mDataId = Long.valueOf(uri.getPathSegments().get(1));
// 获取数据 ID从返回的 URI 中获取数据 ID并赋值给 mDataId。
} catch (NumberFormatException e) {
// 如果发生数字格式异常,进入此代码块;(捕获 NumberFormatException 异常。)
Log.e(TAG, "Get note id error :" + e.toString());
// 输出错误日志;(打印错误日志,提示“获取笔记 ID 错误:”加上异常信息。)
throw new ActionFailureException("create note failed");
// 抛出异常
} else {
// 如果不是正在创建;(如果不是正在创建的状态。)
if (mDiffDataValues.size() > 0) {
// 如果差异数据值不为空;(如果差异数据值有内容。)
int result = 0;
// 初始化结果变量;(先把结果设为 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)
});
// 更新数据并验证版本;(用内容解析器更新数据,同时验证版本。)
}
if (result == 0) {
// 如果更新结果为 0如果更新没有效果。
Log.w(TAG, "there is no update. maybe user updates note when syncing");
// 输出警告日志;(打印警告日志,提示可能是用户在同步时更新了笔记。)
}
}
}
mDiffDataValues.clear();
// 清空差异数据值;(把差异数据值清空。)
mIsCreate = false;
// 设置不是创建状态;(设置当前不是创建新数据的状态。)
public long getId() {
// 获取 ID 的方法;(定义一个获取数据 ID 的方法。)
return mDataId;
// 返回数据 ID返回当前的数据 ID。
}

@ -0,0 +1,711 @@
/*
* 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;
// 导入笔记数据类
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;
// 导入 JSON 数组类
import org.json.JSONException;
// 导入 JSON 异常类
import org.json.JSONObject;
// 导入 JSON 对象类
import java.util.ArrayList;
// 导入 ArrayList 类
public class SqlNote {
// SQL 笔记类定义
private static final String TAG = SqlNote.class.getSimpleName();
// 定义静态常量 TAG为当前类名的简写
private static final int INVALID_ID = -99999;
// 定义无效 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;
// ID 列的索引常量
public static final int ALERTED_DATE_COLUMN = 1;
// 提醒日期列的索引常量
public static final int BG_COLOR_ID_COLUMN = 2;
// 背景颜色 ID 列的索引常量
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;
// 父 ID 列的索引常量
public static final int SNIPPET_COLUMN = 8;
// 摘要列的索引常量
public static final int TYPE_COLUMN = 9;
// 类型列的索引常量
public static final int WIDGET_ID_COLUMN = 10;
// 小部件 ID 列的索引常量
public static final int WIDGET_TYPE_COLUMN = 11;
// 小部件类型列的索引常量
public static final int SYNC_ID_COLUMN = 12;
// 同步 ID 列的索引常量
public static final int LOCAL_MODIFIED_COLUMN = 13;
// 本地修改列的索引常量
public static final int ORIGIN_PARENT_ID_COLUMN = 14;
// 原始父 ID 列的索引常量
public static final int GTASK_ID_COLUMN = 15;
// GTask ID 列的索引常量
public static final int VERSION_COLUMN = 16;
// 版本列的索引常量
private Context mContext;
// 定义上下文变量
private ContentResolver mContentResolver;
// 定义内容解析器变量
private boolean mIsCreate;
// 定义是否为创建状态的变量
private long mId;
// 定义 ID 变量
private long mAlertDate;
// 定义提醒日期变量
private int mBgColorId;
// 定义背景颜色 ID 变量
private long mCreatedDate;
// 定义创建日期变量
private int mHasAttachment;
// 定义是否有附件变量
private long mModifiedDate;
// 定义修改日期变量
private long mParentId;
// 定义父 ID 变量
private String mSnippet;
// 定义摘要变量
private int mType;
// 定义类型变量
private int mWidgetId;
// 定义小部件 ID 变量
private int mWidgetType;
// 定义小部件类型变量
private long mOriginParent;
// 定义原始父 ID 变量
private long mVersion;
// 定义版本变量
private ContentValues mDiffNoteValues;
// 定义差异笔记值变量
private ArrayList<SqlData> mDataList;
// 定义 SQL 数据列表变量
public SqlNote(Context context) {
// 无参构造函数,接受上下文参数
mContext = context;
// 将传入的上下文赋值给成员变量
mContentResolver = context.getContentResolver();
// 获取上下文的内容解析器并赋值给成员变量
mIsCreate = true;
// 设置为创建状态
mId = INVALID_ID;
// 设置 ID 为无效值
mAlertDate = 0;
// 设置提醒日期为 0
mBgColorId = ResourceParser.getDefaultBgId(context);
// 设置背景颜色 ID 为资源解析器获取的默认背景颜色 ID
mCreatedDate = System.currentTimeMillis();
// 设置创建日期为当前时间戳
mHasAttachment = 0;
// 设置是否有附件为 0
mModifiedDate = System.currentTimeMillis();
// 设置修改日期为当前时间戳
mParentId = 0;
// 设置父 ID 为 0
mSnippet = "";
// 设置摘要为空字符串
mType = Notes.TYPE_NOTE;
// 设置类型为笔记类型
mWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
// 设置小部件 ID 为无效值
mWidgetType = Notes.TYPE_WIDGET_INVALIDE;
// 设置小部件类型为无效值
mOriginParent = 0;
// 设置原始父 ID 为 0
mVersion = 0;
// 设置版本为 0
mDiffNoteValues = new ContentValues();
// 创建新的内容值对象并赋值给差异笔记值变量
mDataList = new ArrayList<SqlData>();
// 创建新的 SQL 数据列表
}
public SqlNote(Context context, Cursor c) {
// 接受上下文和游标参数的构造函数
mContext = context;
// 将传入的上下文赋值给成员变量
mContentResolver = context.getContentResolver();
// 获取上下文的内容解析器并赋值给成员变量
mIsCreate = false;
// 设置为非创建状态
loadFromCursor(c);
// 从游标加载数据
mDataList = new ArrayList<SqlData>();
// 创建新的 SQL 数据列表
if (mType == Notes.TYPE_NOTE)
loadDataContent();
// 如果类型为笔记类型,加载数据内容
mDiffNoteValues = new ContentValues();
// 创建新的内容值对象并赋值给差异笔记值变量
}
public SqlNote(Context context, long id) {
// 接受上下文和 ID 参数的构造函数
mContext = context;
// 将传入的上下文赋值给成员变量
mContentResolver = context.getContentResolver();
// 获取上下文的内容解析器并赋值给成员变量
mIsCreate = false;
// 设置为非创建状态
loadFromCursor(id);
// 从 ID 加载数据
mDataList = new ArrayList<SqlData>();
// 创建新的 SQL 数据列表
if (mType == Notes.TYPE_NOTE)
loadDataContent();
// 如果类型为笔记类型,加载数据内容
mDiffNoteValues = new ContentValues();
// 创建新的内容值对象并赋值给差异笔记值变量
}
private void loadFromCursor(long id) {
// 从 ID 加载游标数据的私有方法
Cursor c = null;
// 初始化游标为 null
try {
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, PROJECTION_NOTE, "(_id=?)",
new String[]{
String.valueOf(id)
}, null);
// 查询内容解析器,获取指定 ID 的笔记数据游标
if (c!= null) {
c.moveToNext();
loadFromCursor(c);
// 如果游标不为 null移动到下一行并从游标加载数据
} else {
Log.w(TAG, "loadFromCursor: cursor = null");
// 如果游标为 null记录日志警告
}
} finally {
if (c!= null)
c.close();
// 最终,如果游标不为 null关闭游标
}
}
private void loadFromCursor(Cursor c) {
// 从游标加载数据的私有方法
mId = c.getLong(ID_COLUMN);
// 获取游标中 ID 列的值并赋值给成员变量
mAlertDate = c.getLong(ALERTED_DATE_COLUMN);
// 获取游标中提醒日期列的值并赋值给成员变量
mBgColorId = c.getInt(BG_COLOR_ID_COLUMN);
// 获取游标中背景颜色 ID 列的值并赋值给成员变量
mCreatedDate = c.getLong(CREATED_DATE_COLUMN);
// 获取游标中创建日期列的值并赋值给成员变量
mHasAttachment = c.getInt(HAS_ATTACHMENT_COLUMN);
// 获取游标中是否有附件列的值并赋值给成员变量
mModifiedDate = c.getLong(MODIFIED_DATE_COLUMN);
// 获取游标中修改日期列的值并赋值给成员变量
mParentId = c.getLong(PARENT_ID_COLUMN);
// 获取游标中父 ID 列的值并赋值给成员变量
mSnippet = c.getString(SNIPPET_COLUMN);
// 获取游标中摘要列的值并赋值给成员变量
mType = c.getInt(TYPE_COLUMN);
// 获取游标中类型列的值并赋值给成员变量
mWidgetId = c.getInt(WIDGET_ID_COLUMN);
// 获取游标中小部件 ID 列的值并赋值给成员变量
mWidgetType = c.getInt(WIDGET_TYPE_COLUMN);
// 获取游标中小部件类型列的值并赋值给成员变量
mVersion = c.getLong(VERSION_COLUMN);
// 获取游标中版本列的值并赋值给成员变量
}
private void loadDataContent() {
// 加载数据内容的私有方法
Cursor c = null;
// 初始化游标为 null
mDataList.clear();
// 清空数据列表
try {
c = mContentResolver.query(Notes.CONTENT_DATA_URI, SqlData.PROJECTION_DATA,
"(note_id=?)", new String[]{
String.valueOf(mId)
}, null);
// 查询内容解析器,获取指定笔记 ID 的数据游标
if (c!= null) {
if (c.getCount() == 0) {
Log.w(TAG, "it seems that the note has not data");
// 如果游标计数为 0记录日志警告
return;
}
while (c.moveToNext()) {
SqlData data = new SqlData(mContext, c);
mDataList.add(data);
// 如果游标不为 null遍历游标并创建 SQL 数据对象添加到数据列表
}
} else {
Log.w(TAG, "loadDataContent: cursor = null");
// 如果游标为 null记录日志警告
}
} finally {
if (c!= null)
c.close();
// 最终,如果游标不为 null关闭游标
}
}
public boolean setContent(JSONObject js) {
// 设置内容的方法,接受 JSON 对象参数,返回布尔值
try {
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
// 从传入的 JSON 对象中获取名为 GTaskStringUtils.META_HEAD_NOTE 的 JSON 对象
if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) {
Log.w(TAG, "cannot set system folder");
// 如果类型为系统文件夹类型,记录日志警告并返回 false
return false;
} else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) {
// 如果类型为文件夹类型
// for folder we can only update the snnipet and type
String snippet = note.has(NoteColumns.SNIPPET)? note
.getString(NoteColumns.SNIPPET) : "";
// 获取摘要,如果存在则获取,否则为空字符串
if (mIsCreate ||!mSnippet.equals(snippet)) {
mDiffNoteValues.put(NoteColumns.SNIPPET, snippet);
}
// 如果为创建状态或摘要与当前不同,将摘要添加到差异笔记值中
mSnippet = snippet;
// 更新摘要变量
int type = note.has(NoteColumns.TYPE)? note.getInt(NoteColumns.TYPE)
: Notes.TYPE_NOTE;
// 获取类型,如果存在则获取,否则为笔记类型
if (mIsCreate || mType!= type) {
mDiffNoteValues.put(NoteColumns.TYPE, type);
}
// 如果为创建状态或类型与当前不同,将类型添加到差异笔记值中
mType = type;
// 更新类型变量
} else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_NOTE) {
// 如果类型为笔记类型
JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
// 获取数据数组
long id = note.has(NoteColumns.ID)? note.getLong(NoteColumns.ID) : INVALID_ID;
// 获取 ID如果存在则获取否则为无效值
if (mIsCreate || mId!= id) {
mDiffNoteValues.put(NoteColumns.ID, id);
}
// 如果为创建状态或 ID 与当前不同,将 ID 添加到差异笔记值中
mId = id;
// 更新 ID 变量
long alertDate = note.has(NoteColumns.ALERTED_DATE)? note
.getLong(NoteColumns.ALERTED_DATE) : 0;
// 获取提醒日期,如果存在则获取,否则为 0
if (mIsCreate || mAlertDate!= alertDate) {
mDiffNoteValues.put(NoteColumns.ALERTED_DATE, alertDate);
}
// 如果为创建状态或提醒日期与当前不同,将提醒日期添加到差异笔记值中
mAlertDate = alertDate;
// 更新提醒日期变量
int bgColorId = note.has(NoteColumns.BG_COLOR_ID)? note
.getInt(NoteColumns.BG_COLOR_ID) : ResourceParser.getDefaultBgId(mContext);
// 获取背景颜色 ID如果存在则获取否则为默认背景颜色 ID
if (mIsCreate || mBgColorId!= bgColorId) {
mDiffNoteValues.put(NoteColumns.BG_COLOR_ID, bgColorId);
}
// 如果为创建状态或背景颜色 ID 与当前不同,将背景颜色 ID 添加到差异笔记值中
mBgColorId = bgColorId;
// 更新背景颜色 ID 变量
long createDate = note.has(NoteColumns.CREATED_DATE)? note
.getLong(NoteColumns.CREATED_DATE) : System.currentTimeMillis();
// 获取创建日期,如果存在则获取,否则为当前时间戳
if (mIsCreate || mCreatedDate!= createDate) {
mDiffNoteValues.put(NoteColumns.CREATED_DATE, createDate);
}
// 如果为创建状态或创建日期与当前不同,将创建日期添加到差异笔记值中
mCreatedDate = createDate;
// 更新创建日期变量
int hasAttachment = note.has(NoteColumns.HAS_ATTACHMENT)? note
.getInt(NoteColumns.HAS_ATTACHMENT) : 0;
// 判断 JSON 对象 note 中是否存在 HAS_ATTACHMENT 字段,如果有则获取其整数值,否则将 hasAttachment 初始化为 0。
if (mIsCreate || mHasAttachment!= hasAttachment) {
mDiffNoteValues.put(NoteColumns.HAS_ATTACHMENT, hasAttachment);
}
// 如果当前处于创建状态或者当前的 hasAttachment 值与新获取的值不同,则将新的 hasAttachment 值放入差异笔记值的 HAS_ATTACHMENT 字段中。
mHasAttachment = hasAttachment;
// 更新当前对象的 hasAttachment 变量。
long modifiedDate = note.has(NoteColumns.MODIFIED_DATE)? note
.getLong(NoteColumns.MODIFIED_DATE) : System.currentTimeMillis();
// 判断 JSON 对象 note 中是否存在 MODIFIED_DATE 字段,如果有则获取其长整数值,否则将 modifiedDate 初始化为当前时间戳。
if (mIsCreate || mModifiedDate!= modifiedDate) {
mDiffNoteValues.put(NoteColumns.MODIFIED_DATE, modifiedDate);
}
// 如果当前处于创建状态或者当前的 modifiedDate 值与新获取的值不同,则将新的 modifiedDate 值放入差异笔记值的 MODIFIED_DATE 字段中。
mModifiedDate = modifiedDate;
// 更新当前对象的 modifiedDate 变量。
long parentId = note.has(NoteColumns.PARENT_ID)? note
.getLong(NoteColumns.PARENT_ID) : 0;
// 判断 JSON 对象 note 中是否存在 PARENT_ID 字段,如果有则获取其长整数值,否则将 parentId 初始化为 0。
if (mIsCreate || mParentId!= parentId) {
mDiffNoteValues.put(NoteColumns.PARENT_ID, parentId);
}
// 如果当前处于创建状态或者当前的 parentId 值与新获取的值不同,则将新的 parentId 值放入差异笔记值的 PARENT_ID 字段中。
mParentId = parentId;
// 更新当前对象的 parentId 变量。
String snippet = note.has(NoteColumns.SNIPPET)? note
.getString(NoteColumns.SNIPPET) : "";
// 判断 JSON 对象 note 中是否存在 SNIPPET 字段,如果有则获取其字符串值,否则将 snippet 初始化为空字符串。
if (mIsCreate ||!mSnippet.equals(snippet)) {
mDiffNoteValues.put(NoteColumns.SNIPPET, snippet);
}
// 如果当前处于创建状态或者当前的 snippet 值与新获取的值不同,则将新的 snippet 值放入差异笔记值的 SNIPPET 字段中。
mSnippet = snippet;
// 更新当前对象的 snippet 变量。
int type = note.has(NoteColumns.TYPE)? note.getInt(NoteColumns.TYPE)
: Notes.TYPE_NOTE;
// 判断 JSON 对象 note 中是否存在 TYPE 字段,如果有则获取其整数值,否则将 type 初始化为笔记类型。
if (mIsCreate || mType!= type) {
mDiffNoteValues.put(NoteColumns.TYPE, type);
}
// 如果当前处于创建状态或者当前的 type 值与新获取的值不同,则将新的 type 值放入差异笔记值的 TYPE 字段中。
mType = type;
// 更新当前对象的 type 变量。
int widgetId = note.has(NoteColumns.WIDGET_ID)? note.getInt(NoteColumns.WIDGET_ID)
: AppWidgetManager.INVALID_APPWIDGET_ID;
// 判断 JSON 对象 note 中是否存在 WIDGET_ID 字段,如果有则获取其整数值,否则将 widgetId 初始化为无效小部件 ID。
if (mIsCreate || mWidgetId!= widgetId) {
mDiffNoteValues.put(NoteColumns.WIDGET_ID, widgetId);
}
// 如果当前处于创建状态或者当前的 widgetId 值与新获取的值不同,则将新的 widgetId 值放入差异笔记值的 WIDGET_ID 字段中。
mWidgetId = widgetId;
// 更新当前对象的 widgetId 变量。
int widgetType = note.has(NoteColumns.WIDGET_TYPE)? note
.getInt(NoteColumns.WIDGET_TYPE) : Notes.TYPE_WIDGET_INVALIDE;
// 判断 JSON 对象 note 中是否存在 WIDGET_TYPE 字段,如果有则获取其整数值,否则将 widgetType 初始化为无效小部件类型。
if (mIsCreate || mWidgetType!= widgetType) {
mDiffNoteValues.put(NoteColumns.WIDGET_TYPE, widgetType);
}
// 如果当前处于创建状态或者当前的 widgetType 值与新获取的值不同,则将新的 widgetType 值放入差异笔记值的 WIDGET_TYPE 字段中。
mWidgetType = widgetType;
// 更新当前对象的 widgetType 变量。
long originParent = note.has(NoteColumns.ORIGIN_PARENT_ID)? note
.getLong(NoteColumns.ORIGIN_PARENT_ID) : 0;
// 判断 JSON 对象 note 中是否存在 ORIGIN_PARENT_ID 字段,如果有则获取其长整数值,否则将 originParent 初始化为 0。
if (mIsCreate || mOriginParent!= originParent) {
mDiffNoteValues.put(NoteColumns.ORIGIN_PARENT_ID, originParent);
}
// 如果当前处于创建状态或者当前的 originParent 值与新获取的值不同,则将新的 originParent 值放入差异笔记值的 ORIGIN_PARENT_ID 字段中。
mOriginParent = originParent;
// 更新当前对象的 originParent 变量。
for (int i = 0; i < dataArray.length(); i++) {
JSONObject data = dataArray.getJSONObject(i);
// 从 JSON 数组 dataArray 中获取第 i 个元素,即一个 JSON 对象,并赋值给 data。
SqlData sqlData = null;
// 初始化一个 SqlData 对象为 null。
if (data.has(DataColumns.ID)) {
long dataId = data.getLong(DataColumns.ID);
// 如果 data 中包含 ID 字段,则获取其长整数值并赋值给 dataId。
for (SqlData temp : mDataList) {
if (dataId == temp.getId()) {
sqlData = temp;
}
}
// 在当前对象的 mDataList 中遍历每个 SqlData 对象 temp如果 dataId 与 temp 的 ID 相等,则将 temp 赋值给 sqlData。
}
if (sqlData == null) {
sqlData = new SqlData(mContext);
mDataList.add(sqlData);
}
// 如果 sqlData 为 null即没有找到匹配的 SqlData 对象,则创建一个新的 SqlData 对象并添加到 mDataList 中。
sqlData.setContent(data);
// 调用 sqlData 的 setContent 方法,将当前的 data 对象作为参数传入。
}
java
public JSONObject getContent() {
try {
JSONObject js = new JSONObject();
// 创建一个新的 JSON 对象 js。
if (mIsCreate) {
Log.e(TAG, "it seems that we haven't created this in database yet");
return null;
}
// 如果当前处于创建状态,则记录日志并返回 null。
JSONObject note = new JSONObject();
// 创建一个新的 JSON 对象 note。
if (mType == Notes.TYPE_NOTE) {
note.put(NoteColumns.ID, mId);
note.put(NoteColumns.ALERTED_DATE, mAlertDate);
note.put(NoteColumns.BG_COLOR_ID, mBgColorId);
note.put(NoteColumns.CREATED_DATE, mCreatedDate);
note.put(NoteColumns.HAS_ATTACHMENT, mHasAttachment);
note.put(NoteColumns.MODIFIED_DATE, mModifiedDate);
note.put(NoteColumns.PARENT_ID, mParentId);
note.put(NoteColumns.SNIPPET, mSnippet);
note.put(NoteColumns.TYPE, mType);
note.put(NoteColumns.WIDGET_ID, mWidgetId);
note.put(NoteColumns.WIDGET_TYPE, mWidgetType);
note.put(NoteColumns.ORIGIN_PARENT_ID, mOriginParent);
js.put(GTaskStringUtils.META_HEAD_NOTE, note);
// 如果当前对象的类型是笔记类型,则将各种属性放入 note 中,并将 note 放入 js 的特定键下。
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);
// 创建一个新的 JSON 数组 dataArray遍历数据列表获取每个 SqlData 的内容放入 JSON 数组中,再将 dataArray 放入 js 的特定键下。
} else if (mType == Notes.TYPE_FOLDER || mType == Notes.TYPE_SYSTEM) {
note.put(NoteColumns.ID, mId);
note.put(NoteColumns.TYPE, mType);
note.put(NoteColumns.SNIPPET, mSnippet);
js.put(GTaskStringUtils.META_HEAD_NOTE, note);
}
// 如果当前对象的类型是文件夹类型或系统类型,则只将 ID、类型和摘要放入 note 中,再将 note 放入 js 的特定键下。
return js;
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
}
return null;
}
java
public void setParentId(long id) {
mParentId = id;
// 更新当前对象的父 ID 变量。
mDiffNoteValues.put(NoteColumns.PARENT_ID, id);
// 将新的父 ID 放入差异笔记值的 PARENT_ID 字段中。
}
public void setGtaskId(String gid) {
mDiffNoteValues.put(NoteColumns.GTASK_ID, gid);
// 将新的 GTask ID 放入差异笔记值的 GTASK_ID 字段中。
}
public void setSyncId(long syncId) {
mDiffNoteValues.put(NoteColumns.SYNC_ID, syncId);
// 将新的同步 ID 放入差异笔记值的 SYNC_ID 字段中。
}
public void resetLocalModified() {
mDiffNoteValues.put(NoteColumns.LOCAL_MODIFIED, 0);
// 将本地修改状态设置为 0并放入差异笔记值的 LOCAL_MODIFIED 字段中。
}
public long getId() {
return mId;
// 返回当前对象的 ID。
}
public long getParentId() {
return mParentId;
// 返回当前对象的父 ID。
}
public String getSnippet() {
return mSnippet;
// 返回当前对象的摘要。
}
public boolean isNoteType() {
return mType == Notes.TYPE_NOTE;
// 判断是否是笔记类型的方法。如果当前对象的类型等于笔记类型,则返回 true否则返回 false。
}
public void commit(boolean validateVersion) {
if (mIsCreate) {
if (mId == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) {
mDiffNoteValues.remove(NoteColumns.ID);
}
// 如果当前处于创建状态且 ID 为无效值且差异笔记值中包含 ID 字段,则移除该 ID 字段。
Uri uri = mContentResolver.insert(Notes.CONTENT_NOTE_URI, mDiffNoteValues);
try {
mId = Long.valueOf(uri.getPathSegments().get(1));
} catch (NumberFormatException e) {
Log.e(TAG, "Get note id error :" + e.toString());
throw new ActionFailureException("create note failed");
}
// 插入新的笔记数据到内容解析器中,并获取新插入的笔记 ID。如果插入失败则抛出异常。
if (mId == 0) {
throw new IllegalStateException("Create thread id failed");
}
// 如果当前 ID 为 0则抛出非法状态异常。
if (mType == Notes.TYPE_NOTE) {
for (SqlData sqlData : mDataList) {
sqlData.commit(mId, false, -1);
}
}
// 如果类型是笔记类型,则对数据列表中的每个 SqlData 对象调用提交方法。
} else {
if (mId <= 0 && mId!= Notes.ID_ROOT_FOLDER && mId!= Notes.ID_CALL_RECORD_FOLDER) {
Log.e(TAG, "No such note");
throw new IllegalStateException("Try to update note with invalid id");
}
// 如果不是创建状态且 ID 无效(不等于根文件夹 ID 和通话记录文件夹 ID则抛出异常。
if (mDiffNoteValues.size() > 0) {
mVersion++;
int result = 0;
if (!validateVersion) {
result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "("
+ NoteColumns.ID + "=?)", new String[]{
String.valueOf(mId)
});
} else {
result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "("
+ NoteColumns.ID + "=?) AND (" + NoteColumns.VERSION + "<=?)",
new String[]{
String.valueOf(mId), String.valueOf(mVersion)
});
}
if (result == 0) {
Log.w(TAG, "there is no update. maybe user updates note when syncing");
}
}
// 如果差异笔记值不为空,则更新版本号,并根据 validateVersion 的值选择不同的更新方式。如果更新结果为 0则记录日志警告。
if (mType == Notes.TYPE_NOTE) {
for (SqlData sqlData : mDataList) {
sqlData.commit(mId, validateVersion, mVersion);
}
}
// 如果类型是笔记类型,则对数据列表中的每个 SqlData 对象调用提交方法。
}
// refresh local info
loadFromCursor(mId);
if (mType == Notes.TYPE_NOTE)
loadDataContent();
// 刷新本地信息,根据 ID 重新加载当前对象的数据,如果类型是笔记类型,则加载数据内容。
mDiffNoteValues.clear();
mIsCreate = false;
// 清空差异笔记值,并设置为非创建状态。
}
Loading…
Cancel
Save