|
|
|
@ -31,9 +31,26 @@ import net.micode.notes.data.Notes.NoteColumns;
|
|
|
|
|
import net.micode.notes.data.Notes.TextNote;
|
|
|
|
|
import net.micode.notes.tool.ResourceParser.NoteBgResources;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @ProjectName: xiaomibianqian
|
|
|
|
|
* @Package: model
|
|
|
|
|
* @ClassName: WorkingNote
|
|
|
|
|
* @Description: 创建了一个正在工作的便签类,其中有大量的参数,包括参量类、布尔值类、区分类的变量
|
|
|
|
|
* 另外,封装了一系列的函数,其中有返回私有变量的,与数据库进行操作的,在不同情况下操作的(如新建的便签与修改的便签)
|
|
|
|
|
* 主要交互的包、类:NoteEditActivities,Notes(from data)Note NoteListActivity SqlData
|
|
|
|
|
* 另外,有创建一些接口,比如NoteSettingChangedListener,在NoteEditActivities中具体实现
|
|
|
|
|
*
|
|
|
|
|
* @Author: zhoushiyu_br
|
|
|
|
|
* @CreateDate: 2023.12.16
|
|
|
|
|
* @UpdateUser: 更新者:
|
|
|
|
|
* @UpdateDate: 2023.12.21
|
|
|
|
|
* @UpdateRemark: 更新说明:
|
|
|
|
|
* @Version: 这次更新主要是修改了之前代码批注不够规范的问题,结合上课毛教员对于问题的指出,对格式进行了优化——PickupRAIN
|
|
|
|
|
*/
|
|
|
|
|
public class WorkingNote {
|
|
|
|
|
// Note for the working note
|
|
|
|
|
//这个在Note里面定义了Note类的基本类型,
|
|
|
|
|
private Note mNote;
|
|
|
|
|
// Note Id
|
|
|
|
|
private long mNoteId;
|
|
|
|
@ -43,26 +60,41 @@ public class WorkingNote {
|
|
|
|
|
private int mMode;
|
|
|
|
|
|
|
|
|
|
private long mAlertDate;
|
|
|
|
|
//最后的修改日期
|
|
|
|
|
|
|
|
|
|
private long mModifiedDate;
|
|
|
|
|
//定义的颜色的ID
|
|
|
|
|
|
|
|
|
|
private int mBgColorId;
|
|
|
|
|
|
|
|
|
|
//定义了一个int类型,用来定位到哪一个小组件被使用
|
|
|
|
|
private int mWidgetId;
|
|
|
|
|
|
|
|
|
|
//定义了一个int类型,用来区分使用了什么类型的小组件
|
|
|
|
|
private int mWidgetType;
|
|
|
|
|
|
|
|
|
|
//用来定位便签放在哪个文件夹
|
|
|
|
|
private long mFolderId;
|
|
|
|
|
|
|
|
|
|
private Context mContext;
|
|
|
|
|
|
|
|
|
|
//定义为静态变量,保证不能再被更改。防止数据出现异常
|
|
|
|
|
private static final String TAG = "WorkingNote";
|
|
|
|
|
|
|
|
|
|
//定义一个布尔变量,用来保存是否要被删除。通过查看用法,发现在后面保存|修改的时候要进行判断。
|
|
|
|
|
private boolean mIsDeleted;
|
|
|
|
|
|
|
|
|
|
//定义了一个接口,具体是在NoteEditActivities中实现,实现对于便签是否修改的监听
|
|
|
|
|
private NoteSettingChangedListener mNoteSettingStatusListener;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 定义一个数组,保存DataColumn数组当中的一些列变量。关于DataColumn的注解我写在了定义处。
|
|
|
|
|
* 之所以用一个字符串数组来调用DataColumn接口,是为了“方便在进行数据库操作时可以一次性指定需要查询的列”?
|
|
|
|
|
* 这个数组只有在loadNoteData这个函数的时候进行了调用。将数据加载到
|
|
|
|
|
* 12.22更新,我学习了getContentResolver()的用法
|
|
|
|
|
* 实际上,getContentResolver是用来查询数据库的,这里定义的Projection是所有属性的集合。数据库查询,按列进行
|
|
|
|
|
* 在按列查询时,在数据库访问到底,只需要在数组中继续访问即可。关于函数详解我会写在函数的定义处;
|
|
|
|
|
*/
|
|
|
|
|
public static final String[] DATA_PROJECTION = new String[] {
|
|
|
|
|
//在Note里面定义一个接口类型
|
|
|
|
|
DataColumns.ID,
|
|
|
|
|
DataColumns.CONTENT,
|
|
|
|
|
DataColumns.MIME_TYPE,
|
|
|
|
@ -71,7 +103,7 @@ public class WorkingNote {
|
|
|
|
|
DataColumns.DATA3,
|
|
|
|
|
DataColumns.DATA4,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//这里的用法基本同上方,不过这些接口最后使用在数据库中
|
|
|
|
|
public static final String[] NOTE_PROJECTION = new String[] {
|
|
|
|
|
NoteColumns.PARENT_ID,
|
|
|
|
|
NoteColumns.ALERTED_DATE,
|
|
|
|
@ -80,7 +112,9 @@ public class WorkingNote {
|
|
|
|
|
NoteColumns.WIDGET_TYPE,
|
|
|
|
|
NoteColumns.MODIFIED_DATE
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 定义了一系列的基础值。
|
|
|
|
|
*/
|
|
|
|
|
private static final int DATA_ID_COLUMN = 0;
|
|
|
|
|
|
|
|
|
|
private static final int DATA_CONTENT_COLUMN = 1;
|
|
|
|
@ -101,11 +135,21 @@ public class WorkingNote {
|
|
|
|
|
|
|
|
|
|
private static final int NOTE_MODIFIED_DATE_COLUMN = 5;
|
|
|
|
|
|
|
|
|
|
// New note construct
|
|
|
|
|
/**
|
|
|
|
|
* @method: WorkingNote
|
|
|
|
|
* @description: 初始化一个新的操作的Note
|
|
|
|
|
* @date: 2024/1/6 11:28
|
|
|
|
|
* @author: 周石宇
|
|
|
|
|
* @param: [android.content.Context, long]:[context, folderId]
|
|
|
|
|
* @return:
|
|
|
|
|
*/
|
|
|
|
|
private WorkingNote(Context context, long folderId) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mContext = context;
|
|
|
|
|
mAlertDate = 0;
|
|
|
|
|
mModifiedDate = System.currentTimeMillis();
|
|
|
|
|
mAlertDate = 0;//这里为什么是0还存疑
|
|
|
|
|
mModifiedDate = System.currentTimeMillis();//获取系统时间,保存给最后修改时间
|
|
|
|
|
mFolderId = folderId;
|
|
|
|
|
mNote = new Note();
|
|
|
|
|
mNoteId = 0;
|
|
|
|
@ -113,7 +157,8 @@ public class WorkingNote {
|
|
|
|
|
mMode = 0;
|
|
|
|
|
mWidgetType = Notes.TYPE_WIDGET_INVALIDE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//由于传入了noteId,所以是对一个已经存在的便签进行操作。
|
|
|
|
|
//由于一些基本的已经定义,所以传入的变量很少。
|
|
|
|
|
// Existing note construct
|
|
|
|
|
private WorkingNote(Context context, long noteId, long folderId) {
|
|
|
|
|
mContext = context;
|
|
|
|
@ -124,11 +169,24 @@ public class WorkingNote {
|
|
|
|
|
loadNote();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @author: zhoushiyu_PickupRAIN
|
|
|
|
|
* @methodsName: loadNote
|
|
|
|
|
* @description: 创建游标,对数据库进行操作。首先从传入的URI中找到数据库地址,对元素数组进行逐列筛选。
|
|
|
|
|
* @param: 虽然没传入,,但是说明一下
|
|
|
|
|
* ->Notes.CONTENT_NOTE_URI:数据库的地址,根据URI找到相应数据库
|
|
|
|
|
* ->NOTE_PROJECTION :属性列表,包含了所有的表头
|
|
|
|
|
* ->这里就能很容易理解为什么NOTE_PROJECTION为什么只在这里调用,也没有初始化。
|
|
|
|
|
* @return: String
|
|
|
|
|
* @throws: Nopes
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
private void loadNote() {
|
|
|
|
|
//定义一个cursor游标,用来操作数据。这里传入了很多量,如URI、Id、和来自Projection的一系列。
|
|
|
|
|
Cursor cursor = mContext.getContentResolver().query(
|
|
|
|
|
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mNoteId), NOTE_PROJECTION, null,
|
|
|
|
|
null, null);
|
|
|
|
|
|
|
|
|
|
//设置一个cursor,按行提取各种信息,保存到对应的变量中
|
|
|
|
|
if (cursor != null) {
|
|
|
|
|
if (cursor.moveToFirst()) {
|
|
|
|
|
mFolderId = cursor.getLong(NOTE_PARENT_ID_COLUMN);
|
|
|
|
@ -145,22 +203,38 @@ public class WorkingNote {
|
|
|
|
|
}
|
|
|
|
|
loadNoteData();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @method: loadNoteData
|
|
|
|
|
* @description: 基本同上一个函数。值得注意的是这里对数据进行了筛选(通过selection),还对MIME进行了判断后加载
|
|
|
|
|
* @date: 2024/1/6 11:29
|
|
|
|
|
* @author: 周石宇
|
|
|
|
|
* @param: []:[]
|
|
|
|
|
* @return: void
|
|
|
|
|
*/
|
|
|
|
|
private void loadNoteData() {
|
|
|
|
|
Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION,
|
|
|
|
|
DataColumns.NOTE_ID + "=?", new String[] {
|
|
|
|
|
String.valueOf(mNoteId)
|
|
|
|
|
}, null);
|
|
|
|
|
|
|
|
|
|
if (cursor != null) {
|
|
|
|
|
// 检查是否有数据
|
|
|
|
|
if (cursor.moveToFirst()) {
|
|
|
|
|
do {
|
|
|
|
|
// 获取类型
|
|
|
|
|
String type = cursor.getString(DATA_MIME_TYPE_COLUMN);
|
|
|
|
|
if (DataConstants.NOTE.equals(type)) {
|
|
|
|
|
// 获取内容
|
|
|
|
|
mContent = cursor.getString(DATA_CONTENT_COLUMN);
|
|
|
|
|
// 获取模式
|
|
|
|
|
mMode = cursor.getInt(DATA_MODE_COLUMN);
|
|
|
|
|
// 获取ID
|
|
|
|
|
mNote.setTextDataId(cursor.getLong(DATA_ID_COLUMN));
|
|
|
|
|
} else if (DataConstants.CALL_NOTE.equals(type)) {
|
|
|
|
|
// 设置通话ID
|
|
|
|
|
mNote.setCallDataId(cursor.getLong(DATA_ID_COLUMN));
|
|
|
|
|
} else {
|
|
|
|
|
Log.d(TAG, "Wrong note type with type:" + type);
|
|
|
|
@ -174,33 +248,61 @@ public class WorkingNote {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId,
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @method: createEmptyNote
|
|
|
|
|
* @description: 创建一个空的笔记
|
|
|
|
|
* @date: 2024/1/2 10:21
|
|
|
|
|
* @author: 周石宇
|
|
|
|
|
* @param: [android.content.Context, long, int, int, int]:[context, folderId, widgetId, widgetType, defaultBgColorId]
|
|
|
|
|
* @return: net.micode.notes.model.WorkingNote
|
|
|
|
|
*/
|
|
|
|
|
public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId,
|
|
|
|
|
|
|
|
|
|
int widgetType, int defaultBgColorId) {
|
|
|
|
|
// 创建一个新的WorkingNote实例
|
|
|
|
|
WorkingNote note = new WorkingNote(context, folderId);
|
|
|
|
|
// 设置笔记的背景颜色
|
|
|
|
|
note.setBgColorId(defaultBgColorId);
|
|
|
|
|
// 设置笔记的widgetId
|
|
|
|
|
note.setWidgetId(widgetId);
|
|
|
|
|
// 设置笔记的widgetType
|
|
|
|
|
note.setWidgetType(widgetType);
|
|
|
|
|
// 返回新的WorkingNote实例
|
|
|
|
|
return note;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static WorkingNote load(Context context, long id) {
|
|
|
|
|
return new WorkingNote(context, id, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public synchronized boolean saveNote() {
|
|
|
|
|
/**
|
|
|
|
|
* @method: saveNote
|
|
|
|
|
* @description: 保存笔记
|
|
|
|
|
* @date: 2024/1/2 10:23
|
|
|
|
|
* @author: 周石宇
|
|
|
|
|
* @param: []:[]
|
|
|
|
|
* @return: boolean
|
|
|
|
|
*/
|
|
|
|
|
public synchronized boolean saveNote() {
|
|
|
|
|
|
|
|
|
|
// 如果笔记 worth saving
|
|
|
|
|
if (isWorthSaving()) {
|
|
|
|
|
// 如果笔记不存在数据库中
|
|
|
|
|
if (!existInDatabase()) {
|
|
|
|
|
// 获取新笔记id
|
|
|
|
|
if ((mNoteId = Note.getNewNoteId(mContext, mFolderId)) == 0) {
|
|
|
|
|
Log.e(TAG, "Create new note fail with id:" + mNoteId);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//由于没有这个便签,所以报错,并返回false
|
|
|
|
|
|
|
|
|
|
mNote.syncNote(mContext, mNoteId);
|
|
|
|
|
mNote.syncNote(mContext, mNoteId);//这一行是同步信息的操作
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Update widget content if there exist any widget of this note
|
|
|
|
|
*/
|
|
|
|
|
//对小组件的各种属性进行判断,来确定是否有组件,进行保存
|
|
|
|
|
if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID
|
|
|
|
|
&& mWidgetType != Notes.TYPE_WIDGET_INVALIDE
|
|
|
|
|
&& mNoteSettingStatusListener != null) {
|
|
|
|
@ -212,11 +314,26 @@ public class WorkingNote {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 以下定义、封装了一系列的实用函数,用于一些私有量的设置与判断
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public boolean existInDatabase() {
|
|
|
|
|
return mNoteId > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @method: isWorthSaving
|
|
|
|
|
* @description: 判断是否值得保存,即判断是否需要保存到数据库
|
|
|
|
|
* @date: 2024/1/2 10:24
|
|
|
|
|
* @author: 周石宇
|
|
|
|
|
* @param: []:[]
|
|
|
|
|
* @return: boolean
|
|
|
|
|
*/
|
|
|
|
|
private boolean isWorthSaving() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mIsDeleted || (!existInDatabase() && TextUtils.isEmpty(mContent))
|
|
|
|
|
|| (existInDatabase() && !mNote.isLocalModified())) {
|
|
|
|
|
return false;
|
|
|
|
@ -224,8 +341,19 @@ public class WorkingNote {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* @method: setOnSettingStatusChangedListener
|
|
|
|
|
* @description: 用来记录状态设定是否有发生过更改。
|
|
|
|
|
* @date: 2024/1/2 10:24
|
|
|
|
|
* @author: 周石宇
|
|
|
|
|
* @param: [net.micode.notes.model.WorkingNote.NoteSettingChangedListener]:[l]
|
|
|
|
|
* @return: void
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
public void setOnSettingStatusChangedListener(NoteSettingChangedListener l) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mNoteSettingStatusListener = l;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -256,8 +384,18 @@ public class WorkingNote {
|
|
|
|
|
mNote.setNoteValue(NoteColumns.BG_COLOR_ID, String.valueOf(id));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @method: setCheckListMode
|
|
|
|
|
* @description: 在EditActivities中使用,用来设定在list时的状态
|
|
|
|
|
* @date: 2024/1/6 11:30
|
|
|
|
|
* @author: 周石宇
|
|
|
|
|
* @param: [int]:[mode]
|
|
|
|
|
* @return: void
|
|
|
|
|
*/
|
|
|
|
|
public void setCheckListMode(int mode) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mMode != mode) {
|
|
|
|
|
if (mNoteSettingStatusListener != null) {
|
|
|
|
|
mNoteSettingStatusListener.onCheckListModeChanged(mMode, mode);
|
|
|
|
@ -288,6 +426,14 @@ public class WorkingNote {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 从这里一直向上大概的都是一些设置状态的函数。
|
|
|
|
|
* 原因是设置的私有量,保证数据的可靠性
|
|
|
|
|
* 具体使用在onOptionsItemSelected NoteEditActivities类,中调用
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//这里的callNote我没有搞懂
|
|
|
|
|
public void convertToCallNote(String phoneNumber, long callDate) {
|
|
|
|
|
mNote.setCallData(CallNote.CALL_DATE, String.valueOf(callDate));
|
|
|
|
|
mNote.setCallData(CallNote.PHONE_NUMBER, phoneNumber);
|
|
|
|
@ -341,7 +487,7 @@ public class WorkingNote {
|
|
|
|
|
public int getWidgetType() {
|
|
|
|
|
return mWidgetType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//声明了一个接口,具体都在EditActivies中进行实现。主要是一个监听(listener),来设置各个量的改变
|
|
|
|
|
public interface NoteSettingChangedListener {
|
|
|
|
|
/**
|
|
|
|
|
* Called when the background color of current note has just changed
|
|
|
|
|