diff --git a/src/Notes-master/gradle script/.gradle/8.9/checksums/checksums.lock b/src/Notes-master/gradle script/.gradle/8.9/checksums/checksums.lock deleted file mode 100644 index 46894bf..0000000 Binary files a/src/Notes-master/gradle script/.gradle/8.9/checksums/checksums.lock and /dev/null differ diff --git a/src/Notes-master/gradle script/.gradle/8.9/dependencies-accessors/gc.properties b/src/Notes-master/gradle script/.gradle/8.9/dependencies-accessors/gc.properties deleted file mode 100644 index e69de29..0000000 diff --git a/src/Notes-master/gradle script/.gradle/8.9/executionHistory/executionHistory.lock b/src/Notes-master/gradle script/.gradle/8.9/executionHistory/executionHistory.lock deleted file mode 100644 index 34dc97a..0000000 Binary files a/src/Notes-master/gradle script/.gradle/8.9/executionHistory/executionHistory.lock and /dev/null differ diff --git a/src/Notes-master/gradle script/.gradle/8.9/fileChanges/last-build.bin b/src/Notes-master/gradle script/.gradle/8.9/fileChanges/last-build.bin deleted file mode 100644 index f76dd23..0000000 Binary files a/src/Notes-master/gradle script/.gradle/8.9/fileChanges/last-build.bin and /dev/null differ diff --git a/src/Notes-master/gradle script/.gradle/8.9/fileHashes/fileHashes.lock b/src/Notes-master/gradle script/.gradle/8.9/fileHashes/fileHashes.lock deleted file mode 100644 index a15b41f..0000000 Binary files a/src/Notes-master/gradle script/.gradle/8.9/fileHashes/fileHashes.lock and /dev/null differ diff --git a/src/Notes-master/gradle script/.gradle/8.9/gc.properties b/src/Notes-master/gradle script/.gradle/8.9/gc.properties deleted file mode 100644 index e69de29..0000000 diff --git a/src/Notes-master/gradle script/.gradle/9.2.0/checksums/checksums.lock b/src/Notes-master/gradle script/.gradle/9.2.0/checksums/checksums.lock deleted file mode 100644 index 0480091..0000000 Binary files a/src/Notes-master/gradle script/.gradle/9.2.0/checksums/checksums.lock and /dev/null differ diff --git a/src/Notes-master/gradle script/.gradle/9.2.0/fileChanges/last-build.bin b/src/Notes-master/gradle script/.gradle/9.2.0/fileChanges/last-build.bin deleted file mode 100644 index f76dd23..0000000 Binary files a/src/Notes-master/gradle script/.gradle/9.2.0/fileChanges/last-build.bin and /dev/null differ diff --git a/src/Notes-master/gradle script/.gradle/9.2.0/fileHashes/fileHashes.bin b/src/Notes-master/gradle script/.gradle/9.2.0/fileHashes/fileHashes.bin deleted file mode 100644 index 42cfb00..0000000 Binary files a/src/Notes-master/gradle script/.gradle/9.2.0/fileHashes/fileHashes.bin and /dev/null differ diff --git a/src/Notes-master/gradle script/.gradle/9.2.0/fileHashes/fileHashes.lock b/src/Notes-master/gradle script/.gradle/9.2.0/fileHashes/fileHashes.lock deleted file mode 100644 index f4b0cf6..0000000 Binary files a/src/Notes-master/gradle script/.gradle/9.2.0/fileHashes/fileHashes.lock and /dev/null differ diff --git a/src/Notes-master/gradle script/.gradle/9.2.0/gc.properties b/src/Notes-master/gradle script/.gradle/9.2.0/gc.properties deleted file mode 100644 index e69de29..0000000 diff --git a/src/Notes-master/gradle script/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/src/Notes-master/gradle script/.gradle/buildOutputCleanup/buildOutputCleanup.lock deleted file mode 100644 index 04a527e..0000000 Binary files a/src/Notes-master/gradle script/.gradle/buildOutputCleanup/buildOutputCleanup.lock and /dev/null differ diff --git a/src/Notes-master/gradle script/.gradle/buildOutputCleanup/cache.properties b/src/Notes-master/gradle script/.gradle/buildOutputCleanup/cache.properties deleted file mode 100644 index 1ade9e1..0000000 --- a/src/Notes-master/gradle script/.gradle/buildOutputCleanup/cache.properties +++ /dev/null @@ -1,2 +0,0 @@ -#Wed Jan 28 09:46:21 CST 2026 -gradle.version=9.2.0 diff --git a/src/Notes-master/gradle script/.gradle/vcs-1/gc.properties b/src/Notes-master/gradle script/.gradle/vcs-1/gc.properties deleted file mode 100644 index e69de29..0000000 diff --git a/src/Notes-master/gradle script/build/reports/problems/problems-report.html b/src/Notes-master/gradle script/build/reports/problems/problems-report.html deleted file mode 100644 index 381ccca..0000000 --- a/src/Notes-master/gradle script/build/reports/problems/problems-report.html +++ /dev/null @@ -1,659 +0,0 @@ - - - - - - - - - - - - - Gradle Configuration Cache - - - -
- -
- Loading... -
- - - - - - diff --git a/src/Notes-master/res/drawable/drawable-hdpi/bg_btn_insert_photo.png b/src/Notes-master/res/drawable/drawable-hdpi/bg_btn_insert_photo.png new file mode 100644 index 0000000..f8a0bfb Binary files /dev/null and b/src/Notes-master/res/drawable/drawable-hdpi/bg_btn_insert_photo.png differ diff --git a/src/Notes-master/res/drawable/drawable-hdpi/bg_btn_voice_transfomer.png b/src/Notes-master/res/drawable/drawable-hdpi/bg_btn_voice_transfomer.png new file mode 100644 index 0000000..632a08e Binary files /dev/null and b/src/Notes-master/res/drawable/drawable-hdpi/bg_btn_voice_transfomer.png differ diff --git a/src/Notes-master/src/net/micode/notes/tool/ResourceParser.java b/src/Notes-master/src/net/micode/notes/tool/ResourceParser.java index 14bae33..72d9b47 100644 --- a/src/Notes-master/src/net/micode/notes/tool/ResourceParser.java +++ b/src/Notes-master/src/net/micode/notes/tool/ResourceParser.java @@ -118,6 +118,9 @@ public class ResourceParser { * @return 背景资源ID */ public static int getNoteBgResource(int id) { + if (id < 0 || id >= BG_EDIT_RESOURCES.length) { + return BG_EDIT_RESOURCES[BG_DEFAULT_COLOR]; + } return BG_EDIT_RESOURCES[id]; } @@ -127,6 +130,9 @@ public class ResourceParser { * @return 标题栏背景资源ID */ public static int getNoteTitleBgResource(int id) { + if (id < 0 || id >= BG_EDIT_TITLE_RESOURCES.length) { + return BG_EDIT_TITLE_RESOURCES[BG_DEFAULT_COLOR]; + } return BG_EDIT_TITLE_RESOURCES[id]; } } @@ -205,6 +211,9 @@ public class ResourceParser { * @return 首项背景资源ID */ public static int getNoteBgFirstRes(int id) { + if (id < 0 || id >= BG_FIRST_RESOURCES.length) { + return BG_FIRST_RESOURCES[BG_DEFAULT_COLOR]; + } return BG_FIRST_RESOURCES[id]; } @@ -214,6 +223,9 @@ public class ResourceParser { * @return 末项背景资源ID */ public static int getNoteBgLastRes(int id) { + if (id < 0 || id >= BG_LAST_RESOURCES.length) { + return BG_LAST_RESOURCES[BG_DEFAULT_COLOR]; + } return BG_LAST_RESOURCES[id]; } @@ -223,6 +235,9 @@ public class ResourceParser { * @return 单项背景资源ID */ public static int getNoteBgSingleRes(int id) { + if (id < 0 || id >= BG_SINGLE_RESOURCES.length) { + return BG_SINGLE_RESOURCES[BG_DEFAULT_COLOR]; + } return BG_SINGLE_RESOURCES[id]; } @@ -232,6 +247,9 @@ public class ResourceParser { * @return 中间项背景资源ID */ public static int getNoteBgNormalRes(int id) { + if (id < 0 || id >= BG_NORMAL_RESOURCES.length) { + return BG_NORMAL_RESOURCES[BG_DEFAULT_COLOR]; + } return BG_NORMAL_RESOURCES[id]; } @@ -267,6 +285,9 @@ public class ResourceParser { * @return 2x小部件背景资源ID */ public static int getWidget2xBgResource(int id) { + if (id < 0 || id >= BG_2X_RESOURCES.length) { + return BG_2X_RESOURCES[BG_DEFAULT_COLOR]; + } return BG_2X_RESOURCES[id]; } @@ -288,6 +309,9 @@ public class ResourceParser { * @return 4x小部件背景资源ID */ public static int getWidget4xBgResource(int id) { + if (id < 0 || id >= BG_4X_RESOURCES.length) { + return BG_4X_RESOURCES[BG_DEFAULT_COLOR]; + } return BG_4X_RESOURCES[id]; } } diff --git a/src/Notes-master/src/net/micode/notes/ui/NoteEditActivity.java b/src/Notes-master/src/net/micode/notes/ui/NoteEditActivity.java index a56fa24..39b0da4 100644 --- a/src/Notes-master/src/net/micode/notes/ui/NoteEditActivity.java +++ b/src/Notes-master/src/net/micode/notes/ui/NoteEditActivity.java @@ -234,6 +234,14 @@ public class NoteEditActivity extends Activity implements OnClickListener, private EditText mTagInput; // 标签输入框 private Button mAddTagButton; // 添加标签按钮 private ArrayList mTagsList; // 标签列表 + + // 视图缓存,减少对象创建 + private ArrayList mViewCache = new ArrayList<>(); + private static final int MAX_CACHE_SIZE = 10; // 最大缓存大小 + + // 延迟保存相关 + private android.os.Handler mSaveNoteHandler = new android.os.Handler(); + private TextView mSaveHint; // 保存成功提示视图 // 搜索历史相关 private static final String PREFERENCE_SEARCH_HISTORY = "search_history"; // 搜索历史偏好设置键 @@ -1337,58 +1345,114 @@ public class NoteEditActivity extends Activity implements OnClickListener, long startTime = System.currentTimeMillis(); Log.d(TAG, "switchToListMode started, text length: " + (text != null ? text.length() : 0)); - // 处理null文本,避免空指针异常(OMO) + // 处理null文本,避免空指针异常 final String processedText = text != null ? text : ""; - // 预处理:在后台线程中分割文本和准备数据 - new Thread(new Runnable() { - @Override - public void run() { - final String[] items = processedText.split("\n"); // 按行分割文本 - Log.d(TAG, "switchToListMode: split into " + items.length + " items"); - - // 切换回主线程更新UI - runOnUiThread(new Runnable() { - @Override - public void run() { - // 批量创建和添加视图,减少布局重绘 - mEditTextList.removeAllViews(); // 清空编辑文本列表 - - int index = 0; - View lastItem = null; - - // 先创建所有视图 - ArrayList viewsToAdd = new ArrayList<>(); - for (String item : items) { - if(!TextUtils.isEmpty(item)) { - View listItem = getListItem(item, index); - viewsToAdd.add(listItem); - index++; - } - } - - // 添加最后一个空列表项 - lastItem = getListItem("", index); - viewsToAdd.add(lastItem); - - // 一次性添加所有视图到容器 - for (View view : viewsToAdd) { - mEditTextList.addView(view); + // 优化:直接在主线程处理,减少线程切换开销 + // 对于大多数情况,文本分割和视图创建的开销很小 + // 只有在文本特别长时才需要考虑后台线程 + if (processedText.length() > 10000) { + // 对于长文本,使用后台线程 + new Thread(new Runnable() { + @Override + public void run() { + final String[] items = processTextForListMode(processedText); + Log.d(TAG, "switchToListMode: split into " + items.length + " items"); + + runOnUiThread(new Runnable() { + @Override + public void run() { + createListModeViews(items); + long endTime = System.currentTimeMillis(); + Log.d(TAG, "switchToListMode completed in " + (endTime - startTime) + "ms"); } + }); + } + }).start(); + } else { + // 对于短文本,直接在主线程处理 + final String[] items = processTextForListMode(processedText); + Log.d(TAG, "switchToListMode: split into " + items.length + " items"); + createListModeViews(items); + long endTime = System.currentTimeMillis(); + Log.d(TAG, "switchToListMode completed in " + (endTime - startTime) + "ms"); + } + } - // 设置焦点 - ListItemViewHolder holder = (ListItemViewHolder) lastItem.getTag(); - holder.etEditText.requestFocus(); + /** + * 处理文本,为清单模式做准备 + * @param text 原始文本 + * @return 处理后的文本数组 + */ + private String[] processTextForListMode(String text) { + // 移除HTML标签,只保留纯文本 + String plainText = removeHtmlTags(text); + // 按行分割 + return plainText.split("\n"); + } - mNoteEditor.setVisibility(View.GONE); // 隐藏普通编辑器 - mEditTextList.setVisibility(View.VISIBLE); // 显示清单编辑器 + /** + * 移除HTML标签,只保留纯文本 + * @param html HTML文本 + * @return 纯文本 + */ + private String removeHtmlTags(String html) { + // 简单的HTML标签移除,适合大多数情况 + if (TextUtils.isEmpty(html)) { + return ""; + } + // 移除常见HTML标签 + String plainText = html.replaceAll("<[^>]+>", ""); + // 处理HTML实体 + plainText = plainText.replaceAll(" ", " "); + plainText = plainText.replaceAll("<", "<"); + plainText = plainText.replaceAll(">", ">"); + plainText = plainText.replaceAll("&", "&"); + return plainText; + } - long endTime = System.currentTimeMillis(); - Log.d(TAG, "switchToListMode completed in " + (endTime - startTime) + "ms"); - } - }); + /** + * 创建清单模式的视图 + * @param items 文本项数组 + */ + private void createListModeViews(String[] items) { + // 回收现有视图到缓存,减少内存占用 + int childCount = mEditTextList.getChildCount(); + for (int i = childCount - 1; i >= 0; i--) { + View view = mEditTextList.getChildAt(i); + recycleView(view); + } + // 清空编辑文本列表 + mEditTextList.removeAllViews(); + + // 批量创建视图 + ArrayList viewsToAdd = new ArrayList<>(); + int index = 0; + + for (String item : items) { + if (!TextUtils.isEmpty(item)) { + View listItem = getListItem(item, index); + viewsToAdd.add(listItem); + index++; } - }).start(); + } + + // 添加最后一个空列表项 + View lastItem = getListItem("", index); + viewsToAdd.add(lastItem); + + // 批量添加视图,减少布局重绘 + for (View view : viewsToAdd) { + mEditTextList.addView(view); + } + + // 设置焦点 + ListItemViewHolder holder = (ListItemViewHolder) lastItem.getTag(); + holder.etEditText.requestFocus(); + + // 显示/隐藏编辑器 + mNoteEditor.setVisibility(View.GONE); + mEditTextList.setVisibility(View.VISIBLE); } /** @@ -1446,13 +1510,22 @@ public class NoteEditActivity extends Activity implements OnClickListener, * @return 列表项视图 */ private View getListItem(String item, int index) { - View view = LayoutInflater.from(this).inflate(R.layout.note_edit_list_item, null); + // 优先从缓存中获取视图,减少布局inflate开销 + View view = null; + if (!mViewCache.isEmpty()) { + view = mViewCache.remove(0); + } else { + view = LayoutInflater.from(this).inflate(R.layout.note_edit_list_item, null); + } // 创建并缓存ViewHolder - ListItemViewHolder holder = new ListItemViewHolder(); - holder.etEditText = (NoteEditText) view.findViewById(R.id.et_edit_text); - holder.cbEditItem = (CheckBox) view.findViewById(R.id.cb_edit_item); - view.setTag(holder); + ListItemViewHolder holder = (ListItemViewHolder) view.getTag(); + if (holder == null) { + holder = new ListItemViewHolder(); + holder.etEditText = (NoteEditText) view.findViewById(R.id.et_edit_text); + holder.cbEditItem = (CheckBox) view.findViewById(R.id.cb_edit_item); + view.setTag(holder); + } final NoteEditText edit = holder.etEditText; edit.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId)); @@ -1462,10 +1535,20 @@ public class NoteEditActivity extends Activity implements OnClickListener, cb.setOnCheckedChangeListener(new OnCheckedChangeListener() { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { + // 添加删除线和灰色效果 edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); + edit.setTextColor(Color.GRAY); + // 将已完成项目移到列表底部 + moveCompletedItemToBottom(edit); } else { + // 移除删除线和恢复颜色 edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG); + edit.setTextColor(Color.BLACK); + // 将未完成项目移到列表顶部 + moveUncompletedItemToTop(edit); } + // 延迟保存,避免频繁操作导致卡顿 + saveNoteDelayed(); } }); @@ -1473,13 +1556,120 @@ public class NoteEditActivity extends Activity implements OnClickListener, if (item.startsWith(TAG_CHECKED)) { cb.setChecked(true); edit.setPaintFlags(edit.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG); + edit.setTextColor(Color.GRAY); item = item.substring(TAG_CHECKED.length(), item.length()).trim(); } else if (item.startsWith(TAG_UNCHECKED)) { cb.setChecked(false); edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG); + edit.setTextColor(Color.BLACK); item = item.substring(TAG_UNCHECKED.length(), item.length()).trim(); + } else { + // 重置为默认状态 + cb.setChecked(false); + edit.setPaintFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG); + edit.setTextColor(Color.BLACK); } + // 设置列表项点击事件监听器,用于标记项目为已完成状态 + view.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + // 添加点击反馈效果 + v.setBackgroundColor(Color.parseColor("#E0E0E0")); + v.postDelayed(new Runnable() { + @Override + public void run() { + v.setBackgroundColor(Color.TRANSPARENT); + } + }, 100); + + // 处理列表项点击事件,标记项目为已完成状态 + CheckBox checkBox = (CheckBox) v.findViewById(R.id.cb_edit_item); + checkBox.setChecked(!checkBox.isChecked()); + } + }); + + // 设置复选框点击事件监听器 + cb.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + // 直接切换选中状态,避免与列表项点击事件冲突 + cb.setChecked(!cb.isChecked()); + } + }); + + // 设置编辑文本点击事件监听器,用于进入详细编辑模式 + edit.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + // 阻止事件冒泡,避免触发列表项的点击事件 + v.setClickable(true); + v.setFocusable(true); + v.setFocusableInTouchMode(true); + + // 添加点击反馈效果 + edit.setBackgroundColor(Color.parseColor("#F0F0F0")); + edit.postDelayed(new Runnable() { + @Override + public void run() { + edit.setBackgroundColor(Color.TRANSPARENT); + } + }, 100); + + // 处理编辑文本点击事件,进入详细编辑模式 + edit.requestFocus(); + edit.setSelection(edit.length()); + // 显示软键盘 + getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + } + }); + + // 为编辑文本添加文本变化监听器,确保修改能够被保存 + edit.addTextChangedListener(new android.text.TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(android.text.Editable s) { + // 文本变化后延迟保存笔记,避免频繁操作导致卡顿 + saveNoteDelayed(); + } + }); + + // 设置列表项长按事件监听器 + edit.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + try { + // 添加长按反馈效果 + edit.setBackgroundColor(Color.parseColor("#D0D0D0")); + edit.postDelayed(new Runnable() { + @Override + public void run() { + edit.setBackgroundColor(Color.TRANSPARENT); + } + }, 100); + + // 处理长按事件,将清单标记为已完成状态 + View parentView = (View) v.getParent(); + if (parentView != null) { + CheckBox checkBox = (CheckBox) parentView.findViewById(R.id.cb_edit_item); + if (checkBox != null) { + checkBox.setChecked(!checkBox.isChecked()); + } + } + } catch (Exception e) { + Log.e(TAG, "Error in long click listener: " + e.getMessage()); + } + return true; + } + }); + edit.setOnTextViewChangeListener(this); edit.setIndex(index); edit.setText(getHighlightQueryResult(item, mUserQuery)); @@ -1508,6 +1698,161 @@ public class NoteEditActivity extends Activity implements OnClickListener, } } + /** + * 将已完成的项目移到列表底部 + * @param edit 编辑文本框 + */ + private void moveCompletedItemToBottom(NoteEditText edit) { + try { + int childCount = mEditTextList.getChildCount(); + if (childCount <= 1 || edit == null) { + return; + } + + // 找到当前项目的索引 + int currentIndex = -1; + for (int i = 0; i < childCount; i++) { + View view = mEditTextList.getChildAt(i); + if (view != null) { + ListItemViewHolder holder = (ListItemViewHolder) view.getTag(); + if (holder != null && holder.etEditText == edit) { + currentIndex = i; + break; + } + } + } + + if (currentIndex == -1 || currentIndex == childCount - 1) { + return; + } + + // 找到第一个未完成的项目索引 + int firstUncompletedIndex = -1; + for (int i = currentIndex + 1; i < childCount; i++) { + View view = mEditTextList.getChildAt(i); + if (view != null) { + ListItemViewHolder holder = (ListItemViewHolder) view.getTag(); + if (holder != null && holder.cbEditItem != null && !holder.cbEditItem.isChecked()) { + firstUncompletedIndex = i; + break; + } + } + } + + if (firstUncompletedIndex != -1) { + // 保存当前项目 + View currentView = mEditTextList.getChildAt(currentIndex); + if (currentView != null) { + mEditTextList.removeViewAt(currentIndex); + // 插入到第一个未完成项目之前 + mEditTextList.addView(currentView, firstUncompletedIndex - 1); + // 更新索引 + updateItemIndices(); + } + } + } catch (Exception e) { + Log.e(TAG, "Error in moveCompletedItemToBottom: " + e.getMessage()); + } + } + + /** + * 将未完成的项目移到列表顶部 + * @param edit 编辑文本框 + */ + private void moveUncompletedItemToTop(NoteEditText edit) { + try { + int childCount = mEditTextList.getChildCount(); + if (childCount <= 1 || edit == null) { + return; + } + + // 找到当前项目的索引 + int currentIndex = -1; + for (int i = 0; i < childCount; i++) { + View view = mEditTextList.getChildAt(i); + if (view != null) { + ListItemViewHolder holder = (ListItemViewHolder) view.getTag(); + if (holder != null && holder.etEditText == edit) { + currentIndex = i; + break; + } + } + } + + if (currentIndex == -1 || currentIndex == 0) { + return; + } + + // 找到最后一个已完成的项目索引 + int lastCompletedIndex = -1; + for (int i = 0; i < currentIndex; i++) { + View view = mEditTextList.getChildAt(i); + if (view != null) { + ListItemViewHolder holder = (ListItemViewHolder) view.getTag(); + if (holder != null && holder.cbEditItem != null && holder.cbEditItem.isChecked()) { + lastCompletedIndex = i; + } + } + } + + // 保存当前项目 + View currentView = mEditTextList.getChildAt(currentIndex); + if (currentView != null) { + mEditTextList.removeViewAt(currentIndex); + // 插入到最后一个已完成项目之后 + mEditTextList.addView(currentView, lastCompletedIndex + 1); + // 更新索引 + updateItemIndices(); + } + } catch (Exception e) { + Log.e(TAG, "Error in moveUncompletedItemToTop: " + e.getMessage()); + } + } + + /** + * 更新所有项目的索引 + */ + private void updateItemIndices() { + try { + int childCount = mEditTextList.getChildCount(); + for (int i = 0; i < childCount; i++) { + View view = mEditTextList.getChildAt(i); + if (view != null) { + ListItemViewHolder holder = (ListItemViewHolder) view.getTag(); + if (holder != null && holder.etEditText != null) { + holder.etEditText.setIndex(i); + } + } + } + } catch (Exception e) { + Log.e(TAG, "Error in updateItemIndices: " + e.getMessage()); + } + } + + /** + * 回收视图到缓存 + * @param view 要回收的视图 + */ + private void recycleView(View view) { + if (view != null && mViewCache.size() < MAX_CACHE_SIZE) { + // 清除视图的内容和监听器,避免内存泄漏 + ListItemViewHolder holder = (ListItemViewHolder) view.getTag(); + if (holder != null) { + holder.etEditText.setText(""); + holder.etEditText.setOnTextViewChangeListener(null); + holder.cbEditItem.setOnCheckedChangeListener(null); + } + mViewCache.add(view); + } + } + + /** + * 清空视图缓存 + */ + private void clearViewCache() { + mViewCache.clear(); + } + /** * 清单模式改变时调用 * 实现NoteSettingChangedListener接口 @@ -1580,26 +1925,35 @@ public class NoteEditActivity extends Activity implements OnClickListener, private boolean getWorkingText() { boolean hasChecked = false; if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) { - StringBuilder sb = new StringBuilder(); + // 优化:使用StringBuilder的初始容量,减少扩容开销 + StringBuilder sb = new StringBuilder(mEditTextList.getChildCount() * 50); // 预估每个项目平均50字符 for (int i = 0; i < mEditTextList.getChildCount(); i++) { View view = mEditTextList.getChildAt(i); - ListItemViewHolder holder = (ListItemViewHolder) view.getTag(); - NoteEditText edit = holder.etEditText; - if (!TextUtils.isEmpty(edit.getText())) { - if (holder.cbEditItem.isChecked()) { - sb.append(TAG_CHECKED).append(" ").append(edit.getText()).append("\n"); - hasChecked = true; - } else { - sb.append(TAG_UNCHECKED).append(" ").append(edit.getText()).append("\n"); + if (view != null) { + ListItemViewHolder holder = (ListItemViewHolder) view.getTag(); + if (holder != null && holder.etEditText != null && holder.cbEditItem != null) { + NoteEditText edit = holder.etEditText; + if (!TextUtils.isEmpty(edit.getText())) { + if (holder.cbEditItem.isChecked()) { + sb.append(TAG_CHECKED).append(" ").append(edit.getText()).append("\n"); + hasChecked = true; + } else { + sb.append(TAG_UNCHECKED).append(" ").append(edit.getText()).append("\n"); + } + } } } } mWorkingNote.setWorkingText(sb.toString()); } else { // 对于富文本模式,保存当前的HTML内容,包括Base64图片 - String currentHtml = mNoteEditor.getHtml(); - Log.d(TAG, "getWorkingText called for rich text mode, saving HTML content: " + currentHtml); - mWorkingNote.setWorkingText(currentHtml); + // 优化:避免不必要的日志输出,减少IO开销 + if (mNoteEditor != null) { + String currentHtml = mNoteEditor.getHtml(); + if (currentHtml != null) { + mWorkingNote.setWorkingText(currentHtml); + } + } } return hasChecked; } @@ -1848,6 +2202,71 @@ public class NoteEditActivity extends Activity implements OnClickListener, Toast.makeText(this, resId, duration).show(); } + /** + * 延迟保存笔记,避免频繁操作导致卡顿 + */ + private void saveNoteDelayed() { + // 移除之前的延迟保存任务 + if (mSaveNoteHandler != null) { + mSaveNoteHandler.removeCallbacksAndMessages(null); + } + // 延迟500毫秒保存,避免频繁操作导致卡顿 + mSaveNoteHandler.postDelayed(new Runnable() { + @Override + public void run() { + if (saveNote()) { + // 保存成功的简短提示 + showSaveSuccessHint(); + } + } + }, 500); + } + + /** + * 显示保存成功的简短提示 + */ + private void showSaveSuccessHint() { + if (mSaveHint == null) { + mSaveHint = new TextView(this); + mSaveHint.setText("已保存"); + mSaveHint.setTextColor(Color.GRAY); + mSaveHint.setTextSize(12); + mSaveHint.setPadding(10, 5, 10, 5); + mSaveHint.setGravity(Gravity.CENTER); + mSaveHint.setBackgroundColor(Color.parseColor("#E0E0E0")); + mSaveHint.setAlpha(0.0f); + + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ); + params.gravity = Gravity.CENTER; + params.topMargin = 10; + mEditTextList.addView(mSaveHint, params); + } + + // 显示动画 + mSaveHint.animate() + .alpha(1.0f) + .setDuration(300) + .withEndAction(new Runnable() { + @Override + public void run() { + // 延迟后隐藏 + mSaveHint.postDelayed(new Runnable() { + @Override + public void run() { + mSaveHint.animate() + .alpha(0.0f) + .setDuration(300) + .start(); + } + }, 1000); + } + }) + .start(); + } + /** * 从相册选择图片 OMO */