From 339058b1dd3fc8c8da7449a1796057a3a4c8f032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A2=A7=E9=98=B3=E7=9A=84=E5=B8=95=E5=85=8B?= <3419413165@qq.com> Date: Wed, 28 May 2025 21:26:17 +0800 Subject: [PATCH] 2 --- .idea/misc.xml | 1 - .../src/net/micode/notes/model/Note.java | 144 ++++++++--- .../net/micode/notes/model/WorkingNote.java | 235 ++++++++++++------ .../notes/widget/NoteWidgetProvider.java | 84 ++++++- .../notes/widget/NoteWidgetProvider_2x.java | 30 ++- .../notes/widget/NoteWidgetProvider_4x.java | 31 ++- 6 files changed, 403 insertions(+), 122 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index 1945ce5..cf90582 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,3 @@ - diff --git a/Notes-master/src/net/micode/notes/model/Note.java b/Notes-master/src/net/micode/notes/model/Note.java index 6706cf6..01fcd38 100644 --- a/Notes-master/src/net/micode/notes/model/Note.java +++ b/Notes-master/src/net/micode/notes/model/Note.java @@ -15,6 +15,7 @@ */ package net.micode.notes.model; + import android.content.ContentProviderOperation; import android.content.ContentProviderResult; import android.content.ContentUris; @@ -33,16 +34,25 @@ import net.micode.notes.data.Notes.TextNote; import java.util.ArrayList; - +/** + * 表示笔记应用中的一条笔记,并处理其CRUD操作 + */ public class Note { + // 存储需要更新的笔记列的变化值 private ContentValues mNoteDiffValues; + // 处理与笔记相关的数据(文本或通话数据) private NoteData mNoteData; private static final String TAG = "Note"; + /** - * Create a new note id for adding a new note to databases + * 在数据库中创建新笔记并返回其ID + * @param context 应用上下文 + * @param folderId 笔记将要创建到的文件夹ID + * @return 新创建笔记的ID + * @throws IllegalStateException 如果笔记创建失败 */ public static synchronized long getNewNoteId(Context context, long folderId) { - // Create a new note in the database + // 在数据库中创建新笔记 ContentValues values = new ContentValues(); long createdTime = System.currentTimeMillis(); values.put(NoteColumns.CREATED_DATE, createdTime); @@ -54,55 +64,96 @@ public class Note { long noteId = 0; try { + // 从返回的URI中提取新笔记ID noteId = Long.valueOf(uri.getPathSegments().get(1)); } catch (NumberFormatException e) { - Log.e(TAG, "Get note id error :" + e.toString()); + Log.e(TAG, "获取笔记ID错误:" + e.toString()); noteId = 0; } if (noteId == -1) { - throw new IllegalStateException("Wrong note id:" + noteId); + throw new IllegalStateException("错误的笔记ID:" + noteId); } return noteId; } + /** + * 构造函数 - 用空值初始化笔记 + */ public Note() { mNoteDiffValues = new ContentValues(); mNoteData = new NoteData(); } + /** + * 设置笔记列的值并将笔记标记为已修改 + * @param key 列名 + * @param value 要设置的值 + */ public void setNoteValue(String key, String value) { mNoteDiffValues.put(key, value); mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); } + /** + * 设置文本数据 + * @param key 数据键 + * @param value 数据值 + */ public void setTextData(String key, String value) { mNoteData.setTextData(key, value); } + /** + * 设置文本数据ID + * @param id 文本数据ID + */ public void setTextDataId(long id) { mNoteData.setTextDataId(id); } + /** + * 获取文本数据ID + * @return 文本数据ID + */ public long getTextDataId() { return mNoteData.mTextDataId; } + /** + * 设置通话数据ID + * @param id 通话数据ID + */ public void setCallDataId(long id) { mNoteData.setCallDataId(id); } + /** + * 设置通话数据 + * @param key 数据键 + * @param value 数据值 + */ public void setCallData(String key, String value) { mNoteData.setCallData(key, value); } + /** + * 检查笔记是否有本地修改 + * @return 如果有修改返回true,否则返回false + */ public boolean isLocalModified() { return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified(); } + /** + * 同步笔记到数据库 + * @param context 应用上下文 + * @param noteId 要同步的笔记ID + * @return 同步是否成功 + */ public boolean syncNote(Context context, long noteId) { if (noteId <= 0) { - throw new IllegalArgumentException("Wrong note id:" + noteId); + throw new IllegalArgumentException("错误的笔记ID:" + noteId); } if (!isLocalModified()) { @@ -110,15 +161,15 @@ public class Note { } /** - * In theory, once data changed, the note should be updated on {@link NoteColumns#LOCAL_MODIFIED} and - * {@link NoteColumns#MODIFIED_DATE}. For data safety, though update note fails, we also update the - * note data info + * 理论上,一旦数据更改,笔记应该在{@link NoteColumns#LOCAL_MODIFIED}和 + * {@link NoteColumns#MODIFIED_DATE}上更新。为了数据安全,即使更新笔记失败, + * 我们也会更新笔记数据信息 */ if (context.getContentResolver().update( ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null, null) == 0) { - Log.e(TAG, "Update note error, should not happen"); - // Do not return, fall through + Log.e(TAG, "更新笔记错误,不应该发生"); + // 不返回,继续执行 } mNoteDiffValues.clear(); @@ -130,17 +181,19 @@ public class Note { return true; } + /** + * 内部类,处理笔记的具体数据(文本或通话数据) + */ private class NoteData { - private long mTextDataId; - - private ContentValues mTextDataValues; - - private long mCallDataId; - - private ContentValues mCallDataValues; - + private long mTextDataId; // 文本数据ID + private ContentValues mTextDataValues; // 文本数据值 + private long mCallDataId; // 通话数据ID + private ContentValues mCallDataValues; // 通话数据值 private static final String TAG = "NoteData"; + /** + * 构造函数 - 初始化数据 + */ public NoteData() { mTextDataValues = new ContentValues(); mCallDataValues = new ContentValues(); @@ -148,61 +201,92 @@ public class Note { mCallDataId = 0; } + /** + * 检查数据是否有本地修改 + * @return 如果有修改返回true,否则返回false + */ boolean isLocalModified() { return mTextDataValues.size() > 0 || mCallDataValues.size() > 0; } + /** + * 设置文本数据ID + * @param id 文本数据ID + * @throws IllegalArgumentException 如果ID小于等于0 + */ void setTextDataId(long id) { if(id <= 0) { - throw new IllegalArgumentException("Text data id should larger than 0"); + throw new IllegalArgumentException("文本数据ID应该大于0"); } mTextDataId = id; } + /** + * 设置通话数据ID + * @param id 通话数据ID + * @throws IllegalArgumentException 如果ID小于等于0 + */ void setCallDataId(long id) { if (id <= 0) { - throw new IllegalArgumentException("Call data id should larger than 0"); + throw new IllegalArgumentException("通话数据ID应该大于0"); } mCallDataId = id; } + /** + * 设置通话数据 + * @param key 数据键 + * @param value 数据值 + */ void setCallData(String key, String value) { mCallDataValues.put(key, value); mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); } + /** + * 设置文本数据 + * @param key 数据键 + * @param value 数据值 + */ void setTextData(String key, String value) { mTextDataValues.put(key, value); mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); } + /** + * 将数据推送到ContentResolver + * @param context 应用上下文 + * @param noteId 关联的笔记ID + * @return 操作结果的URI,如果失败返回null + */ Uri pushIntoContentResolver(Context context, long noteId) { - /** - * Check for safety - */ + // 安全检查 if (noteId <= 0) { - throw new IllegalArgumentException("Wrong note id:" + noteId); + throw new IllegalArgumentException("错误的笔记ID:" + noteId); } ArrayList operationList = new ArrayList(); ContentProviderOperation.Builder builder = null; + // 处理文本数据 if(mTextDataValues.size() > 0) { mTextDataValues.put(DataColumns.NOTE_ID, noteId); if (mTextDataId == 0) { + // 新文本数据 - 插入 mTextDataValues.put(DataColumns.MIME_TYPE, TextNote.CONTENT_ITEM_TYPE); Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, mTextDataValues); try { setTextDataId(Long.valueOf(uri.getPathSegments().get(1))); } catch (NumberFormatException e) { - Log.e(TAG, "Insert new text data fail with noteId" + noteId); + Log.e(TAG, "插入新文本数据失败,笔记ID:" + noteId); mTextDataValues.clear(); return null; } } else { + // 现有文本数据 - 更新 builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId( Notes.CONTENT_DATA_URI, mTextDataId)); builder.withValues(mTextDataValues); @@ -211,20 +295,23 @@ public class Note { mTextDataValues.clear(); } + // 处理通话数据 if(mCallDataValues.size() > 0) { mCallDataValues.put(DataColumns.NOTE_ID, noteId); if (mCallDataId == 0) { + // 新通话数据 - 插入 mCallDataValues.put(DataColumns.MIME_TYPE, CallNote.CONTENT_ITEM_TYPE); Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, mCallDataValues); try { setCallDataId(Long.valueOf(uri.getPathSegments().get(1))); } catch (NumberFormatException e) { - Log.e(TAG, "Insert new call data fail with noteId" + noteId); + Log.e(TAG, "插入新通话数据失败,笔记ID:" + noteId); mCallDataValues.clear(); return null; } } else { + // 现有通话数据 - 更新 builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId( Notes.CONTENT_DATA_URI, mCallDataId)); builder.withValues(mCallDataValues); @@ -233,6 +320,7 @@ public class Note { mCallDataValues.clear(); } + // 执行批量操作 if (operationList.size() > 0) { try { ContentProviderResult[] results = context.getContentResolver().applyBatch( @@ -250,4 +338,4 @@ public class Note { return null; } } -} +} \ No newline at end of file diff --git a/Notes-master/src/net/micode/notes/model/WorkingNote.java b/Notes-master/src/net/micode/notes/model/WorkingNote.java index be081e4..71f9147 100644 --- a/Notes-master/src/net/micode/notes/model/WorkingNote.java +++ b/Notes-master/src/net/micode/notes/model/WorkingNote.java @@ -1,19 +1,3 @@ -/* - * 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.model; import android.appwidget.AppWidgetManager; @@ -31,37 +15,33 @@ import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.data.Notes.TextNote; import net.micode.notes.tool.ResourceParser.NoteBgResources; - +/** + * 工作笔记类,处理笔记的创建、加载、保存和修改操作 + */ public class WorkingNote { - // Note for the working note + // 基础笔记对象 private Note mNote; - // Note Id + // 笔记ID private long mNoteId; - // Note content + // 笔记内容 private String mContent; - // Note mode + // 笔记模式(普通模式或清单模式) private int mMode; - private long mAlertDate; - - private long mModifiedDate; - - private int mBgColorId; - - private int mWidgetId; - - private int mWidgetType; - - private long mFolderId; - - private Context mContext; - - private static final String TAG = "WorkingNote"; - - private boolean mIsDeleted; - + private long mAlertDate; // 提醒日期 + private long mModifiedDate; // 修改日期 + private int mBgColorId; // 背景颜色ID + private int mWidgetId; // 关联的小部件ID + private int mWidgetType; // 小部件类型 + private long mFolderId; // 所属文件夹ID + private Context mContext; // 上下文对象 + private static final String TAG = "WorkingNote"; // 日志标签 + private boolean mIsDeleted; // 是否已删除标记 + + // 笔记设置变更监听器 private NoteSettingChangedListener mNoteSettingStatusListener; + // 数据表查询字段 public static final String[] DATA_PROJECTION = new String[] { DataColumns.ID, DataColumns.CONTENT, @@ -72,6 +52,7 @@ public class WorkingNote { DataColumns.DATA4, }; + // 笔记表查询字段 public static final String[] NOTE_PROJECTION = new String[] { NoteColumns.PARENT_ID, NoteColumns.ALERTED_DATE, @@ -81,56 +62,64 @@ public class WorkingNote { NoteColumns.MODIFIED_DATE }; + // 数据表字段索引 private static final int DATA_ID_COLUMN = 0; - private static final int DATA_CONTENT_COLUMN = 1; - private static final int DATA_MIME_TYPE_COLUMN = 2; - private static final int DATA_MODE_COLUMN = 3; + // 笔记表字段索引 private static final int NOTE_PARENT_ID_COLUMN = 0; - private static final int NOTE_ALERTED_DATE_COLUMN = 1; - private static final int NOTE_BG_COLOR_ID_COLUMN = 2; - private static final int NOTE_WIDGET_ID_COLUMN = 3; - private static final int NOTE_WIDGET_TYPE_COLUMN = 4; - private static final int NOTE_MODIFIED_DATE_COLUMN = 5; - // New note construct + /** + * 创建新笔记的构造函数 + * @param context 上下文对象 + * @param folderId 所属文件夹ID + */ private WorkingNote(Context context, long folderId) { mContext = context; - mAlertDate = 0; - mModifiedDate = System.currentTimeMillis(); + mAlertDate = 0; // 初始无提醒 + mModifiedDate = System.currentTimeMillis(); // 设置当前时间为修改时间 mFolderId = folderId; - mNote = new Note(); - mNoteId = 0; - mIsDeleted = false; - mMode = 0; - mWidgetType = Notes.TYPE_WIDGET_INVALIDE; + mNote = new Note(); // 创建基础笔记对象 + mNoteId = 0; // 新笔记初始ID为0 + mIsDeleted = false; // 初始未删除 + mMode = 0; // 默认模式 + mWidgetType = Notes.TYPE_WIDGET_INVALIDE; // 初始无小部件 } - // Existing note construct + /** + * 加载已有笔记的构造函数 + * @param context 上下文对象 + * @param noteId 笔记ID + * @param folderId 所属文件夹ID + */ private WorkingNote(Context context, long noteId, long folderId) { mContext = context; mNoteId = noteId; mFolderId = folderId; mIsDeleted = false; mNote = new Note(); - loadNote(); + loadNote(); // 加载笔记数据 } + /** + * 从数据库加载笔记基本信息 + */ private void loadNote() { + // 查询笔记表 Cursor cursor = mContext.getContentResolver().query( ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mNoteId), NOTE_PROJECTION, null, null, null); if (cursor != null) { if (cursor.moveToFirst()) { + // 从游标读取笔记属性 mFolderId = cursor.getLong(NOTE_PARENT_ID_COLUMN); mBgColorId = cursor.getInt(NOTE_BG_COLOR_ID_COLUMN); mWidgetId = cursor.getInt(NOTE_WIDGET_ID_COLUMN); @@ -140,40 +129,53 @@ public class WorkingNote { } cursor.close(); } else { - Log.e(TAG, "No note with id:" + mNoteId); - throw new IllegalArgumentException("Unable to find note with id " + mNoteId); + Log.e(TAG, "找不到ID为:" + mNoteId + "的笔记"); + throw new IllegalArgumentException("无法找到ID为 " + mNoteId + " 的笔记"); } - loadNoteData(); + loadNoteData(); // 加载笔记内容数据 } + /** + * 从数据库加载笔记内容数据 + */ private void loadNoteData() { + // 查询数据表 Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION, - DataColumns.NOTE_ID + "=?", new String[] { - String.valueOf(mNoteId) - }, null); + 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); mNote.setTextDataId(cursor.getLong(DATA_ID_COLUMN)); } else if (DataConstants.CALL_NOTE.equals(type)) { + // 通话笔记数据 mNote.setCallDataId(cursor.getLong(DATA_ID_COLUMN)); } else { - Log.d(TAG, "Wrong note type with type:" + type); + Log.d(TAG, "错误的笔记类型:" + type); } } while (cursor.moveToNext()); } cursor.close(); } else { - Log.e(TAG, "No data with id:" + mNoteId); - throw new IllegalArgumentException("Unable to find note's data with id " + mNoteId); + Log.e(TAG, "找不到ID为:" + mNoteId + "的笔记数据"); + throw new IllegalArgumentException("无法找到ID为 " + mNoteId + " 的笔记数据"); } } + /** + * 创建空笔记 + * @param context 上下文对象 + * @param folderId 所属文件夹ID + * @param widgetId 小部件ID + * @param widgetType 小部件类型 + * @param defaultBgColorId 默认背景颜色ID + * @return 新创建的WorkingNote对象 + */ public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId, int widgetType, int defaultBgColorId) { WorkingNote note = new WorkingNote(context, folderId); @@ -183,24 +185,33 @@ public class WorkingNote { return note; } + /** + * 加载已有笔记 + * @param context 上下文对象 + * @param id 笔记ID + * @return 加载的WorkingNote对象 + */ public static WorkingNote load(Context context, long id) { return new WorkingNote(context, id, 0); } + /** + * 保存笔记 + * @return 保存是否成功 + */ public synchronized boolean saveNote() { - if (isWorthSaving()) { - if (!existInDatabase()) { + if (isWorthSaving()) { // 检查是否需要保存 + if (!existInDatabase()) { // 如果是新笔记 if ((mNoteId = Note.getNewNoteId(mContext, mFolderId)) == 0) { - Log.e(TAG, "Create new note fail with id:" + mNoteId); + Log.e(TAG, "创建新笔记失败,ID:" + mNoteId); return false; } } + // 同步笔记数据到数据库 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,23 +223,41 @@ public class WorkingNote { } } + /** + * 检查笔记是否已存在于数据库中 + * @return 存在返回true,否则返回false + */ public boolean existInDatabase() { return mNoteId > 0; } + /** + * 检查笔记是否值得保存 + * @return 需要保存返回true,否则返回false + */ private boolean isWorthSaving() { - if (mIsDeleted || (!existInDatabase() && TextUtils.isEmpty(mContent)) - || (existInDatabase() && !mNote.isLocalModified())) { + if (mIsDeleted || // 已删除 + (!existInDatabase() && TextUtils.isEmpty(mContent)) || // 新笔记且内容为空 + (existInDatabase() && !mNote.isLocalModified())) { // 已有笔记且未修改 return false; } else { return true; } } + /** + * 设置笔记设置变更监听器 + * @param l 监听器对象 + */ public void setOnSettingStatusChangedListener(NoteSettingChangedListener l) { mNoteSettingStatusListener = l; } + /** + * 设置提醒日期 + * @param date 提醒日期时间戳 + * @param set 是否设置提醒 + */ public void setAlertDate(long date, boolean set) { if (date != mAlertDate) { mAlertDate = date; @@ -239,14 +268,24 @@ public class WorkingNote { } } + /** + * 标记笔记为删除状态 + * @param mark 是否删除 + */ public void markDeleted(boolean mark) { mIsDeleted = mark; + // 如果有小部件,通知更新 if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID - && mWidgetType != Notes.TYPE_WIDGET_INVALIDE && mNoteSettingStatusListener != null) { + && mWidgetType != Notes.TYPE_WIDGET_INVALIDE + && mNoteSettingStatusListener != null) { mNoteSettingStatusListener.onWidgetChanged(); } } + /** + * 设置背景颜色ID + * @param id 颜色ID + */ public void setBgColorId(int id) { if (id != mBgColorId) { mBgColorId = id; @@ -257,6 +296,10 @@ public class WorkingNote { } } + /** + * 设置清单模式 + * @param mode 模式值 + */ public void setCheckListMode(int mode) { if (mMode != mode) { if (mNoteSettingStatusListener != null) { @@ -267,6 +310,10 @@ public class WorkingNote { } } + /** + * 设置小部件类型 + * @param type 小部件类型 + */ public void setWidgetType(int type) { if (type != mWidgetType) { mWidgetType = type; @@ -274,6 +321,10 @@ public class WorkingNote { } } + /** + * 设置小部件ID + * @param id 小部件ID + */ public void setWidgetId(int id) { if (id != mWidgetId) { mWidgetId = id; @@ -281,6 +332,10 @@ public class WorkingNote { } } + /** + * 设置工作文本内容 + * @param text 文本内容 + */ public void setWorkingText(String text) { if (!TextUtils.equals(mContent, text)) { mContent = text; @@ -288,16 +343,27 @@ public class WorkingNote { } } + /** + * 将笔记转换为通话笔记 + * @param phoneNumber 电话号码 + * @param callDate 通话日期 + */ public void convertToCallNote(String phoneNumber, long callDate) { mNote.setCallData(CallNote.CALL_DATE, String.valueOf(callDate)); mNote.setCallData(CallNote.PHONE_NUMBER, phoneNumber); + // 设置父文件夹为通话记录文件夹 mNote.setNoteValue(NoteColumns.PARENT_ID, String.valueOf(Notes.ID_CALL_RECORD_FOLDER)); } + /** + * 检查是否有提醒设置 + * @return 有提醒返回true,否则返回false + */ public boolean hasClockAlert() { return (mAlertDate > 0 ? true : false); } + // 以下是一系列获取笔记属性的方法 public String getContent() { return mContent; } @@ -342,27 +408,32 @@ public class WorkingNote { return mWidgetType; } + /** + * 笔记设置变更监听器接口 + */ public interface NoteSettingChangedListener { /** - * Called when the background color of current note has just changed + * 当背景颜色改变时调用 */ void onBackgroundColorChanged(); /** - * Called when user set clock + * 当提醒时钟改变时调用 + * @param date 提醒日期 + * @param set 是否设置 */ void onClockAlertChanged(long date, boolean set); /** - * Call when user create note from widget + * 当小部件改变时调用 */ void onWidgetChanged(); /** - * Call when switch between check list mode and normal mode - * @param oldMode is previous mode before change - * @param newMode is new mode + * 当清单模式改变时调用 + * @param oldMode 旧模式 + * @param newMode 新模式 */ void onCheckListModeChanged(int oldMode, int newMode); } -} +} \ No newline at end of file diff --git a/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider.java b/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider.java index ec6f819..081f066 100644 --- a/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider.java +++ b/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider.java @@ -15,6 +15,7 @@ */ package net.micode.notes.widget; + import android.app.PendingIntent; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; @@ -32,23 +33,38 @@ import net.micode.notes.tool.ResourceParser; import net.micode.notes.ui.NoteEditActivity; import net.micode.notes.ui.NotesListActivity; +/** + * 便签桌面小部件的抽象基类,为不同尺寸的便签小部件提供统一实现。 + * 负责管理小部件的生命周期、数据查询和UI更新逻辑。 + */ public abstract class NoteWidgetProvider extends AppWidgetProvider { + // 查询便签数据的投影列 public static final String [] PROJECTION = new String [] { - NoteColumns.ID, - NoteColumns.BG_COLOR_ID, - NoteColumns.SNIPPET + NoteColumns.ID, // 便签ID + NoteColumns.BG_COLOR_ID, // 便签背景颜色ID + NoteColumns.SNIPPET // 便签摘要内容 }; + // 投影列索引常量 public static final int COLUMN_ID = 0; public static final int COLUMN_BG_COLOR_ID = 1; public static final int COLUMN_SNIPPET = 2; private static final String TAG = "NoteWidgetProvider"; + /** + * 当一个或多个小部件被删除时调用。 + * 清除被删除小部件在数据库中的关联信息。 + * + * @param context 应用上下文 + * @param appWidgetIds 被删除的小部件ID数组 + */ @Override public void onDeleted(Context context, int[] appWidgetIds) { ContentValues values = new ContentValues(); values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); + + // 遍历删除的小部件ID,清除数据库中的关联 for (int i = 0; i < appWidgetIds.length; i++) { context.getContentResolver().update(Notes.CONTENT_NOTE_URI, values, @@ -57,6 +73,13 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider { } } + /** + * 查询与指定小部件ID关联的便签信息。 + * + * @param context 应用上下文 + * @param widgetId 小部件ID + * @return 包含便签信息的Cursor,若无数据则返回null + */ private Cursor getNoteWidgetInfo(Context context, int widgetId) { return context.getContentResolver().query(Notes.CONTENT_NOTE_URI, PROJECTION, @@ -65,68 +88,115 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider { null); } + /** + * 更新一组小部件的UI显示(非隐私模式)。 + * + * @param context 应用上下文 + * @param appWidgetManager 小部件管理器 + * @param appWidgetIds 需要更新的小部件ID数组 + */ protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { update(context, appWidgetManager, appWidgetIds, false); } + /** + * 更新一组小部件的UI显示,支持隐私模式。 + * + * @param context 应用上下文 + * @param appWidgetManager 小部件管理器 + * @param appWidgetIds 需要更新的小部件ID数组 + * @param privacyMode 是否启用隐私模式 + */ private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds, boolean privacyMode) { + // 遍历所有小部件ID并更新UI for (int i = 0; i < appWidgetIds.length; i++) { if (appWidgetIds[i] != AppWidgetManager.INVALID_APPWIDGET_ID) { + // 初始化默认值 int bgId = ResourceParser.getDefaultBgId(context); String snippet = ""; + + // 创建便签编辑页面的意图 Intent intent = new Intent(context, NoteEditActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); intent.putExtra(Notes.INTENT_EXTRA_WIDGET_ID, appWidgetIds[i]); intent.putExtra(Notes.INTENT_EXTRA_WIDGET_TYPE, getWidgetType()); + // 查询便签数据 Cursor c = getNoteWidgetInfo(context, appWidgetIds[i]); if (c != null && c.moveToFirst()) { + // 检查是否存在多个匹配的便签(异常情况) if (c.getCount() > 1) { Log.e(TAG, "Multiple message with same widget id:" + appWidgetIds[i]); c.close(); return; } + + // 获取便签内容和背景 snippet = c.getString(COLUMN_SNIPPET); bgId = c.getInt(COLUMN_BG_COLOR_ID); intent.putExtra(Intent.EXTRA_UID, c.getLong(COLUMN_ID)); intent.setAction(Intent.ACTION_VIEW); } else { + // 若无关联便签,显示默认提示 snippet = context.getResources().getString(R.string.widget_havenot_content); intent.setAction(Intent.ACTION_INSERT_OR_EDIT); } + // 关闭Cursor释放资源 if (c != null) { c.close(); } + // 创建RemoteViews并设置UI元素 RemoteViews rv = new RemoteViews(context.getPackageName(), getLayoutId()); rv.setImageViewResource(R.id.widget_bg_image, getBgResourceId(bgId)); intent.putExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, bgId); - /** - * Generate the pending intent to start host for the widget - */ + + // 根据隐私模式设置不同的点击行为 PendingIntent pendingIntent = null; if (privacyMode) { + // 隐私模式:显示通用提示并打开便签列表 rv.setTextViewText(R.id.widget_text, context.getString(R.string.widget_under_visit_mode)); pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], new Intent( context, NotesListActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); } else { + // 正常模式:显示便签内容并打开编辑页面 rv.setTextViewText(R.id.widget_text, snippet); pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], intent, PendingIntent.FLAG_UPDATE_CURRENT); } + // 设置点击事件并更新小部件 rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent); appWidgetManager.updateAppWidget(appWidgetIds[i], rv); } } } + /** + * 根据背景ID获取对应的背景资源。 + * 由子类实现以提供特定尺寸的背景资源。 + * + * @param bgId 背景样式ID + * @return 对应的背景资源ID + */ protected abstract int getBgResourceId(int bgId); + /** + * 获取小部件布局资源ID。 + * 由子类实现以提供特定尺寸的布局。 + * + * @return 布局资源ID + */ protected abstract int getLayoutId(); + /** + * 获取小部件类型常量。 + * 由子类实现以标识不同尺寸的小部件类型。 + * + * @return 小部件类型常量 + */ protected abstract int getWidgetType(); -} +} \ No newline at end of file diff --git a/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_2x.java b/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_2x.java index adcb2f7..31ca097 100644 --- a/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_2x.java +++ b/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_2x.java @@ -23,25 +23,51 @@ import net.micode.notes.R; import net.micode.notes.data.Notes; import net.micode.notes.tool.ResourceParser; - +/** + * 2×2尺寸的便签桌面小部件实现类。 + * 继承自NoteWidgetProvider基类,负责处理2×2规格小部件的更新和显示逻辑。 + */ public class NoteWidgetProvider_2x extends NoteWidgetProvider { + /** + * 当小部件更新时调用,触发基类的更新逻辑。 + * + * @param context 应用上下文 + * @param appWidgetManager 小部件管理器 + * @param appWidgetIds 需要更新的小部件ID数组 + */ @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.update(context, appWidgetManager, appWidgetIds); } + /** + * 获取小部件布局资源ID。 + * + * @return R.layout.widget_2x对应的布局资源ID + */ @Override protected int getLayoutId() { return R.layout.widget_2x; } + /** + * 根据背景ID获取对应的背景资源。 + * + * @param bgId 背景样式ID + * @return 2×2小部件对应的背景资源ID + */ @Override protected int getBgResourceId(int bgId) { return ResourceParser.WidgetBgResources.getWidget2xBgResource(bgId); } + /** + * 获取小部件类型常量。 + * + * @return Notes.TYPE_WIDGET_2X,表示2×2尺寸的小部件类型 + */ @Override protected int getWidgetType() { return Notes.TYPE_WIDGET_2X; } -} +} \ No newline at end of file diff --git a/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_4x.java b/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_4x.java index c12a02e..b09aca4 100644 --- a/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_4x.java +++ b/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_4x.java @@ -23,24 +23,51 @@ import net.micode.notes.R; import net.micode.notes.data.Notes; import net.micode.notes.tool.ResourceParser; - +/** + * 4×4尺寸的便签桌面小部件实现类。 + * 继承自NoteWidgetProvider基类,负责处理4×4规格小部件的更新和显示逻辑。 + */ public class NoteWidgetProvider_4x extends NoteWidgetProvider { + /** + * 当小部件更新时调用,触发基类的更新逻辑。 + * + * @param context 应用上下文 + * @param appWidgetManager 小部件管理器 + * @param appWidgetIds 需要更新的小部件ID数组 + */ @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.update(context, appWidgetManager, appWidgetIds); } + /** + * 获取小部件布局资源ID。 + * + * @return R.layout.widget_4x对应的布局资源ID + */ + @Override protected int getLayoutId() { return R.layout.widget_4x; } + /** + * 根据背景ID获取对应的背景资源。 + * + * @param bgId 背景样式ID + * @return 4×4小部件对应的背景资源ID + */ @Override protected int getBgResourceId(int bgId) { return ResourceParser.WidgetBgResources.getWidget4xBgResource(bgId); } + /** + * 获取小部件类型常量。 + * + * @return Notes.TYPE_WIDGET_4X,表示4×4尺寸的小部件类型 + */ @Override protected int getWidgetType() { return Notes.TYPE_WIDGET_4X; } -} +} \ No newline at end of file