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.
git/java/net/micode/notes/ui/NoteItemData.java

421 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.
*/
// NoteItemData.java - 便签项数据模型类
// 主要功能:封装便签列表项的数据,提供便捷的访问方法和位置判断逻辑
package net.micode.notes.ui;
// ======================= 导入区域 =======================
// Android基础
import android.content.Context; // 上下文
import android.database.Cursor; // 数据库查询结果游标
import android.text.TextUtils; // 文本工具
// 应用内部工具
import net.micode.notes.data.Contact; // 联系人工具类
import net.micode.notes.data.Notes; // Notes主类
import net.micode.notes.data.Notes.NoteColumns; // 便签表列定义
import net.micode.notes.tool.DataUtils; // 数据工具
// ======================= 便签项数据模型 =======================
/**
* NoteItemData - 便签项数据模型类
* 功能从数据库Cursor解析便签数据封装为对象模型
* 用途:在便签列表适配器中表示单个便签项的数据
* 特点:包含位置判断逻辑,用于列表项背景选择
*/
public class NoteItemData {
// ======================= 数据库查询配置 =======================
/**
* 查询投影数组 - 指定从数据库查询哪些字段
* 包含便签表的所有重要字段
*/
static final String [] PROJECTION = new String [] {
NoteColumns.ID, // 0 - 便签ID
NoteColumns.ALERTED_DATE, // 1 - 提醒时间
NoteColumns.BG_COLOR_ID, // 2 - 背景颜色ID
NoteColumns.CREATED_DATE, // 3 - 创建时间
NoteColumns.HAS_ATTACHMENT, // 4 - 是否有附件
NoteColumns.MODIFIED_DATE, // 5 - 修改时间
NoteColumns.NOTES_COUNT, // 6 - 包含的便签数(文件夹用)
NoteColumns.PARENT_ID, // 7 - 父文件夹ID
NoteColumns.SNIPPET, // 8 - 便签摘要
NoteColumns.TYPE, // 9 - 便签类型
NoteColumns.WIDGET_ID, // 10 - 小部件ID
NoteColumns.WIDGET_TYPE, // 11 - 小部件类型
NoteColumns.PINNED // 12 - 是否置顶
};
// ======================= 字段索引常量 =======================
// 使用常量而非魔法数字,提高代码可读性
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; // 背景颜色字段索引
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 static final int PINNED_COLUMN = 12; // 是否置顶字段索引
// ======================= 数据成员 =======================
// 基本数据字段
private long mId; // 便签ID
private long mAlertDate; // 提醒时间戳
private int mBgColorId; // 背景颜色索引
private long mCreatedDate; // 创建时间戳
private boolean mHasAttachment; // 是否有附件
private long mModifiedDate; // 修改时间戳
private int mNotesCount; // 包含的便签数(文件夹)
private long mParentId; // 父文件夹ID
private String mSnippet; // 便签摘要
private int mType; // 便签类型
private int mWidgetId; // 小部件ID
private int mWidgetType; // 小部件类型
private boolean mPinned; // 是否置顶
// 通话记录相关
private String mName; // 联系人姓名
private String mPhoneNumber; // 电话号码
// 位置状态标志
private boolean mIsLastItem; // 是否是列表最后一项
private boolean mIsFirstItem; // 是否是列表第一项
private boolean mIsOnlyOneItem; // 是否是唯一一项
private boolean mIsOneNoteFollowingFolder; // 是否是文件夹后的唯一便签
private boolean mIsMultiNotesFollowingFolder; // 是否是文件夹后的多个便签之一
// ======================= 构造函数 =======================
/**
* 构造函数
* 从Cursor解析数据并初始化对象
* 执行流程:
* 1. 从Cursor读取所有字段
* 2. 清理清单标记
* 3. 处理通话记录
* 4. 检查位置状态
*
* @param context 上下文,用于联系人查询
* @param cursor 数据库游标必须包含PROJECTION指定的字段
*/
public NoteItemData(Context context, Cursor cursor) {
// 1. 读取基本字段
mId = cursor.getLong(ID_COLUMN);
mAlertDate = cursor.getLong(ALERTED_DATE_COLUMN);
mBgColorId = cursor.getInt(BG_COLOR_ID_COLUMN);
mCreatedDate = cursor.getLong(CREATED_DATE_COLUMN);
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);
mType = cursor.getInt(TYPE_COLUMN);
mWidgetId = cursor.getInt(WIDGET_ID_COLUMN);
mWidgetType = cursor.getInt(WIDGET_TYPE_COLUMN);
mPinned = (cursor.getInt(PINNED_COLUMN) > 0) ? true : false;
// 2. 清理摘要中的清单标记
// 移除已勾选(√)和未勾选(□)标记,只显示纯文本
mSnippet = mSnippet.replace(NoteEditActivity.TAG_CHECKED, "").replace(
NoteEditActivity.TAG_UNCHECKED, "");
// 3. 处理通话记录
mPhoneNumber = ""; // 初始化电话号码
if (mParentId == Notes.ID_CALL_RECORD_FOLDER) {
// 从通话记录文件夹中获取电话号码
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 = "";
}
// 4. 检查位置状态
checkPostion(cursor);
}
// ======================= 位置检查方法 =======================
/**
* 检查便签在列表中的位置状态
* 用于确定列表项应使用的背景样式
* 位置判断逻辑:
* 1. 基本位置:首项、末项、唯一项
* 2. 文件夹后位置:文件夹后的第一个便签、多个便签
*
* @param cursor 数据库游标,用于位置判断
*/
private void checkPostion(Cursor cursor) {
// 1. 基本位置判断
mIsLastItem = cursor.isLast() ? true : false; // 是否是最后一项
mIsFirstItem = cursor.isFirst() ? true : false; // 是否是第一项
mIsOnlyOneItem = (cursor.getCount() == 1); // 是否是唯一一项
// 初始化文件夹后位置标志
mIsMultiNotesFollowingFolder = false;
mIsOneNoteFollowingFolder = false;
// 2. 判断是否是文件夹后的便签
// 条件:当前是便签类型 且 不是第一项
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");
}
}
}
}
// ======================= 位置状态获取方法 =======================
/**
* 是否是文件夹后的唯一便签
* 用于选择列表项背景list_{color}_single
* @return true: 是文件夹后的唯一便签
*/
public boolean isOneFollowingFolder() {
return mIsOneNoteFollowingFolder;
}
/**
* 是否是文件夹后的多个便签之一
* 用于选择列表项背景list_{color}_middle
* @return true: 是文件夹后的多个便签之一
*/
public boolean isMultiFollowingFolder() {
return mIsMultiNotesFollowingFolder;
}
/**
* 是否是列表最后一项
* 用于选择列表项背景list_{color}_down
* @return true: 是最后一项
*/
public boolean isLast() {
return mIsLastItem;
}
/**
* 获取通话记录联系人姓名
* 用于通话记录便签的显示
* @return 联系人姓名,无联系人时返回电话号码
*/
public String getCallName() {
return mName;
}
/**
* 是否是列表第一项
* 用于选择列表项背景list_{color}_up
* @return true: 是第一项
*/
public boolean isFirst() {
return mIsFirstItem;
}
/**
* 是否是列表唯一项
* 用于选择列表项背景list_{color}_single
* @return true: 是唯一项
*/
public boolean isSingle() {
return mIsOnlyOneItem;
}
// ======================= 基本属性获取方法 =======================
/**
* 获取便签ID
* @return 便签ID
*/
public long getId() {
return mId;
}
/**
* 获取提醒时间
* @return 提醒时间戳0表示无提醒
*/
public long getAlertDate() {
return mAlertDate;
}
/**
* 获取创建时间
* @return 创建时间戳
*/
public long getCreatedDate() {
return mCreatedDate;
}
/**
* 是否包含附件
* @return true: 包含附件
*/
public boolean hasAttachment() {
return mHasAttachment;
}
/**
* 获取修改时间
* @return 修改时间戳
*/
public long getModifiedDate() {
return mModifiedDate;
}
/**
* 获取背景颜色ID
* @return 背景颜色索引
*/
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 类型常量TYPE_NOTE, TYPE_FOLDER, TYPE_SYSTEM
*/
public int getType() {
return mType;
}
/**
* 获取小部件类型
* @return 小部件类型TYPE_WIDGET_INVALIDE, TYPE_WIDGET_2X, TYPE_WIDGET_4X
*/
public int getWidgetType() {
return mWidgetType;
}
/**
* 获取便签是否置顶
* @return true: 置顶, false: 不置顶
*/
public boolean isPinned() {
return mPinned;
}
/**
* 获取小部件ID
* @return 小部件ID
*/
public int getWidgetId() {
return mWidgetId;
}
/**
* 获取便签摘要
* 已清理清单标记
* @return 便签摘要文本
*/
public String getSnippet() {
return mSnippet;
}
// ======================= 状态判断方法 =======================
/**
* 是否有提醒设置
* @return true: 设置了提醒
*/
public boolean hasAlert() {
return (mAlertDate > 0);
}
/**
* 是否是通话记录
* 判断条件:在通话记录文件夹中 且 有电话号码
* @return true: 是通话记录
*/
public boolean isCallRecord() {
return (mParentId == Notes.ID_CALL_RECORD_FOLDER && !TextUtils.isEmpty(mPhoneNumber));
}
// ======================= 静态工具方法 =======================
/**
* 从Cursor获取便签类型
* 静态方法,无需创建对象
* @param cursor 数据库游标
* @return 便签类型
*/
public static int getNoteType(Cursor cursor) {
return cursor.getInt(TYPE_COLUMN);
}
}