From 2e41e10f8d33a93179dc678be404d01aa259b381 Mon Sep 17 00:00:00 2001 From: lengjiao <2327282532@qq.com> Date: Fri, 2 Jun 2023 08:47:11 +0800 Subject: [PATCH] =?UTF-8?q?BackupUtils.java=E4=BB=A3=E7=A0=81=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/tool/BackupUtils.java | 38 +++++++++++++++++++------------- notes/tool/DataUtils.java | 25 ++++++++++++--------- notes/tool/GTaskStringUtils.java | 4 ++-- notes/tool/ResourceParser.java | 16 ++++++++++++++ 4 files changed, 55 insertions(+), 28 deletions(-) diff --git a/notes/tool/BackupUtils.java b/notes/tool/BackupUtils.java index 39f6ec4..18caa27 100644 --- a/notes/tool/BackupUtils.java +++ b/notes/tool/BackupUtils.java @@ -41,8 +41,13 @@ public class BackupUtils { // Singleton stuff private static BackupUtils sInstance; + /* + 功能描述:ynchronized 关键字,代表这个方法加锁,相当于不管哪一个线程(例如线程A) + 实现过程:运行到这个方法时,都要检查有没有其它线程B(或者C、 D等)正在用这个方法(或者该类的其他同步方法),有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,锁定调用者,然后直接运行。 + 它包括两种用法:synchronized 方法和 synchronized 块。 + */ public static synchronized BackupUtils getInstance(Context context) { - if (sInstance == null) { + if (sInstance == null) {//如果当前备份不存在,则新声明一个 sInstance = new BackupUtils(context); } return sInstance; @@ -65,11 +70,12 @@ public class BackupUtils { private TextExport mTextExport; + //初始化函数 private BackupUtils(Context context) { mTextExport = new TextExport(context); } - private static boolean externalStorageAvailable() { + private static boolean externalStorageAvailable() {//外部存储功能是否可用 return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); } @@ -132,6 +138,7 @@ public class BackupUtils { mFileDirectory = ""; } + //获取文本的组成部分 private String getFormat(int id) { return TEXT_FORMAT[id]; } @@ -140,7 +147,7 @@ public class BackupUtils { * Export the folder identified by folder id to text */ private void exportFolderToText(String folderId, PrintStream ps) { - // Query notes belong to this folder + // Query notes belong to this folder 通过查询parent id是文件夹id的note来选出制定ID文件夹下的Note Cursor notesCursor = mContext.getContentResolver().query(Notes.CONTENT_NOTE_URI, NOTE_PROJECTION, NoteColumns.PARENT_ID + "=?", new String[] { folderId @@ -149,13 +156,13 @@ public class BackupUtils { if (notesCursor != null) { if (notesCursor.moveToFirst()) { do { - // Print note's last modified date + // Print note's last modified date ps里面保存有这份note的日期 ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format( mContext.getString(R.string.format_datetime_mdhm), notesCursor.getLong(NOTE_COLUMN_MODIFIED_DATE)))); // Query data belong to this note String noteId = notesCursor.getString(NOTE_COLUMN_ID); - exportNoteToText(noteId, ps); + exportNoteToText(noteId, ps);//将文件导出到text } while (notesCursor.moveToNext()); } notesCursor.close(); @@ -171,7 +178,7 @@ public class BackupUtils { noteId }, null); - if (dataCursor != null) { + if (dataCursor != null) {//利用光标来扫描内容,区别为callnote和note两种,靠ps.printline输出 if (dataCursor.moveToFirst()) { do { String mimeType = dataCursor.getString(DATA_COLUMN_MIME_TYPE); @@ -181,7 +188,7 @@ public class BackupUtils { long callDate = dataCursor.getLong(DATA_COLUMN_CALL_DATE); String location = dataCursor.getString(DATA_COLUMN_CONTENT); - if (!TextUtils.isEmpty(phoneNumber)) { + if (!TextUtils.isEmpty(phoneNumber)) {//判断是否为空字符 ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), phoneNumber)); } @@ -218,7 +225,7 @@ public class BackupUtils { /** * Note will be exported as text which is user readable */ - public int exportToText() { + public int exportToText() {//总函数,调用上面的exportFolder和exportNote if (!externalStorageAvailable()) { Log.d(TAG, "Media was not mounted"); return STATE_SD_CARD_UNMOUONTED; @@ -229,7 +236,7 @@ public class BackupUtils { Log.e(TAG, "get print stream error"); return STATE_SYSTEM_ERROR; } - // First export folder and its notes + // First export folder and its notes 导出文件夹,就是导出里面包含的便签 Cursor folderCursor = mContext.getContentResolver().query( Notes.CONTENT_NOTE_URI, NOTE_PROJECTION, @@ -257,7 +264,7 @@ public class BackupUtils { folderCursor.close(); } - // Export notes in root's folder + // Export notes in root's folder 将根目录里的便签导出(由于不属于任何文件夹,因此无法通过文件夹导出来实现这一部分便签的导出) Cursor noteCursor = mContext.getContentResolver().query( Notes.CONTENT_NOTE_URI, NOTE_PROJECTION, @@ -298,6 +305,7 @@ public class BackupUtils { try { FileOutputStream fos = new FileOutputStream(file); ps = new PrintStream(fos); + //将ps输出流输出到特定的文件,目的就是导出到文件,而不是直接输出 } catch (FileNotFoundException e) { e.printStackTrace(); return null; @@ -314,16 +322,16 @@ public class BackupUtils { */ private static File generateFileMountedOnSDcard(Context context, int filePathResId, int fileNameFormatResId) { StringBuilder sb = new StringBuilder(); - sb.append(Environment.getExternalStorageDirectory()); - sb.append(context.getString(filePathResId)); - File filedir = new File(sb.toString()); + sb.append(Environment.getExternalStorageDirectory());//外部(SD卡)的存储路径 + sb.append(context.getString(filePathResId));//文件的存储路径 + File filedir = new File(sb.toString());//filedir应该就是用来存储路径信息 sb.append(context.getString( fileNameFormatResId, DateFormat.format(context.getString(R.string.format_date_ymd), System.currentTimeMillis()))); File file = new File(sb.toString()); - try { + try {//如果这些文件不存在,则新建 if (!filedir.exists()) { filedir.mkdir(); } @@ -336,7 +344,7 @@ public class BackupUtils { } catch (IOException e) { e.printStackTrace(); } - +// try catch 异常处理 return null; } } diff --git a/notes/tool/DataUtils.java b/notes/tool/DataUtils.java index 2a14982..f3b98e7 100644 --- a/notes/tool/DataUtils.java +++ b/notes/tool/DataUtils.java @@ -52,13 +52,14 @@ public class DataUtils { 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); + //数据库事务,数据库事务是由一组数据库操作序列组成,事务作为一个整体被执行 if (results == null || results.length == 0 || results[0] == null) { Log.d(TAG, "delete notes failed, ids:" + ids.toString()); return false; @@ -94,7 +95,7 @@ public class DataUtils { builder.withValue(NoteColumns.PARENT_ID, folderId); builder.withValue(NoteColumns.LOCAL_MODIFIED, 1); operationList.add(builder.build()); - } + }//将ids里包含的每一列的数据逐次加入到operationList中,等待最后的批量处理 try { ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); @@ -119,7 +120,7 @@ public class DataUtils { new String[] { "COUNT(*)" }, NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>?", new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER)}, - null); + null); //筛选条件:源文件不为trash folder int count = 0; if(cursor != null) { @@ -141,11 +142,11 @@ public class DataUtils { null, NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER, new String [] {String.valueOf(type)}, - null); + null);//查询条件:type符合,且不属于垃圾文件夹 boolean exist = false; if (cursor != null) { - if (cursor.getCount() > 0) { + if (cursor.getCount() > 0) {//用getcount函数判断cursor是否为空 exist = true; } cursor.close(); @@ -187,6 +188,7 @@ public class DataUtils { " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + " AND " + NoteColumns.SNIPPET + "=?", new String[] { name }, null); + //通过名字查询文件是否存在 boolean exist = false; if(cursor != null) { if(cursor.getCount() > 0) { @@ -202,7 +204,7 @@ public class DataUtils { new String[] { NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE }, NoteColumns.PARENT_ID + "=?", new String[] { String.valueOf(folderId) }, - null); + null);//查询条件:父ID是传入的folderId; HashSet set = null; if (c != null) { @@ -211,13 +213,13 @@ public class DataUtils { do { try { AppWidgetAttribute widget = new AppWidgetAttribute(); - widget.widgetId = c.getInt(0); - widget.widgetType = c.getInt(1); + widget.widgetId = c.getInt(0);//0对应的NoteColumns.WIDGET_ID + widget.widgetType = c.getInt(1);//1对应的NoteColumns.WIDGET_TYPE set.add(widget); } catch (IndexOutOfBoundsException e) { Log.e(TAG, e.toString()); } - } while (c.moveToNext()); + } while (c.moveToNext());//查询下一条 } c.close(); } @@ -250,7 +252,7 @@ public class DataUtils { + CallNote.PHONE_NUMBER + ",?)", new String [] { String.valueOf(callDate), CallNote.CONTENT_ITEM_TYPE, phoneNumber }, null); - + //通过数据库操作,查询条件是(callDate和phoneNumber匹配传入参数的值) if (cursor != null) { if (cursor.moveToFirst()) { try { @@ -269,7 +271,7 @@ public class DataUtils { new String [] { NoteColumns.SNIPPET }, NoteColumns.ID + "=?", new String [] { String.valueOf(noteId)}, - null); + null);//查询条件:noteId if (cursor != null) { String snippet = ""; @@ -282,6 +284,7 @@ public class DataUtils { throw new IllegalArgumentException("Note is not found with id: " + noteId); } + //对字符串进行格式处理,将字符串两头的空格去掉,同时将换行符去掉 public static String getFormattedSnippet(String snippet) { if (snippet != null) { snippet = snippet.trim(); diff --git a/notes/tool/GTaskStringUtils.java b/notes/tool/GTaskStringUtils.java index 666b729..0f1ffa7 100644 --- a/notes/tool/GTaskStringUtils.java +++ b/notes/tool/GTaskStringUtils.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +//简介:定义了很多的静态字符串,目的就是为了提供jsonObject中相应字符串的"key"。把这些静态的定义单独写到了一个类里面,这是非常好的编程规范 package net.micode.notes.tool; - +//这个类就是定义了一堆static string,实际就是为jsonObject提供Key,把这些定义全部写到一个类里,方便查看管理,是一个非常好的编程习惯 public class GTaskStringUtils { public final static String GTASK_JSON_ACTION_ID = "action_id"; diff --git a/notes/tool/ResourceParser.java b/notes/tool/ResourceParser.java index 1ad3ad6..d6d065a 100644 --- a/notes/tool/ResourceParser.java +++ b/notes/tool/ResourceParser.java @@ -15,6 +15,20 @@ */ package net.micode.notes.tool; +/*简介:字面意义是资源分析器,实际上就是获取资源并且在程序中使用,比如颜色图片等 + * 实现方法:主要利用R.java这个类,其中包括 + * R.id 组件资源引用 + * R.drawable 图片资源 (被使用) + * R.layout 布局资源 + * R.menu 菜单资源 + * R.String 文字资源 + * R.style 主题资源 (被使用) + * 在按顺序设置好相应的id后,就可以编写简单的getXXX函数获取需要的资源 + * + * 特殊的变量 : + * @BG_DEFAULT_COLOR 默认背景颜色(黄) + * BG_DEFAULT_FONT_SIZE 默认文本大小(中) + */ import android.content.Context; import android.preference.PreferenceManager; @@ -65,6 +79,7 @@ public class ResourceParser { } } + //直接获取默认的背景颜色。看不太懂,这个PREFERENCE_SET_BG_COLOR_KEY是个final string,也就是说getBoolean肯定执行else public static int getDefaultBgId(Context context) { if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean( NotesPreferenceActivity.PREFERENCE_SET_BG_COLOR_KEY, false)) { @@ -162,6 +177,7 @@ public class ResourceParser { R.style.TextAppearanceSuper }; + //这里有一个容错的函数,防止输入的id大于资源总量,若如此,则自动返回默认的设置结果 public static int getTexAppearanceResource(int id) { /** * HACKME: Fix bug of store the resource id in shared preference.