diff --git a/Notesmaster/app/src/main/java/net/micode/notes/gtask/data/MetaData.java b/Notesmaster/app/src/main/java/net/micode/notes/gtask/data/MetaData.java index 3a2050b..45b4bea 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/gtask/data/MetaData.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/gtask/data/MetaData.java @@ -26,57 +26,109 @@ import org.json.JSONObject; public class MetaData extends Task { + // 常量标签,用于日志输出,值为当前类的简单名称 private final static String TAG = MetaData.class.getSimpleName(); + // 相关GID的字符串变量,初始化为null private String mRelatedGid = null; + /** + * 设置元数据 + * + * @param gid 任务的GID + * @param metaInfo 包含元数据的JSONObject对象 + */ public void setMeta(String gid, JSONObject metaInfo) { try { + // 将GID放入metaInfo中,键为GTaskStringUtils.META_HEAD_GTASK_ID metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid); } catch (JSONException e) { + // 如果放入GID失败,输出错误日志 Log.e(TAG, "failed to put related gid"); } + // 将metaInfo转换为字符串并设置为便签的备注 setNotes(metaInfo.toString()); + // 设置便签的名称为预定义的元数据名称 setName(GTaskStringUtils.META_NOTE_NAME); } + /** + * 获取相关GID + * + * @return 返回相关GID的字符串,如果未设置则返回null + */ public String getRelatedGid() { return mRelatedGid; } + /** + * 判断便签是否值得保存 + * + * @return 如果便签有备注则返回true,否则返回false + */ @Override public boolean isWorthSaving() { return getNotes() != null; } + /** + * 通过远程JSON对象设置便签内容 + * + * @param js 包含便签内容的JSONObject对象 + */ @Override public void setContentByRemoteJSON(JSONObject js) { + // 调用父类的方法处理JSON对象 super.setContentByRemoteJSON(js); + // 如果便签有备注 if (getNotes() != null) { try { + // 将备注转换为JSONObject对象 JSONObject metaInfo = new JSONObject(getNotes().trim()); + // 从metaInfo中获取相关GID mRelatedGid = metaInfo.getString(GTaskStringUtils.META_HEAD_GTASK_ID); } catch (JSONException e) { + // 如果获取GID失败,输出警告日志,并将相关GID设置为null Log.w(TAG, "failed to get related gid"); mRelatedGid = null; } } } + /** + * 通过本地JSON对象设置便签内容(不应调用此方法) + * + * @param js 包含便签内容的JSONObject对象 + * @throws IllegalAccessError 总是抛出此错误,因为此方法不应被调用 + */ @Override public void setContentByLocalJSON(JSONObject js) { - // this function should not be called + // 抛出错误,因为此方法不应被调用 throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called"); } + /** + * 从便签内容获取本地JSON对象(不应调用此方法) + * + * @return 不返回任何值,因为此方法不应被调用 + * @throws IllegalAccessError 总是抛出此错误,因为此方法不应被调用 + */ @Override public JSONObject getLocalJSONFromContent() { + // 抛出错误,因为此方法不应被调用 throw new IllegalAccessError("MetaData:getLocalJSONFromContent should not be called"); } + /** + * 获取同步操作(不应调用此方法) + * + * @param c 数据库游标 + * @return 不返回任何值,因为此方法不应被调用 + * @throws IllegalAccessError 总是抛出此错误,因为此方法不应被调用 + */ @Override public int getSyncAction(Cursor c) { + // 抛出错误,因为此方法不应被调用 throw new IllegalAccessError("MetaData:getSyncAction should not be called"); } - } diff --git a/Notesmaster/app/src/main/java/net/micode/notes/gtask/data/Node.java b/Notesmaster/app/src/main/java/net/micode/notes/gtask/data/Node.java index 63950e0..06adc92 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/gtask/data/Node.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/gtask/data/Node.java @@ -21,79 +21,108 @@ import android.database.Cursor; import org.json.JSONObject; public abstract class Node { - public static final int SYNC_ACTION_NONE = 0; - - public static final int SYNC_ACTION_ADD_REMOTE = 1; - - public static final int SYNC_ACTION_ADD_LOCAL = 2; - - public static final int SYNC_ACTION_DEL_REMOTE = 3; - - public static final int SYNC_ACTION_DEL_LOCAL = 4; - - public static final int SYNC_ACTION_UPDATE_REMOTE = 5; - - public static final int SYNC_ACTION_UPDATE_LOCAL = 6; - - public static final int SYNC_ACTION_UPDATE_CONFLICT = 7; - - public static final int SYNC_ACTION_ERROR = 8; - + // 同步动作的常量定义,表示不同的同步操作 + public static final int SYNC_ACTION_NONE = 0; // 无同步动作 + public static final int SYNC_ACTION_ADD_REMOTE = 1; // 远程添加 + public static final int SYNC_ACTION_ADD_LOCAL = 2; // 本地添加 + public static final int SYNC_ACTION_DEL_REMOTE = 3; // 远程删除 + public static final int SYNC_ACTION_DEL_LOCAL = 4; // 本地删除 + public static final int SYNC_ACTION_UPDATE_REMOTE = 5; // 远程更新 + public static final int SYNC_ACTION_UPDATE_LOCAL = 6; // 本地更新 + public static final int SYNC_ACTION_UPDATE_CONFLICT = 7; // 更新冲突 + public static final int SYNC_ACTION_ERROR = 8; // 同步错误 + + // 节点的GID(全局唯一标识符) private String mGid; + // 节点的名称 private String mName; + // 节点的最后修改时间 private long mLastModified; + // 节点是否被删除的标记 private boolean mDeleted; + // 构造方法,初始化节点的属性 public Node() { - mGid = null; - mName = ""; - mLastModified = 0; - mDeleted = false; + mGid = null; // GID初始化为null + mName = ""; // 名称初始化为空字符串 + mLastModified = 0; // 最后修改时间初始化为0 + mDeleted = false; // 删除标记初始化为false } + // 抽象方法,获取创建动作的JSON对象 + // @param actionId 同步动作的ID + // @return 包含创建动作的JSON对象 public abstract JSONObject getCreateAction(int actionId); + // 抽象方法,获取更新动作的JSON对象 + // @param actionId 同步动作的ID + // @return 包含更新动作的JSON对象 public abstract JSONObject getUpdateAction(int actionId); + // 抽象方法,通过远程JSON对象设置节点内容 + // @param js 包含节点内容的JSON对象 public abstract void setContentByRemoteJSON(JSONObject js); + // 抽象方法,通过本地JSON对象设置节点内容 + // @param js 包含节点内容的JSON对象 public abstract void setContentByLocalJSON(JSONObject js); + // 抽象方法,从节点内容获取本地JSON对象 + // @return 包含节点内容的本地JSON对象 public abstract JSONObject getLocalJSONFromContent(); + // 抽象方法,获取同步动作 + // @param c 数据库游标,用于获取节点的同步状态 + // @return 同步动作的ID public abstract int getSyncAction(Cursor c); + // 设置节点的GID + // @param gid 要设置的GID public void setGid(String gid) { this.mGid = gid; } + // 设置节点的名称 + // @param name 要设置的名称 public void setName(String name) { this.mName = name; } + // 设置节点的最后修改时间 + // @param lastModified 要设置的最后修改时间 public void setLastModified(long lastModified) { this.mLastModified = lastModified; } + // 设置节点的删除标记 + // @param deleted 要设置的删除标记 public void setDeleted(boolean deleted) { this.mDeleted = deleted; } + // 获取节点的GID + // @return 节点的GID public String getGid() { return this.mGid; } + // 获取节点的名称 + // @return 节点的名称 public String getName() { return this.mName; } + // 获取节点的最后修改时间 + // @return 节点的最后修改时间 public long getLastModified() { return this.mLastModified; } + // 获取节点的删除标记 + // @return 节点的删除标记 public boolean getDeleted() { return this.mDeleted; } diff --git a/Notesmaster/app/src/main/java/net/micode/notes/gtask/data/TaskList.java b/Notesmaster/app/src/main/java/net/micode/notes/gtask/data/TaskList.java index 4ea21c5..9a0d411 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/gtask/data/TaskList.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/gtask/data/TaskList.java @@ -31,41 +31,44 @@ import java.util.ArrayList; public class TaskList extends Node { - private static final String TAG = TaskList.class.getSimpleName(); + private static final String TAG = TaskList.class.getSimpleName(); // 获取当前类的简单名称作为日志标签 - private int mIndex; + private int mIndex; // 任务列表的索引 - private ArrayList mChildren; + private ArrayList mChildren; // 存储子任务的列表 + // 构造方法,初始化任务列表和索引 public TaskList() { super(); mChildren = new ArrayList(); mIndex = 1; } + // 生成创建任务的JSON对象 public JSONObject getCreateAction(int actionId) { JSONObject js = new JSONObject(); try { - // action_type + // 设置动作类型为创建 js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE); - // action_id + // 设置动作ID js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); - // index + // 设置索引 js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex); - // entity_delta + // 设置实体变化信息 JSONObject entity = new JSONObject(); - entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); - entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null"); + entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); // 任务列表名称 + entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null"); // 创建者ID,这里为空 entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE, - GTaskStringUtils.GTASK_JSON_TYPE_GROUP); + GTaskStringUtils.GTASK_JSON_TYPE_GROUP); // 实体类型为组 js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); } catch (JSONException e) { + // 捕获JSON异常,打印错误日志并抛出自定义异常 Log.e(TAG, e.toString()); e.printStackTrace(); throw new ActionFailureException("fail to generate tasklist-create jsonobject"); @@ -74,27 +77,29 @@ public class TaskList extends Node { return js; } + // 生成更新任务的JSON对象 public JSONObject getUpdateAction(int actionId) { JSONObject js = new JSONObject(); try { - // action_type + // 设置动作类型为更新 js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE); - // action_id + // 设置动作ID js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); - // id + // 设置任务列表ID js.put(GTaskStringUtils.GTASK_JSON_ID, getGid()); - // entity_delta + // 设置实体变化信息 JSONObject entity = new JSONObject(); - entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); - entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted()); + entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); // 任务列表名称 + entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted()); // 是否删除 js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); } catch (JSONException e) { + // 捕获JSON异常,打印错误日志并抛出自定义异常 Log.e(TAG, e.toString()); e.printStackTrace(); throw new ActionFailureException("fail to generate tasklist-update jsonobject"); @@ -103,25 +108,27 @@ public class TaskList extends Node { return js; } + // 根据远程JSON对象设置任务列表内容 public void setContentByRemoteJSON(JSONObject js) { if (js != null) { try { - // id + // 设置任务列表ID if (js.has(GTaskStringUtils.GTASK_JSON_ID)) { setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID)); } - // last_modified + // 设置最后修改时间 if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) { setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)); } - // name + // 设置任务列表名称 if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) { setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME)); } } catch (JSONException e) { + // 捕获JSON异常,打印错误日志并抛出自定义异常 Log.e(TAG, e.toString()); e.printStackTrace(); throw new ActionFailureException("fail to get tasklist content from jsonobject"); @@ -129,14 +136,16 @@ public class TaskList extends Node { } } + // 根据本地JSON对象设置任务列表内容 public void setContentByLocalJSON(JSONObject js) { if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)) { - Log.w(TAG, "setContentByLocalJSON: nothing is avaiable"); + Log.w(TAG, "setContentByLocalJSON: nothing is avaiable"); // 本地JSON对象无效或没有头部信息 } try { - JSONObject folder = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); + JSONObject folder = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); // 获取头部信息 + // 根据文件夹类型设置任务列表名称 if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) { String name = folder.getString(NoteColumns.SNIPPET); setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + name); @@ -147,16 +156,18 @@ public class TaskList extends Node { setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_CALL_NOTE); else - Log.e(TAG, "invalid system folder"); + Log.e(TAG, "invalid system folder"); // 无效的系统文件夹 } else { - Log.e(TAG, "error type"); + Log.e(TAG, "error type"); // 错误的文件夹类型 } } catch (JSONException e) { + // 捕获JSON异常,打印错误日志 Log.e(TAG, e.toString()); e.printStackTrace(); } } + // 获取任务列表的本地JSON对象 public JSONObject getLocalJSONFromContent() { try { JSONObject js = new JSONObject(); @@ -167,6 +178,7 @@ public class TaskList extends Node { folderName = folderName.substring(GTaskStringUtils.MIUI_FOLDER_PREFFIX.length(), folderName.length()); folder.put(NoteColumns.SNIPPET, folderName); + // 根据文件夹名称设置文件夹类型 if (folderName.equals(GTaskStringUtils.FOLDER_DEFAULT) || folderName.equals(GTaskStringUtils.FOLDER_CALL_NOTE)) folder.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); @@ -177,38 +189,41 @@ public class TaskList extends Node { return js; } catch (JSONException e) { + // 捕获JSON异常,打印错误日志并返回null Log.e(TAG, e.toString()); e.printStackTrace(); return null; } } + // 获取同步动作(根据游标数据判断) public int getSyncAction(Cursor c) { try { if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) { - // there is no local update + // 本地没有更新 if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { - // no update both side + // 远程和本地都没有更新 return SYNC_ACTION_NONE; } else { - // apply remote to local + // 应用远程更新到本地 return SYNC_ACTION_UPDATE_LOCAL; } } else { - // validate gtask id + // 验证任务列表ID if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) { - Log.e(TAG, "gtask id doesn't match"); + Log.e(TAG, "gtask id doesn't match"); // 任务列表ID不匹配 return SYNC_ACTION_ERROR; } if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { - // local modification only + // 只有本地更新 return SYNC_ACTION_UPDATE_REMOTE; } else { - // for folder conflicts, just apply local modification + // 文件夹冲突,只应用本地更新 return SYNC_ACTION_UPDATE_REMOTE; } } } catch (Exception e) { + // 捕获异常,打印错误日志并返回错误动作 Log.e(TAG, e.toString()); e.printStackTrace(); } @@ -216,10 +231,13 @@ public class TaskList extends Node { return SYNC_ACTION_ERROR; } + // 获取子任务数量 public int getChildTaskCount() { return mChildren.size(); } + // 添加子任务 + public boolean addChildTask(Task task) { boolean ret = false; if (task != null && !mChildren.contains(task)) { diff --git a/Notesmaster/app/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java b/Notesmaster/app/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java index 15504be..4391248 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java @@ -15,7 +15,7 @@ */ package net.micode.notes.gtask.exception; - +//行为失败后抛出异常 public class ActionFailureException extends RuntimeException { private static final long serialVersionUID = 4425249765923293627L; diff --git a/Notesmaster/app/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java b/Notesmaster/app/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java index b08cfb1..879ac69 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java @@ -15,7 +15,7 @@ */ package net.micode.notes.gtask.exception; - +//网络连接失败后抛出异常 public class NetworkFailureException extends Exception { private static final long serialVersionUID = 2107610287180234136L; diff --git a/Notesmaster/app/src/main/java/net/micode/notes/gtask/remote/GTaskSyncService.java b/Notesmaster/app/src/main/java/net/micode/notes/gtask/remote/GTaskSyncService.java index cca36f7..9095790 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/gtask/remote/GTaskSyncService.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/gtask/remote/GTaskSyncService.java @@ -23,29 +23,42 @@ import android.content.Intent; import android.os.Bundle; import android.os.IBinder; +// 定义一个服务类,用于处理Google任务的同步 public class GTaskSyncService extends Service { + // 定义一个字符串常量,表示同步操作的类型 public final static String ACTION_STRING_NAME = "sync_action_type"; + // 定义常量,表示开始同步的操作 public final static int ACTION_START_SYNC = 0; + // 定义常量,表示取消同步的操作 public final static int ACTION_CANCEL_SYNC = 1; + // 定义常量,表示无效的操作 public final static int ACTION_INVALID = 2; + // 定义一个广播的名称,用于通知同步状态的变化 public final static String GTASK_SERVICE_BROADCAST_NAME = "net.micode.notes.gtask.remote.gtask_sync_service"; + // 定义广播的附加数据键,表示是否正在同步 public final static String GTASK_SERVICE_BROADCAST_IS_SYNCING = "isSyncing"; + // 定义广播的附加数据键,表示同步的进度信息 public final static String GTASK_SERVICE_BROADCAST_PROGRESS_MSG = "progressMsg"; + // 定义一个异步任务,用于执行同步操作 private static GTaskASyncTask mSyncTask = null; + // 定义一个字符串,用于保存同步的进度信息 private static String mSyncProgress = ""; + // 开始同步的方法 private void startSync() { + // 如果当前没有正在执行的同步任务,则创建一个新的异步任务开始同步 if (mSyncTask == null) { mSyncTask = new GTaskASyncTask(this, new GTaskASyncTask.OnCompleteListener() { public void onComplete() { + // 同步完成后,将异步任务设置为null,发送一个空消息的广播,并停止服务 mSyncTask = null; sendBroadcast(""); stopSelf(); @@ -56,21 +69,27 @@ public class GTaskSyncService extends Service { } } + // 取消同步的方法 private void cancelSync() { + // 如果当前有正在执行的同步任务,则取消它 if (mSyncTask != null) { mSyncTask.cancelSync(); } } + // 服务创建时调用的方法 @Override public void onCreate() { mSyncTask = null; } + // 服务启动时调用的方法 @Override public int onStartCommand(Intent intent, int flags, int startId) { + // 从启动服务的Intent中获取附加数据 Bundle bundle = intent.getExtras(); if (bundle != null && bundle.containsKey(ACTION_STRING_NAME)) { + // 根据附加数据中的操作类型,执行相应的操作 switch (bundle.getInt(ACTION_STRING_NAME, ACTION_INVALID)) { case ACTION_START_SYNC: startSync(); @@ -81,22 +100,26 @@ public class GTaskSyncService extends Service { default: break; } - return START_STICKY; + return START_STICKY; // 服务被杀死后,系统会尝试重新创建并启动服务 } return super.onStartCommand(intent, flags, startId); } + // 系统内存不足时调用的方法 @Override public void onLowMemory() { + // 如果当前有正在执行的同步任务,则取消它 if (mSyncTask != null) { mSyncTask.cancelSync(); } } + // 服务绑定时调用的方法,此处直接返回null,表示不支持绑定 public IBinder onBind(Intent intent) { return null; } + // 发送广播的方法,通知同步状态的变化 public void sendBroadcast(String msg) { mSyncProgress = msg; Intent intent = new Intent(GTASK_SERVICE_BROADCAST_NAME); @@ -105,6 +128,7 @@ public class GTaskSyncService extends Service { sendBroadcast(intent); } + // 静态方法,用于从Activity中启动同步服务 public static void startSync(Activity activity) { GTaskManager.getInstance().setActivityContext(activity); Intent intent = new Intent(activity, GTaskSyncService.class); @@ -112,16 +136,19 @@ public class GTaskSyncService extends Service { activity.startService(intent); } + // 静态方法,用于取消同步服务 public static void cancelSync(Context context) { Intent intent = new Intent(context, GTaskSyncService.class); intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_CANCEL_SYNC); context.startService(intent); } + // 静态方法,用于判断当前是否有正在执行的同步任务 public static boolean isSyncing() { return mSyncTask != null; } + // 静态方法,用于获取同步的进度信息 public static String getProgressString() { return mSyncProgress; } diff --git a/Notesmaster/app/src/main/java/net/micode/notes/model/Note.java b/Notesmaster/app/src/main/java/net/micode/notes/model/Note.java index 6706cf6..c953a6a 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/model/Note.java +++ b/Notesmaster/app/src/main/java/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,19 @@ import net.micode.notes.data.Notes.TextNote; import java.util.ArrayList; - public class Note { - private ContentValues mNoteDiffValues; - private NoteData mNoteData; - private static final String TAG = "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 */ 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); @@ -56,72 +60,109 @@ public class Note { try { 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 如果同步成功则返回true,否则返回false + */ public boolean syncNote(Context context, long noteId) { if (noteId <= 0) { - throw new IllegalArgumentException("Wrong note id:" + noteId); + throw new IllegalArgumentException("错误的笔记ID:" + noteId); } if (!isLocalModified()) { return true; } - /** - * 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 - */ + // 更新笔记的修改状态和修改时间 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(); + // 如果笔记数据被修改且推送到ContentResolver失败,则返回false if (mNoteData.isLocalModified() && (mNoteData.pushIntoContentResolver(context, noteId) == null)) { return false; @@ -130,17 +171,19 @@ public class Note { return true; } + /** + * 笔记数据内部类 + */ private class NoteData { - private long mTextDataId; - - private ContentValues mTextDataValues; - - private long mCallDataId; - - private ContentValues mCallDataValues; - - private static final String TAG = "NoteData"; + 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,36 +191,64 @@ public class Note { mCallDataId = 0; } + /** + * 判断笔记数据是否在本地被修改 + * @return 如果被修改则返回true,否则返回false + */ boolean isLocalModified() { return mTextDataValues.size() > 0 || mCallDataValues.size() > 0; } + /** + * 设置文本数据ID + * @param id ID + */ 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 + */ 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 diff --git a/Notesmaster/app/src/main/java/net/micode/notes/model/WorkingNote.java b/Notesmaster/app/src/main/java/net/micode/notes/model/WorkingNote.java index be081e4..090f679 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/model/WorkingNote.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/model/WorkingNote.java @@ -33,35 +33,36 @@ import net.micode.notes.tool.ResourceParser.NoteBgResources; public class WorkingNote { - // Note for the working note + // 便签的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 mAlertDate; // 提醒日期 - private long mModifiedDate; + private long mModifiedDate; // 修改日期 - private int mBgColorId; + private int mBgColorId; // 背景颜色ID - private int mWidgetId; + private int mWidgetId; // 小部件ID - private int mWidgetType; + private int mWidgetType; // 小部件类型 - private long mFolderId; + private long mFolderId; // 文件夹ID - private Context mContext; + private Context mContext; // 上下文对象 - private static final String TAG = "WorkingNote"; + private static final String TAG = "WorkingNote"; // 日志标签 - private boolean mIsDeleted; + private boolean mIsDeleted; // 是否已删除 - private NoteSettingChangedListener mNoteSettingStatusListener; + private NoteSettingChangedListener mNoteSettingStatusListener; // 便签设置状态监听器 + // 数据列的投影,用于数据库查询 public static final String[] DATA_PROJECTION = new String[] { DataColumns.ID, DataColumns.CONTENT, @@ -72,6 +73,7 @@ public class WorkingNote { DataColumns.DATA4, }; + // 便签列的投影,用于数据库查询 public static final String[] NOTE_PROJECTION = new String[] { NoteColumns.PARENT_ID, NoteColumns.ALERTED_DATE, @@ -81,27 +83,21 @@ 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 + // 新建便签的构造函数 private WorkingNote(Context context, long folderId) { mContext = context; mAlertDate = 0; @@ -111,19 +107,20 @@ public class WorkingNote { mNoteId = 0; mIsDeleted = false; mMode = 0; - mWidgetType = Notes.TYPE_WIDGET_INVALIDE; + mWidgetType = Notes.TYPE_WIDGET_INVALIDE; // 无效的小部件类型 } - // Existing note construct + // 现有便签的构造函数 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, @@ -143,13 +140,14 @@ public class WorkingNote { Log.e(TAG, "No note with id:" + mNoteId); throw new IllegalArgumentException("Unable to find note with 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) + String.valueOf(mNoteId) }, null); if (cursor != null) { @@ -174,8 +172,9 @@ public class WorkingNote { } } + // 创建一个空的便签 public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId, - int widgetType, int defaultBgColorId) { + int widgetType, int defaultBgColorId) { WorkingNote note = new WorkingNote(context, folderId); note.setBgColorId(defaultBgColorId); note.setWidgetId(widgetId); @@ -183,10 +182,12 @@ public class WorkingNote { return note; } + // 加载一个已存在的便签 public static WorkingNote load(Context context, long id) { return new WorkingNote(context, id, 0); } + // 保存便签 public synchronized boolean saveNote() { if (isWorthSaving()) { if (!existInDatabase()) { @@ -198,9 +199,7 @@ public class WorkingNote { 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,10 +211,12 @@ public class WorkingNote { } } + // 检查便签是否存在于数据库中 public boolean existInDatabase() { return mNoteId > 0; } + // 检查便签是否值得保存 private boolean isWorthSaving() { if (mIsDeleted || (!existInDatabase() && TextUtils.isEmpty(mContent)) || (existInDatabase() && !mNote.isLocalModified())) { @@ -225,10 +226,12 @@ public class WorkingNote { } } + // 设置便签设置状态监听器 public void setOnSettingStatusChangedListener(NoteSettingChangedListener l) { mNoteSettingStatusListener = l; } + // 设置提醒日期 public void setAlertDate(long date, boolean set) { if (date != mAlertDate) { mAlertDate = date; @@ -238,6 +241,7 @@ public class WorkingNote { mNoteSettingStatusListener.onClockAlertChanged(date, set); } } + // 标记便签为已删除或未删除 public void markDeleted(boolean mark) { mIsDeleted = mark; diff --git a/Notesmaster/app/src/main/java/net/micode/notes/tool/DataUtils.java b/Notesmaster/app/src/main/java/net/micode/notes/tool/DataUtils.java index 2a14982..45e067d 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/tool/DataUtils.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/tool/DataUtils.java @@ -36,123 +36,208 @@ import java.util.HashSet; public class DataUtils { + // 常量标签,用于日志输出 public static final String TAG = "DataUtils"; + + /** + * 批量删除笔记 + * + * @param resolver 内容解析器,用于访问内容提供者 + * @param ids 要删除的笔记ID的集合 + * @return 删除成功返回true,否则返回false + */ public static boolean batchDeleteNotes(ContentResolver resolver, HashSet ids) { + // 如果ID集合为空,则直接返回true,表示删除成功(实际未进行删除操作) if (ids == null) { Log.d(TAG, "the ids is null"); return true; } + // 如果ID集合大小为0,也直接返回true if (ids.size() == 0) { Log.d(TAG, "no id is in the hashset"); return true; } + // 创建一个内容提供者操作列表 ArrayList operationList = new ArrayList(); + // 遍历ID集合,构建删除操作 for (long id : ids) { + // 如果是系统根文件夹,则跳过删除操作,并输出错误日志 if(id == Notes.ID_ROOT_FOLDER) { Log.e(TAG, "Don't delete system folder root"); continue; } + // 构建删除操作,并添加到操作列表 ContentProviderOperation.Builder builder = ContentProviderOperation .newDelete(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id)); operationList.add(builder.build()); } + try { + // 批量执行操作,并获取结果 ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); + // 如果结果为空或长度为0或第一个结果为空,则认为删除失败 if (results == null || results.length == 0 || results[0] == null) { Log.d(TAG, "delete notes failed, ids:" + ids.toString()); return false; } + // 删除成功 return true; } catch (RemoteException e) { + // 捕获远程异常,并输出错误日志 Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); } catch (OperationApplicationException e) { + // 捕获操作应用异常,并输出错误日志 Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); } + // 发生异常,返回false return false; } + /** + * 移动笔记到指定文件夹 + * + * @param resolver 内容解析器,用于访问内容提供者 + * @param id 要移动的笔记ID + * @param srcFolderId 源文件夹ID + * @param desFolderId 目标文件夹ID + */ public static void moveNoteToFoler(ContentResolver resolver, long id, long srcFolderId, long desFolderId) { + // 创建内容值对象,用于存储要更新的字段及其新值 ContentValues values = new ContentValues(); + // 设置目标文件夹ID values.put(NoteColumns.PARENT_ID, desFolderId); + // 设置源文件夹ID values.put(NoteColumns.ORIGIN_PARENT_ID, srcFolderId); + // 设置本地修改标志为1 values.put(NoteColumns.LOCAL_MODIFIED, 1); + // 更新笔记信息 resolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id), values, null, null); } - public static boolean batchMoveToFolder(ContentResolver resolver, HashSet ids, - long folderId) { + /** + * 批量移动笔记到指定文件夹 + * + * @param resolver 内容解析器,用于访问内容提供者 + * @param ids 要移动的笔记ID集合 + * @param folderId 目标文件夹ID + * @return 移动成功返回true,否则返回false + */ + public static boolean batchMoveToFolder(ContentResolver resolver, HashSet ids, long folderId) { + // 如果ID集合为空,则直接返回true,表示移动成功(实际未进行移动操作) if (ids == null) { Log.d(TAG, "the ids is null"); return true; } + // 创建一个内容提供者操作列表 ArrayList operationList = new ArrayList(); + // 遍历ID集合,构建更新操作 for (long id : ids) { ContentProviderOperation.Builder builder = ContentProviderOperation .newUpdate(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id)); + // 设置目标文件夹ID builder.withValue(NoteColumns.PARENT_ID, folderId); + // 设置本地修改标志为1 builder.withValue(NoteColumns.LOCAL_MODIFIED, 1); + // 将构建的操作添加到操作列表 operationList.add(builder.build()); } try { + // 批量执行操作,并获取结果 ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); + // 如果结果为空或长度为0或第一个结果为空,则认为移动失败 if (results == null || results.length == 0 || results[0] == null) { Log.d(TAG, "delete notes failed, ids:" + ids.toString()); return false; } + // 移动成功 return true; } catch (RemoteException e) { + // 捕获远程异常,并输出错误日志 Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); } catch (OperationApplicationException e) { + // 捕获操作应用异常,并输出错误日志 Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); } + // 发生异常,返回false return false; } /** - * Get the all folder count except system folders {@link Notes#TYPE_SYSTEM}} + * 获取除系统文件夹外的所有文件夹数量 + * + * @param resolver 内容解析器,用于访问内容提供者 + * @return 文件夹数量 */ public static int getUserFolderCount(ContentResolver resolver) { - Cursor cursor =resolver.query(Notes.CONTENT_NOTE_URI, + // 查询非系统文件夹且非垃圾文件夹的数量 + Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI, new String[] { "COUNT(*)" }, NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>?", new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER)}, null); int count = 0; - if(cursor != null) { - if(cursor.moveToFirst()) { + // 如果游标不为空 + if (cursor != null) { + // 移动到结果集的第一条记录 + if (cursor.moveToFirst()) { try { + // 获取文件夹数量 count = cursor.getInt(0); } catch (IndexOutOfBoundsException e) { + // 捕获索引越界异常,并输出错误日志 Log.e(TAG, "get folder count failed:" + e.toString()); } finally { + // 关闭游标 cursor.close(); } } } + // 返回文件夹数量 return count; } + /** + * 判断笔记是否在笔记数据库中可见 + * + * @param resolver 内容解析器,用于访问内容提供者 + * @param noteId 笔记ID + * @param type 笔记类型 + * @return 如果笔记存在且可见,则返回true,否则返回false + */ public static boolean visibleInNoteDatabase(ContentResolver resolver, long noteId, int type) { + // 查询指定ID和类型的笔记,且不在垃圾文件夹中 Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null, NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER, - new String [] {String.valueOf(type)}, + new String[] { String.valueOf(type) }, null); boolean exist = false; + // 如果游标不为空 if (cursor != null) { + // 如果查询结果的数量大于0,则表示笔记存在 if (cursor.getCount() > 0) { exist = true; } + // 关闭游标 cursor.close(); } + // 返回笔记是否存在 return exist; } + /** + * 判断笔记是否在笔记数据库中存在 + * + * @param resolver 内容解析器,用于访问内容提供者 + * @param noteId 笔记ID + * @return 如果笔记存在,则返回true,否则返回false + */ + public static boolean existInNoteDatabase(ContentResolver resolver, long noteId) { Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null, null, null, null); diff --git a/Notesmaster/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java b/Notesmaster/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java index ec6f819..1062ff8 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java @@ -32,23 +32,31 @@ import net.micode.notes.tool.ResourceParser; import net.micode.notes.ui.NoteEditActivity; import net.micode.notes.ui.NotesListActivity; +// 这是一个抽象类,用于提供笔记小部件的功能 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"; + // 当小部件被删除时调用此方法 @Override public void onDeleted(Context context, int[] appWidgetIds) { + // 创建一个ContentValues对象,用于更新数据库中的数据 ContentValues values = new ContentValues(); + // 将小部件ID设置为无效ID 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,7 +65,9 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider { } } + // 私有方法,用于获取指定小部件ID的笔记信息 private Cursor getNoteWidgetInfo(Context context, int widgetId) { + // 查询数据库,获取指定小部件ID且不在垃圾箱中的笔记信息 return context.getContentResolver().query(Notes.CONTENT_NOTE_URI, PROJECTION, NoteColumns.WIDGET_ID + "=? AND " + NoteColumns.PARENT_ID + "<>?", @@ -65,47 +75,61 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider { null); } + // 保护方法,用于更新小部件,不开启隐私模式 protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { update(context, appWidgetManager, appWidgetIds, false); } + // 私有方法,用于更新小部件,可选择是否开启隐私模式 private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds, - boolean privacyMode) { + boolean privacyMode) { + // 遍历所有需要更新的小部件ID for (int i = 0; i < appWidgetIds.length; i++) { + // 如果小部件ID有效 if (appWidgetIds[i] != AppWidgetManager.INVALID_APPWIDGET_ID) { + // 初始化背景颜色ID和摘要 int bgId = ResourceParser.getDefaultBgId(context); String snippet = ""; + // 创建一个指向NoteEditActivity的Intent,用于点击小部件时跳转 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()); + // 获取指定小部件ID的笔记信息 Cursor c = getNoteWidgetInfo(context, appWidgetIds[i]); + // 如果获取到笔记信息 if (c != null && c.moveToFirst()) { + // 如果有多条笔记信息使用相同的小部件ID,记录错误日志并返回 if (c.getCount() > 1) { Log.e(TAG, "Multiple message with same widget id:" + appWidgetIds[i]); c.close(); return; } + // 获取摘要和背景颜色ID,并设置到Intent中 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 { + // 如果没有获取到笔记信息,设置默认摘要,并设置Intent动作为插入或编辑 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)); + // 将背景颜色ID设置到Intent中 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, @@ -118,15 +142,20 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider { PendingIntent.FLAG_UPDATE_CURRENT); } + // 设置小部件的点击行为 rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent); + // 更新小部件的UI appWidgetManager.updateAppWidget(appWidgetIds[i], rv); } } } + // 抽象方法,由子类实现,用于获取背景资源ID protected abstract int getBgResourceId(int bgId); + // 抽象方法,由子类实现,用于获取布局ID protected abstract int getLayoutId(); + // 抽象方法,由子类实现,用于获取小部件类型 protected abstract int getWidgetType(); } diff --git a/Notesmaster/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java b/Notesmaster/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java index adcb2f7..c00ec2e 100644 --- a/Notesmaster/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java +++ b/Notesmaster/app/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java @@ -24,24 +24,34 @@ import net.micode.notes.data.Notes; import net.micode.notes.tool.ResourceParser; +// 这是一个名为NoteWidgetProvider_2x的类,它继承自NoteWidgetProvider类 public class NoteWidgetProvider_2x extends NoteWidgetProvider { + + // 重写父类的onUpdate方法,用于更新小部件 @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + // 调用父类的update方法来进行实际的更新操作,传递上下文、小部件管理器和小部件ID数组 super.update(context, appWidgetManager, appWidgetIds); } + // 重写父类的getLayoutId方法,用于获取小部件的布局ID @Override protected int getLayoutId() { + // 返回widget_2x布局资源的ID return R.layout.widget_2x; } + // 重写父类的getBgResourceId方法,用于根据背景ID获取对应的资源ID @Override protected int getBgResourceId(int bgId) { + // 使用ResourceParser.WidgetBgResources的getWidget2xBgResource方法,根据传入的背景ID获取对应的2x小部件背景资源ID return ResourceParser.WidgetBgResources.getWidget2xBgResource(bgId); } + // 重写父类的getWidgetType方法,用于获取小部件的类型 @Override protected int getWidgetType() { + // 返回表示2x类型小部件的常量值 return Notes.TYPE_WIDGET_2X; } -} +} \ No newline at end of file