You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
xiaomi/SqlData.java

257 lines
12 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* Copyright (c) 2010 - 2011, The MiCode Open Source Community (www.micode.net)
*
* 遵循 Apache 许可证 2.0 版(“许可证”);
* 除非遵守许可证,否则不得使用此文件。
* 你可以在以下网址获取许可证副本:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 除非适用法律要求或书面同意,
* 根据许可证分发的软件按“原样”分发,
* 不附带任何明示或暗示的保证或条件。
* 请参阅许可证,了解具体的权限和限制。
*/
package net.micode.notes.gtask.data;
import android.content.ContentResolver; // 用于与 ContentProvider 进行交互的类
import android.content.ContentUris; // 用于操作包含 ID 的 Uri 的工具类
import android.content.ContentValues; // 用于存储一组键值对,通常用于插入或更新数据库记录
import android.content.Context; // 提供对应用程序环境的全局信息访问
import android.database.Cursor; // 用于遍历查询结果集的类
import android.net.Uri; // 用于表示统一资源标识符
import android.util.Log; // 用于记录日志信息的类
import net.micode.notes.data.Notes; // 导入与笔记相关的类
import net.micode.notes.data.Notes.DataColumns; // 导入数据列相关的接口
import net.micode.notes.data.Notes.DataConstants; // 导入数据常量相关的类
import net.micode.notes.data.Notes.NoteColumns; // 导入笔记列相关的接口
import net.micode.notes.data.NotesDatabaseHelper.TABLE; // 导入数据库表名相关的接口
import net.micode.notes.gtask.exception.ActionFailureException; // 导入自定义的异常类
import org.json.JSONException; // 用于处理 JSON 异常的类
import org.json.JSONObject; // 用于处理 JSON 对象的类
// SqlData 类用于处理与 SQLite 数据库中数据相关的操作
public class SqlData {
// 用于日志记录的标签,使用类的简单名称
private static final String TAG = SqlData.class.getSimpleName();
// 定义无效的 ID 值
private static final int INVALID_ID = -99999;
// 定义查询数据时使用的投影列
public static final String[] PROJECTION_DATA = new String[] {
DataColumns.ID, // 数据的唯一标识
DataColumns.MIME_TYPE, // 数据的 MIME 类型
DataColumns.CONTENT, // 数据的内容
DataColumns.DATA1, // 通用数据列 1
DataColumns.DATA3 // 通用数据列 3
};
// 定义投影列中数据 ID 所在的索引
public static final int DATA_ID_COLUMN = 0;
// 定义投影列中数据 MIME 类型所在的索引
public static final int DATA_MIME_TYPE_COLUMN = 1;
// 定义投影列中数据内容所在的索引
public static final int DATA_CONTENT_COLUMN = 2;
// 定义投影列中数据通用列 1 所在的索引
public static final int DATA_CONTENT_DATA_1_COLUMN = 3;
// 定义投影列中数据通用列 3 所在的索引
public static final int DATA_CONTENT_DATA_3_COLUMN = 4;
// 用于与 ContentProvider 进行交互的 ContentResolver 对象
private ContentResolver mContentResolver;
// 表示是否为创建操作的标志
private boolean mIsCreate;
// 数据的 ID
private long mDataId;
// 数据的 MIME 类型
private String mDataMimeType;
// 数据的内容
private String mDataContent;
// 数据通用列 1 的值
private long mDataContentData1;
// 数据通用列 3 的值
private String mDataContentData3;
// 用于存储数据差异的 ContentValues 对象
private ContentValues mDiffDataValues;
// 构造函数,用于创建一个新的 SqlData 对象,通常用于创建新的数据记录
public SqlData(Context context) {
// 获取应用程序的 ContentResolver
mContentResolver = context.getContentResolver();
// 标记为创建操作
mIsCreate = true;
// 初始化数据 ID 为无效值
mDataId = INVALID_ID;
// 设置默认的 MIME 类型
mDataMimeType = DataConstants.NOTE;
// 设置默认的数据内容
mDataContent = "";
// 设置默认的数据通用列 1 的值
mDataContentData1 = 0;
// 设置默认的数据通用列 3 的值
mDataContentData3 = "";
// 初始化用于存储数据差异的 ContentValues 对象
mDiffDataValues = new ContentValues();
}
// 构造函数,用于从 Cursor 中加载数据,通常用于从数据库中读取已有的数据记录
public SqlData(Context context, Cursor c) {
// 获取应用程序的 ContentResolver
mContentResolver = context.getContentResolver();
// 标记为非创建操作
mIsCreate = false;
// 从 Cursor 中加载数据
loadFromCursor(c);
// 初始化用于存储数据差异的 ContentValues 对象
mDiffDataValues = new ContentValues();
}
// 从 Cursor 中加载数据的私有方法
private void loadFromCursor(Cursor c) {
// 从 Cursor 中获取数据的 ID
mDataId = c.getLong(DATA_ID_COLUMN);
// 从 Cursor 中获取数据的 MIME 类型
mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN);
// 从 Cursor 中获取数据的内容
mDataContent = c.getString(DATA_CONTENT_COLUMN);
// 从 Cursor 中获取数据通用列 1 的值
mDataContentData1 = c.getLong(DATA_CONTENT_DATA_1_COLUMN);
// 从 Cursor 中获取数据通用列 3 的值
mDataContentData3 = c.getString(DATA_CONTENT_DATA_3_COLUMN);
}
// 根据 JSON 对象设置数据内容的方法
public void setContent(JSONObject js) throws JSONException {
// 从 JSON 对象中获取数据 ID如果不存在则使用无效 ID
long dataId = js.has(DataColumns.ID)? js.getLong(DataColumns.ID) : INVALID_ID;
// 如果是创建操作或者当前数据 ID 与 JSON 中的数据 ID 不一致
if (mIsCreate || mDataId!= dataId) {
// 将数据 ID 放入差异值中
mDiffDataValues.put(DataColumns.ID, dataId);
}
// 更新当前数据 ID
mDataId = dataId;
// 从 JSON 对象中获取数据 MIME 类型,如果不存在则使用默认值
String dataMimeType = js.has(DataColumns.MIME_TYPE)? js.getString(DataColumns.MIME_TYPE)
: DataConstants.NOTE;
// 如果是创建操作或者当前 MIME 类型与 JSON 中的 MIME 类型不一致
if (mIsCreate ||!mDataMimeType.equals(dataMimeType)) {
// 将数据 MIME 类型放入差异值中
mDiffDataValues.put(DataColumns.MIME_TYPE, dataMimeType);
}
// 更新当前数据 MIME 类型
mDataMimeType = dataMimeType;
// 从 JSON 对象中获取数据内容,如果不存在则使用空字符串
String dataContent = js.has(DataColumns.CONTENT)? js.getString(DataColumns.CONTENT) : "";
// 如果是创建操作或者当前数据内容与 JSON 中的数据内容不一致
if (mIsCreate ||!mDataContent.equals(dataContent)) {
// 将数据内容放入差异值中
mDiffDataValues.put(DataColumns.CONTENT, dataContent);
}
// 更新当前数据内容
mDataContent = dataContent;
// 从 JSON 对象中获取数据通用列 1 的值,如果不存在则使用 0
long dataContentData1 = js.has(DataColumns.DATA1)? js.getLong(DataColumns.DATA1) : 0;
// 如果是创建操作或者当前数据通用列 1 的值与 JSON 中的值不一致
if (mIsCreate || mDataContentData1!= dataContentData1) {
// 将数据通用列 1 的值放入差异值中
mDiffDataValues.put(DataColumns.DATA1, dataContentData1);
}
// 更新当前数据通用列 1 的值
mDataContentData1 = dataContentData1;
// 从 JSON 对象中获取数据通用列 3 的值,如果不存在则使用空字符串
String dataContentData3 = js.has(DataColumns.DATA3)? js.getString(DataColumns.DATA3) : "";
// 如果是创建操作或者当前数据通用列 3 的值与 JSON 中的值不一致
if (mIsCreate ||!mDataContentData3.equals(dataContentData3)) {
// 将数据通用列 3 的值放入差异值中
mDiffDataValues.put(DataColumns.DATA3, dataContentData3);
}
// 更新当前数据通用列 3 的值
mDataContentData3 = dataContentData3;
}
// 获取当前数据内容的 JSON 对象的方法
public JSONObject getContent() throws JSONException {
// 如果是创建操作,说明数据可能还未存入数据库,记录错误日志并返回 null
if (mIsCreate) {
Log.e(TAG, "it seems that we haven't created this in database yet");
return null;
}
// 创建一个新的 JSON 对象
JSONObject js = new JSONObject();
// 将数据 ID 放入 JSON 对象中
js.put(DataColumns.ID, mDataId);
// 将数据 MIME 类型放入 JSON 对象中
js.put(DataColumns.MIME_TYPE, mDataMimeType);
// 将数据内容放入 JSON 对象中
js.put(DataColumns.CONTENT, mDataContent);
// 将数据通用列 1 的值放入 JSON 对象中
js.put(DataColumns.DATA1, mDataContentData1);
// 将数据通用列 3 的值放入 JSON 对象中
js.put(DataColumns.DATA3, mDataContentData3);
// 返回包含数据内容的 JSON 对象
return js;
}
// 提交数据到数据库的方法
public void commit(long noteId, boolean validateVersion, long version) {
// 如果是创建操作
if (mIsCreate) {
// 如果数据 ID 为无效值且差异值中包含数据 ID移除差异值中的数据 ID
if (mDataId == INVALID_ID && mDiffDataValues.containsKey(DataColumns.ID)) {
mDiffDataValues.remove(DataColumns.ID);
}
// 将所属笔记的 ID 放入差异值中
mDiffDataValues.put(DataColumns.NOTE_ID, noteId);
// 向 ContentProvider 插入数据
Uri uri = mContentResolver.insert(Notes.CONTENT_DATA_URI, mDiffDataValues);
try {
// 从插入操作返回的 Uri 中获取数据的 ID
mDataId = Long.valueOf(uri.getPathSegments().get(1));
} catch (NumberFormatException e) {
// 如果获取数据 ID 时发生异常,记录错误日志并抛出异常
Log.e(TAG, "Get note id error :" + e.toString());
throw new ActionFailureException("create note failed");
}
} else {
// 如果差异值中有数据需要更新
if (mDiffDataValues.size() > 0) {
int result = 0;
// 如果不需要验证版本
if (!validateVersion) {
// 更新数据
result = mContentResolver.update(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, null, null);
} else {
// 更新数据,并添加版本验证条件
result = mContentResolver.update(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues,
"? in (SELECT " + NoteColumns.ID + " FROM " + TABLE.NOTE
+ " WHERE " + NoteColumns.VERSION + "=?)", new String[] {
String.valueOf(noteId), String.valueOf(version)
});
}
// 如果更新结果为 0说明可能没有更新记录警告日志
if (result == 0) {
Log.w(TAG, "there is no update. maybe user updates note when syncing");
}
}
}
// 清空差异值
mDiffDataValues.clear();
// 标记为非创建操作
mIsCreate = false;
}
// 获取数据 ID 的方法
public long getId() {
return mDataId;
}
}