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_reading/src/notes/ui/NoteItemData.java

367 lines
14 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.ui;
import android.content.Context;
import android.database.Cursor;
import android.text.TextUtils;
import net.micode.notes.data.Contact;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.tool.DataUtils;
/**
* 笔记列表项的数据封装类。
* 这个类的主要作用是将数据库查询结果Cursor对象中的原始数据
* 封装成一个易于使用的Java对象POJO并添加一些业务逻辑判断。
* 它代表了笔记列表中的一个条目,这个条目可能是一条笔记、一个文件夹或系统文件夹。
*/
public class NoteItemData {
/**
* 数据库查询的列投影Projection定义了要从数据库中查询哪些列。
* 这个数组中的列名顺序很重要,后面的列索引常量要与之对应。
*/
static final String [] PROJECTION = new String [] {
NoteColumns.ID, // 笔记ID
NoteColumns.ALERTED_DATE, // 提醒日期
NoteColumns.BG_COLOR_ID, // 背景颜色ID
NoteColumns.CREATED_DATE, // 创建日期
NoteColumns.HAS_ATTACHMENT, // 是否有附件
NoteColumns.MODIFIED_DATE, // 最后修改日期
NoteColumns.NOTES_COUNT, // 包含的笔记数量(针对文件夹)
NoteColumns.PARENT_ID, // 父文件夹ID
NoteColumns.SNIPPET, // 内容摘要/片段
NoteColumns.TYPE, // 类型(笔记、文件夹、系统文件夹等)
NoteColumns.WIDGET_ID, // 关联的小部件ID
NoteColumns.WIDGET_TYPE, // 小部件类型
};
/**
* 列索引常量对应上面PROJECTION数组中各列的位置。
* 使用常量而不是直接写数字如0,1,2可以提高代码可读性和可维护性。
*/
private static final int ID_COLUMN = 0; // ID列的索引
private static final int ALERTED_DATE_COLUMN = 1; // 提醒日期列的索引
private static final int BG_COLOR_ID_COLUMN = 2; // 背景颜色ID列的索引
private static final int CREATED_DATE_COLUMN = 3; // 创建日期列的索引
private static final int HAS_ATTACHMENT_COLUMN = 4; // 是否有附件列的索引
private static final int MODIFIED_DATE_COLUMN = 5; // 修改日期列的索引
private static final int NOTES_COUNT_COLUMN = 6; // 笔记数量列的索引
private static final int PARENT_ID_COLUMN = 7; // 父文件夹ID列的索引
private static final int SNIPPET_COLUMN = 8; // 内容摘要列的索引
private static final int TYPE_COLUMN = 9; // 类型列的索引
private static final int WIDGET_ID_COLUMN = 10; // 小部件ID列的索引
private static final int WIDGET_TYPE_COLUMN = 11; // 小部件类型列的索引
// 成员变量,对应数据库中的各个字段
private long mId; // 笔记/文件夹的唯一标识ID
private long mAlertDate; // 提醒时间戳(毫秒)
private int mBgColorId; // 背景颜色资源ID
private long mCreatedDate; // 创建时间戳(毫秒)
private boolean mHasAttachment; // 是否有附件true/false
private long mModifiedDate; // 最后修改时间戳(毫秒)
private int mNotesCount; // 文件夹中包含的笔记数量(如果是文件夹的话)
private long mParentId; // 父文件夹的ID
private String mSnippet; // 笔记内容的摘要/片段(用于列表显示)
private int mType; // 类型(笔记、文件夹、系统文件夹等)
private int mWidgetId; // 关联的桌面小部件ID
private int mWidgetType; // 桌面小部件的类型
// 额外添加的业务逻辑相关字段(不直接来自数据库)
private String mName; // 联系人姓名(如果是通话记录笔记)
private String mPhoneNumber; // 电话号码(如果是通话记录笔记)
// 位置状态标志,用于判断当前项在列表中的位置关系
private boolean mIsLastItem; // 是否是列表中的最后一项
private boolean mIsFirstItem; // 是否是列表中的第一项
private boolean mIsOnlyOneItem; // 是否是列表中唯一的一项
private boolean mIsOneNoteFollowingFolder; // 是否是一个紧跟在文件夹后面的笔记
private boolean mIsMultiNotesFollowingFolder; // 是否是多个紧跟在文件夹后面的笔记之一
/**
* 构造函数从数据库游标Cursor中加载数据并初始化对象
* @param context 上下文,用于获取内容解析器等系统服务
* @param cursor 数据库查询结果游标,指向当前要处理的数据行
*/
public NoteItemData(Context context, Cursor cursor) {
// 从游标中按列索引获取数据,并赋值给对应的成员变量
mId = cursor.getLong(ID_COLUMN);
mAlertDate = cursor.getLong(ALERTED_DATE_COLUMN);
mBgColorId = cursor.getInt(BG_COLOR_ID_COLUMN);
mCreatedDate = cursor.getLong(CREATED_DATE_COLUMN);
// 将整数值转换为布尔值大于0表示有附件true否则为false
mHasAttachment = (cursor.getInt(HAS_ATTACHMENT_COLUMN) > 0) ? true : false;
mModifiedDate = cursor.getLong(MODIFIED_DATE_COLUMN);
mNotesCount = cursor.getInt(NOTES_COUNT_COLUMN);
mParentId = cursor.getLong(PARENT_ID_COLUMN);
mSnippet = cursor.getString(SNIPPET_COLUMN);
// 清理摘要文本中的清单标记符号(对勾和方框),让显示更干净
mSnippet = mSnippet.replace(NoteEditActivity.TAG_CHECKED, "").replace(
NoteEditActivity.TAG_UNCHECKED, "");
mType = cursor.getInt(TYPE_COLUMN);
mWidgetId = cursor.getInt(WIDGET_ID_COLUMN);
mWidgetType = cursor.getInt(WIDGET_TYPE_COLUMN);
// 初始化电话号码和姓名为空
mPhoneNumber = "";
// 如果当前项属于"通话记录"文件夹
if (mParentId == Notes.ID_CALL_RECORD_FOLDER) {
// 根据笔记ID查询对应的电话号码
mPhoneNumber = DataUtils.getCallNumberByNoteId(context.getContentResolver(), mId);
if (!TextUtils.isEmpty(mPhoneNumber)) {
// 如果电话号码不为空,通过联系人提供者查询对应的联系人姓名
mName = Contact.getContact(context, mPhoneNumber);
if (mName == null) {
// 如果查询不到联系人,则用电话号码本身作为显示名称
mName = mPhoneNumber;
}
}
}
// 确保姓名不为null避免后续使用时报错
if (mName == null) {
mName = "";
}
// 检查当前项在列表中的位置状态(如是否是第一项、最后一项等)
checkPostion(cursor);
}
/**
* 检查当前数据项在游标(列表)中的位置状态
* 这些状态信息可能用于控制列表项的UI显示如分割线、边距等
* @param cursor 数据库游标
*/
private void checkPostion(Cursor cursor) {
// 使用游标的方法判断位置
mIsLastItem = cursor.isLast() ? true : false; // 是否是最后一项
mIsFirstItem = cursor.isFirst() ? true : false; // 是否是第一项
mIsOnlyOneItem = (cursor.getCount() == 1); // 是否只有一项
// 初始化位置关系标志为false
mIsMultiNotesFollowingFolder = false;
mIsOneNoteFollowingFolder = false;
// 只有当当前项是笔记类型(不是文件夹),且不是第一项时,才需要检查前面的项
if (mType == Notes.TYPE_NOTE && !mIsFirstItem) {
// 记录当前位置
int position = cursor.getPosition();
// 将游标移动到前一项(即列表中的上一行)
if (cursor.moveToPrevious()) {
// 检查前一项的类型是否是文件夹或系统文件夹
if (cursor.getInt(TYPE_COLUMN) == Notes.TYPE_FOLDER
|| cursor.getInt(TYPE_COLUMN) == Notes.TYPE_SYSTEM) {
// 判断当前项后面是否还有其他项
if (cursor.getCount() > (position + 1)) {
// 如果后面还有项,说明有多个笔记跟在文件夹后面
mIsMultiNotesFollowingFolder = true;
} else {
// 如果后面没有项了,说明只有一个笔记跟在文件夹后面
mIsOneNoteFollowingFolder = true;
}
}
// 将游标移回原来的位置
if (!cursor.moveToNext()) {
// 理论上不应该发生,如果发生了说明游标状态有问题
throw new IllegalStateException("cursor move to previous but can't move back");
}
}
}
}
// ========== 以下是一系列的getter方法用于外部获取对象的属性值 ==========
/**
* 判断当前笔记是否是唯一一个紧跟在文件夹后面的笔记
* @return 如果是返回true
*/
public boolean isOneFollowingFolder() {
return mIsOneNoteFollowingFolder;
}
/**
* 判断当前笔记是否是多个紧跟在文件夹后面的笔记之一
* @return 如果是返回true
*/
public boolean isMultiFollowingFolder() {
return mIsMultiNotesFollowingFolder;
}
/**
* 判断当前项是否是列表中的最后一项
* @return 如果是最后一项返回true
*/
public boolean isLast() {
return mIsLastItem;
}
/**
* 获取通话记录对应的联系人姓名(如果不是通话记录,返回空字符串)
* @return 联系人姓名
*/
public String getCallName() {
return mName;
}
/**
* 判断当前项是否是列表中的第一项
* @return 如果是第一项返回true
*/
public boolean isFirst() {
return mIsFirstItem;
}
/**
* 判断当前项是否是列表中唯一的一项
* @return 如果是唯一项返回true
*/
public boolean isSingle() {
return mIsOnlyOneItem;
}
/**
* 获取笔记/文件夹的ID
* @return 唯一标识ID
*/
public long getId() {
return mId;
}
/**
* 获取提醒日期时间戳
* @return 提醒时间(毫秒)
*/
public long getAlertDate() {
return mAlertDate;
}
/**
* 获取创建日期时间戳
* @return 创建时间(毫秒)
*/
public long getCreatedDate() {
return mCreatedDate;
}
/**
* 判断是否有附件
* @return 有附件返回true否则false
*/
public boolean hasAttachment() {
return mHasAttachment;
}
/**
* 获取最后修改日期时间戳
* @return 最后修改时间(毫秒)
*/
public long getModifiedDate() {
return mModifiedDate;
}
/**
* 获取背景颜色ID
* @return 背景颜色资源ID
*/
public int getBgColorId() {
return mBgColorId;
}
/**
* 获取父文件夹ID
* @return 父文件夹ID
*/
public long getParentId() {
return mParentId;
}
/**
* 获取文件夹中的笔记数量(如果是文件夹的话)
* @return 包含的笔记数量
*/
public int getNotesCount() {
return mNotesCount;
}
/**
* 获取文件夹ID与getParentId()功能相同,可能是为了语义清晰)
* @return 文件夹ID
*/
public long getFolderId () {
return mParentId;
}
/**
* 获取类型(笔记、文件夹、系统文件夹等)
* @return 类型常量值
*/
public int getType() {
return mType;
}
/**
* 获取小部件类型
* @return 小部件类型常量值
*/
public int getWidgetType() {
return mWidgetType;
}
/**
* 获取小部件ID
* @return 小部件ID
*/
public int getWidgetId() {
return mWidgetId;
}
/**
* 获取内容摘要/片段(已清理清单标记)
* @return 清理后的内容摘要
*/
public String getSnippet() {
return mSnippet;
}
/**
* 判断是否有设置提醒
* @return 有提醒返回truemAlertDate > 0
*/
public boolean hasAlert() {
return (mAlertDate > 0);
}
/**
* 判断是否是通话记录笔记
* 条件:属于通话记录文件夹 且 有有效的电话号码
* @return 是通话记录笔记返回true
*/
public boolean isCallRecord() {
return (mParentId == Notes.ID_CALL_RECORD_FOLDER && !TextUtils.isEmpty(mPhoneNumber));
}
/**
* 静态方法:直接从游标中获取笔记类型
* 这个方法不需要创建NoteItemData对象效率更高
* @param cursor 数据库游标
* @return 笔记类型
*/
public static int getNoteType(Cursor cursor) {
return cursor.getInt(TYPE_COLUMN);
}
}