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-Notes/SqlData.java

258 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)
*
* 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;:定义当前类所属的包。
//导入了与内容提供者交互的 ContentResolver、ContentUris、ContentValues、Cursor 等 Android 类,
// 还包括 JSON 处理类 JSONObject以及自定义异常类 ActionFailureException。
package net.micode.notes.gtask.data;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.DataConstants;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.NotesDatabaseHelper.TABLE;
import net.micode.notes.gtask.exception.ActionFailureException;
import org.json.JSONException;
import org.json.JSONObject;
//字段解释:
//TAG日志标识通常用于调试时输出日志。
//INVALID_ID一个无效的 ID 值,通常用于初始化时表示数据未找到或未设置。
//PROJECTION_DATA定义了查询时返回的列数据表的列与常量 DataColumns 中定义的列名相对应。
//mContentResolverContentResolver 是用来访问 Android 内容提供者的工具。
//mIsCreate布尔值表示当前 SqlData 对象是新创建的true还是从数据库中加载的false
//mDataId、mDataMimeType、mDataContent、mDataContentData1 和 mDataContentData3 用来存储与特定数据项相关的字段。
//mDiffDataValues用于存储不同数据项的差异通常在插入或更新数据库时使用。
public class SqlData {
private static final String TAG = SqlData.class.getSimpleName(); // 日志标识,用于调试和打印日志
private static final int INVALID_ID = -99999; // 无效的ID常量用于初始化时标记无效ID
// 定义用于查询数据表的投影列PROJECTION即查询结果中返回的列
public static final String[] PROJECTION_DATA = new String[]{
DataColumns.ID, DataColumns.MIME_TYPE, DataColumns.CONTENT, DataColumns.DATA1,
DataColumns.DATA3
};
// 定义数据表中各列的索引值通过索引访问Cursor中的数据
public static final int DATA_ID_COLUMN = 0;
public static final int DATA_MIME_TYPE_COLUMN = 1;
public static final int DATA_CONTENT_COLUMN = 2;
public static final int DATA_CONTENT_DATA_1_COLUMN = 3;
public static final int DATA_CONTENT_DATA_3_COLUMN = 4;
private ContentResolver mContentResolver; // ContentResolver用于访问和操作内容提供者中的数据
private boolean mIsCreate; // 标记当前对象是否是新创建的
// 存储数据的ID
private long mDataId;
// 存储数据的MIME类型
private String mDataMimeType;
// 存储数据的内容
private String mDataContent;
// 存储数据的附加信息
private long mDataContentData1;
// 存储数据的附加信息
private String mDataContentData3;
// 存储不同的数据值,用于更新或插入时的差异
private ContentValues mDiffDataValues;
//构造函数:
//第一个构造函数用于创建一个新的 SqlData 实例,初始化一些默认值。
//第二个构造函数接收一个 Cursor 对象,表示从数据库查询到的数据行。它将通过 loadFromCursor 方法加载 Cursor 中的数据。
// 默认构造函数,用于创建一个新的 SqlData 实例
public SqlData(Context context) {
// 获取 Context 中的 ContentResolver
mContentResolver = context.getContentResolver();
// 标记这是一个新创建的实例
mIsCreate = true;
// 初始化 ID 为无效 ID
mDataId = INVALID_ID;
// 设置默认的 MIME 类型
mDataMimeType = DataConstants.NOTE;
// 初始化内容为空字符串
mDataContent = "";
// 初始化附加数据 1 为 0
mDataContentData1 = 0;
// 初始化附加数据 3 为空字符串
mDataContentData3 = "";
// 初始化差异数据的 ContentValues 对象
mDiffDataValues = new ContentValues();
}
// 构造函数,用于从 Cursor 中加载数据
public SqlData(Context context, Cursor c) {
// 获取 Context 中的 ContentResolver
mContentResolver = context.getContentResolver();
// 标记这个实例是从 Cursor 中加载数据而来的
mIsCreate = false;
// 从 Cursor 中加载数据到对象的成员变量
loadFromCursor(c);
// 初始化差异数据的 ContentValues 对象
mDiffDataValues = new ContentValues();
}
// 从 Cursor 中加载数据,填充到当前 SqlData 对象的成员变量中
//loadFromCursor 方法:
//这个方法从数据库查询结果 Cursor 中获取数据,并填充到当前 SqlData 对象的成员变量中。
//Cursor 是 Android 数据库查询结果的一个游标getLong() 和 getString() 方法用于从 Cursor 中提取具体的列值,按照列的索引顺序获取。
private void loadFromCursor(Cursor c) {
// 获取数据 ID
mDataId = c.getLong(DATA_ID_COLUMN);
// 获取数据的 MIME 类型
mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN);
// 获取数据内容
mDataContent = c.getString(DATA_CONTENT_COLUMN);
// 获取数据的附加信息 1
mDataContentData1 = c.getLong(DATA_CONTENT_DATA_1_COLUMN);
// 获取数据的附加信息 3
mDataContentData3 = c.getString(DATA_CONTENT_DATA_3_COLUMN); // 获取数据的附加信息 3
}
// 设置内容的方法将传入的JSON对象中的数据提取并更新类的成员变量
public void setContent(JSONObject js) throws JSONException {
// 获取ID如果JSON中不存在则使用INVALID_ID
long dataId = js.has(DataColumns.ID) ? js.getLong(DataColumns.ID) : INVALID_ID;
// 如果是新创建或者ID发生变化则更新差异数据
if (mIsCreate || mDataId != dataId) {
mDiffDataValues.put(DataColumns.ID, dataId);
}
mDataId = dataId;
// 获取MIME类型如果JSON中没有则使用默认值"NOTE"
String dataMimeType = js.has(DataColumns.MIME_TYPE) ? js.getString(DataColumns.MIME_TYPE)
: DataConstants.NOTE;
// 如果是新创建或MIME类型不同则更新差异数据
if (mIsCreate || !mDataMimeType.equals(dataMimeType)) {
mDiffDataValues.put(DataColumns.MIME_TYPE, dataMimeType);
}
mDataMimeType = dataMimeType;
// 获取内容数据如果JSON中没有则使用空字符串
String dataContent = js.has(DataColumns.CONTENT) ? js.getString(DataColumns.CONTENT) : "";
// 如果是新创建或内容不同,则更新差异数据
if (mIsCreate || !mDataContent.equals(dataContent)) {
mDiffDataValues.put(DataColumns.CONTENT, dataContent);
}
mDataContent = dataContent;
// 获取DATA1字段的数值如果JSON中没有则默认为0
long dataContentData1 = js.has(DataColumns.DATA1) ? js.getLong(DataColumns.DATA1) : 0;
// 如果是新创建或DATA1不同则更新差异数据
if (mIsCreate || mDataContentData1 != dataContentData1) {
mDiffDataValues.put(DataColumns.DATA1, dataContentData1);
}
mDataContentData1 = dataContentData1;
// 获取DATA3字段的内容如果JSON中没有则使用空字符串
String dataContentData3 = js.has(DataColumns.DATA3) ? js.getString(DataColumns.DATA3) : "";
// 如果是新创建或DATA3不同则更新差异数据
if (mIsCreate || !mDataContentData3.equals(dataContentData3)) {
mDiffDataValues.put(DataColumns.DATA3, dataContentData3);
}
mDataContentData3 = dataContentData3;
}
// 获取内容的方法返回一个JSONObject包含当前对象的各个字段
public JSONObject getContent() throws JSONException {
// 如果是新创建抛出错误日志并返回null
if (mIsCreate) {
Log.e(TAG, "it seems that we haven't created this in database yet");
return null;
}
// 创建新的JSONObject并填充数据
JSONObject js = new JSONObject();
js.put(DataColumns.ID, mDataId);
js.put(DataColumns.MIME_TYPE, mDataMimeType);
js.put(DataColumns.CONTENT, mDataContent);
js.put(DataColumns.DATA1, mDataContentData1);
js.put(DataColumns.DATA3, mDataContentData3);
return js;
}
// 提交数据到数据库,如果是新创建则插入,否则更新现有记录
public void commit(long noteId, boolean validateVersion, long version) {
// 如果是新创建,插入数据
if (mIsCreate) {
// 如果ID无效且有差异数据移除ID
if (mDataId == INVALID_ID && mDiffDataValues.containsKey(DataColumns.ID)) {
mDiffDataValues.remove(DataColumns.ID);
}
// 添加noteId并执行插入操作
mDiffDataValues.put(DataColumns.NOTE_ID, noteId);
Uri uri = mContentResolver.insert(Notes.CONTENT_DATA_URI, mDiffDataValues);
try {
// 获取新插入的ID
mDataId = Long.valueOf(uri.getPathSegments().get(1));
} catch (NumberFormatException e) {
Log.e(TAG, "Get note id error :" + e.toString());
throw new ActionFailureException("create note failed");
}
} else {
// 如果有差异数据,则执行更新操作
if (mDiffDataValues.size() > 0) {
int result = 0;
// 如果不验证版本,则直接更新
if (!validateVersion) {
result = mContentResolver.update(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, null, null);
} else {
// 如果验证版本,执行带版本检查的更新
result = mContentResolver.update(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues,
" ? in (SELECT " + NoteColumns.ID + " FROM " + TABLE.NOTE
+ " WHERE " + NoteColumns.VERSION + "=?)", new String[]{
String.valueOf(noteId), String.valueOf(version)
});
}
// 如果没有更新,打印警告
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;
}
}