代码精读结对练习-小米便签

一、小米便签的代码精读

小米便签源码

1.关键用例的顺序图和详细类图

顺序图:

类图:

2.精读部分的代码标注

对核心类NotesListActivity.java这个类进行精读:

1.

该部分为初始化和定义我们所需要的变量,定义了一系列常量,如查询令牌、菜单ID、偏好设置键名等。

定义了一个枚举类型 ListEditState 来表示当前列表的状态(普通笔记列表、子文件夹列表或通话记录文件夹列表)。

持有各种UI组件引用,如 mNotesListView(笔记列表)、mAddNewNote(添加新笔记按钮)、mTitleBar(标题栏)等。

初始化背景查询处理器 mBackgroundQueryHandler,用于异步查询数据库中的笔记和文件夹数据。

创建并持有 NotesListAdapter 实例,用于适配笔记列表的数据。

定义了其他一些成员变量,如当前文件夹ID、内容解析器、模式回调函数等。

2.

protected void onCreate(Bundle savedInstanceState)

覆盖基类方法,在应用程序启动时调用,用于初始化资源、设置布局,并检查是否需要向初次使用的用户展示介绍内容。

 protected void onActivityResult(int requestCode, int resultCode, Intent data)

当从另一个Activity返回结果时调用,更新列表数据以反映用户在其他Activity中所做的更改。

private void setAppInfoFromRawRes()

在首次启动应用时(从Shared Preferences中检查标志位PREFERENCE_ADD_INTRODUCTION),从raw资源目录读取名为"introduction"的文本文件,并将其内容作为一条工作笔记保存到数据库中。之后更新 Shared Preferences 标志位,表示已添加过介绍。

protected void onStart()

覆盖父类方法,在活动开始时调用 startAsyncNotesListQuery() 来异步加载笔记列表数据。

private void initResources()

初始化活动所需的组件和变量,如Content Resolver、后台查询处理器(BackgroundQueryHandler)、根文件夹ID、ListView、Adapter等。

设置ListView的各种事件监听器,例如单击、长按事件处理,以及底部添加新笔记按钮的点击和触摸监听器。

创建了一个内部类 ModeCallback,实现了MultiChoiceModeListener和OnMenuItemClickListener接口,用于处理多选模式下的各种菜单项点击事件,如删除、移动笔记等。

private class ModeCallback implements ListView.MultiChoiceModeListener, OnMenuItemClickListener

该类主要用于显示和管理用户的笔记列表,支持多选操作(包括删除和移动笔记),同时确保在应用启动时能正确加载和处理资源文件中的介绍信息。

 private class NewNoteOnTouchListener implements OnTouchListener

这是一个实现 OnTouchListener 接口的内部类,主要负责处理添加新笔记按钮的触摸事件。其目的是在用户滑动屏幕时,如果触摸的是该按钮的透明部分,事件会被传递给位于按钮下方的笔记列表视图。这样设计是为了满足UI设计师的要求,使得用户可以通过滑动透明区域来滚动列表,同时保持添加新笔记按钮始终可见。

private void startAsyncNotesListQuery()

发起异步查询请求以获取指定文件夹下的笔记列表数据。使用 BackgroundQueryHandler 对象执行查询,并根据当前文件夹ID设置不同的查询条件。

private final class BackgroundQueryHandler extends AsyncQueryHandler

继承自 AsyncQueryHandler,用于在后台线程处理数据库查询。覆盖了onQueryComplete() 方法,在查询完成时根据传入的令牌(token)更新UI,比如替换笔记列表适配器的游标,或者处理查询文件夹列表的结果。

private void showFolderListMenu(Cursor cursor)

当需要显示文件夹选择对话框时,此方法构建并显示一个对话框,其中包含了文件夹列表。用户选择某个文件夹后,会批量移动所选笔记至该文件夹,并显示相应提示信息。

private void createNewNote()

 启动一个新的 NoteEditActivity 以创建或编辑笔记,传递当前文件夹ID作为额外意图参数。

private void batchDelete()

异步任务,用于批量删除所选笔记。在非同步模式下直接删除笔记,在同步模式下将笔记移动到回收站文件夹。在删除/移动操作完成后,如果有相关的桌面小部件存在,更新这些小部件的状态。最后关闭多选模式。

private void deleteFolder(long folderId)

删除指定ID的文件夹。首先判断是否是根文件夹,如果是则不允许删除。接着收集该文件夹内所有笔记的ID,并根据同步模式决定是直接删除还是移至回收站文件夹。然后,更新与该文件夹关联的小部件。

private void openNode(NoteItemData data)

打开指定的笔记进行查看。创建Intent并设置ACTION_VIEW,附带笔记ID,然后启动新的NoteEditActivity以显示笔记内容。

private void openFolder(NoteItemData data)

打开指定的文件夹并展示其中的笔记列表。更新当前文件夹ID,并根据文件夹类型调整界面状态,如隐藏“新建笔记”按钮、更改标题栏文本等。

public void onClick(View v)

这是OnClickListener接口的实现,当点击按钮时触发。在这个案例中,仅处理了点击“新建笔记”按钮的事件,调用createNewNote()方法创建新笔记。

private void showSoftInput() private void hideSoftInput(View view)分别用来显示和隐藏软键盘。

private void showCreateOrModifyFolderDialog(final boolean create)

显示创建或修改文件夹的对话框。根据参数create的值决定是创建新文件夹还是修改已有文件夹名称。在对话框中提供一个输入框让用户输入文件夹名,并检查名称是否已经存在。当用户点击确定按钮时,根据情况进行插入或更新数据库操作,并关闭对话框。同时,通过TextWatcher监控输入框内容变化,实时更新对话框中的确定按钮是否可用。

public void onBackPressed()

重写系统默认的后退按钮行为。根据当前状态(mState)的不同做出不同的响应。如果处于子文件夹或者通话记录文件夹状态,则回到根文件夹并刷新列表;若已在笔记列表状态,则调用父类的onBackPressed()方法以执行正常的后退操作。

private void updateWidget(int appWidgetId, int appWidgetType)

于更新应用小部件的方法。根据提供的小部件类型创建对应的Intent,并发送广播通知小部件进行更新。

private final OnCreateContextMenuListener mFolderOnCreateContextMenuListener = new OnCreateContextMenuListener()

这是一个上下文菜单创建监听器,当长按文件夹项时会显示相应的菜单项,包括查看文件夹、删除文件夹和修改文件夹名称。

public void onContextMenuClosed(Menu menu)

当上下文菜单关闭时,取消长按监听器

public boolean onContextItemSelected(MenuItem item)

处理上下文菜单项的选择事件。针对不同的菜单选项执行相应操作,例如打开文件夹、删除文件夹或修改文件夹名称。

public boolean onPrepareOptionsMenu(Menu menu)

准备并填充选项菜单,根据当前的状态(mState)加载不同的菜单资源,并根据同步状态动态更新"sync"菜单项的标题。

public boolean onOptionsItemSelected(MenuItem item)

处理选项菜单项的选择事件。根据用户选择的菜单项,执行对应的操作,如创建新文件夹、导出笔记到文本、开始/取消同步、进入设置页面、创建新笔记以及发起搜索请求。

public boolean onSearchRequested()

覆盖系统的搜索请求方法,启动搜索界面。当用户触发搜索动作时,调用 startSearch() 方法开启搜索功能,并返回 true 表示已处理该请求。

private void exportNoteToText()

实现导出所有笔记到文本文件的功能。创建一个异步任务(AsyncTask),在后台线程中调用 BackupUtils 类的 exportToText() 方法来执行导出操作。完成后,在主线程中根据导出结果展示不同的对话框提示用户导出成功与否,以及可能存在的错误信息,如SD卡未挂载或系统错误等。

private boolean isSyncMode()

检查当前是否开启了同步模式。通过读取偏好设置获取同步账号名,如果长度大于0则认为是同步模式。

private void startPreferenceActivity()

启动偏好设置Activity,允许用户配置应用的相关设置。

private class OnListItemClickListener implements OnItemClickListener

内部类实现了 OnItemClickListener 接口,当用户点击列表项时触发此回调。根据不同的状态判断点击的是文件夹还是笔记,并执行相应的操作,如打开文件夹或笔记,或者在多选模式下切换项目的选择状态。

private void startQueryDestinationFolders()

查询目标文件夹列表。根据当前状态构造SQL语句,使用后台查询处理器(mBackgroundQueryHandler)从数据库中获取指定条件下的文件夹数据,这些数据将用于填充文件夹列表视图。

 public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id)

处理列表项的长按事件。当用户长按笔记列表项时,如果是笔记类型且不在多选模式下,则尝试启动多选模式并选中该条目;如果长按的是文件夹,则设置上下文菜单创建监听器以便后续显示文件夹相关的上下文菜单。最后,返回 false 表示长按事件的默认处理不被阻止。

3.对项目的代码标注

3.1主要功能包括:文件夹与笔记的增删改查操作、用户界面交互处理(如菜单点击、长按事件)、文件夹内容浏览与组织、数据同步、笔记导出、以及搜索功能。

3.2.应用流程:围绕用户在笔记列表界面的各种操作展开,根据用户触发的动作(如点击、长按、菜单选择等),调用对应的方法执行业务逻辑,同时通过与数据库交互完成数据的持久化。

3.4.核心实现思路:使用事件驱动模型,通过监听用户交互行为触发对应的操作。 数据库操作封装在DataUtils类中,对外提供统一接口,方便业务逻辑调用。 界面状态和导航结构清晰,通过变量mState维护当前列表编辑状态,便于根据不同状态展示不同的界面元素和菜单项。 异步任务(如备份导出)使用了AsyncTask进行处理,避免阻塞主线程。

3.5.时空复杂度:

时间复杂度:

数据库操作(如删除、插入、更新)通常取决于数据库表中数据的数量,假设为O(n),n为操作所影响的行数。

显示或隐藏软键盘、更新小部件、启动新Activity等操作的时间复杂度一般认为是常数级别O(1)。

上下文菜单和选项菜单的构建与展示时间复杂度也基本为O(1)。

空间复杂度:

创建集合(如HashSet)存储ID,其大小与要操作的笔记数量有关,最坏情况下为O(n)。

弹出对话框和菜单需要一定的内存空间,但由于Android系统会自动管理这些临时对象,故这部分的空间开销不是主要考虑因素。但如果对话框中涉及到大量数据加载,则需关注这部分的内存消耗。

4.代码质量检查工具

1.下载并配置好findbugs

1.1先点help,然后install New Software

1.2然后直接add

1.3然后添加name:findbugs

添加链接:http://findbugs.cs.umd.edu/eclipse

1.4最后直接下载,重启

1.5调出视图

2.然后运行findbug

3.查看结果

4.对分析结果:

FindBugs找出的bug有3中颜色:

黑色的臭虫标志是分类

红色的臭虫表示严重bug发现后必须修改代码

橘黄色的臭虫表示潜在警告性bug 尽量修改

问题一:

Possible null pointer dereference of js in net.micode.notes.gtaskdata.Task.setContentByLocalJSON(JSONObject) [Scary(8), Normal confidence] 这个警告指出,在net.micode.notes.gtaskdata.Task.setContentByLocalJSON()方法中可能存在空指针引用。这意味着变量js可能为null,并且在后续操作中被使用时会导致NullPointerException(NPE)。建议检查js是否为null并在必要时添加适当的null检查。

问题二:

Possible null pointer dereference of js in net.micode.notes.gtaskdata.TaskList.setContentByLocalJSON(JSONObject) [Scary(8), Normal confidence] 类似于第一个问题,这个警告表示在net.micode.notes.gtaskdata.TaskList.setContentByLocalJSON()方法中也存在空指针引用的风险。同样需要对js进行null检查以避免NPE。

Of Concern (2) 这部分包含两个与“关注”相关的问题,它们具有高置信度。

High confidence (2) 这部分包含两个具有高置信度的问题。

Write to static field from instance method (2) 这类问题是关于从实例方法写入静态字段的操作。这通常不是一个好做法,因为它可能会导致状态共享或并发问题。应该考虑将这些字段更改为实例字段或者重新设计方法以避免这种行为。

问题三:

Write to static field net.micode.notes.gtask.remote.GTaskSyncService.mSyncProgress from instance method net.micode.notes.gtask.remote.GTaskSyncService.sendBroadcast(String) [Of Concern(15), High confidence] 这个特定的警告表明在net.micode.notes.gtask.remote.GTaskSyncService.sendBroadcast()实例方法中写入了静态字段mSyncProgress。这是不推荐的做法,因为静态字段在整个应用程序中是全局可见的,可能导致意外的行为。

问题四:

Write to static field net.micode.notes.gtask.remote.GTaskSyncService.mSyncTask from instance method net micode.notes.gtask.remote.GTaskSyncService.onCreate() [Of Concern(15), High confidence] 同样,这个警告指出在net.micode.notes.gtask.remote.GTaskSyncService.onCreate()实例方法中写入了静态字段mSyncTask。这也是一种不推荐的做法。

二、实践心得

在最初分配工作时,双方首先面对面地坐在同一台设备前查看项目结构,大致浏览了一遍各个包的功能后再划分各自的精读范围。在各自的精读过程中,双方也就彼此的疑问做出讨论,同时交流彼此对于对方项目的理解,确保了项目推进的高效性与一致性。最后编写报告时,双方也拿到彼此的报告进行检查,

通过本次实验,双方对于团队合作有了更深层次的理解,相较于上一次团队合作,我们能够更好地分配工作,彼此交流,最重要的是能够在一个项目推进时时刻保持一致与紧密联系。因此在长达3周时间的磨合下,1+1>2!

  • 10
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你好!对于 Faster R-CNN 的代码精读,你可以参考以下步骤: 1. 阅读主要的文件结构:Faster R-CNN 通常包括几个主要的文件,包括模型定义文件、数据加载文件、训练和测试脚本等。首先,了解代码的整体结构和文件之间的关系是很重要的。 2. 理解模型架构:查看模型定义文件,通常是一个包含网络结构的类或函数。在这个文件中,你可以找到网络的主要组件,如卷积层、池化层、全连接层等。仔细阅读这些组件的定义和参数设置,对整个网络的结构和运作方式有一个清晰的理解。 3. 研究损失函数:Faster R-CNN 使用一种特定的损失函数来衡量模型预测与真实标签之间的差异。阅读训练脚本中的损失函数实现部分,了解如何计算损失以及如何反向传播梯度更新模型参数。 4. 数据加载与处理:Faster R-CNN 在训练和测试过程中需要加载和处理数据。查看数据加载文件,了解如何从数据集中读取图像和标签,并进行预处理操作,如缩放、裁剪、归一化等。 5. 推断与预测过程:Faster R-CNN 的目标是在图像中检测和定位物体。了解测试脚本中的推断和预测过程,包括如何对输入图像进行前向传播,并根据预测结果生成检测框和类别。 6. 调试和修改:在阅读代码的过程中,你可能会遇到一些问题或有一些想法来改进模型。尝试调试代码并进行一些修改,看看是否能够改善模型的性能或加入新的功能。 请记住,Faster R-CNN 是一个相对复杂的模型,可能需要花费一些时间来理解和熟悉代码。阅读官方的文档和参考资料,以及查找其他人的实现和解释,都是学习和理解代码的有用资源。祝你成功!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值