小米便签源代码泛读报告

一、项目导入

在导入小米便签源代码的时候,由于一开始使用2023的最新版本,但是由于gradle问题,在导入的时候无法自动识别为“Android”模式,后面采用了2020版本,成功识别出“Android”模式。当然在环境搭建过程中也出现了多种多样的问题,参考了往届学长的博客:在Win10以及SDK为33的环境下——小米便签项目的搭建_3 files found with path 'meta-inf/dependencies'.-CSDN博客

里面涵盖了大部分搭建过程会出现的问题,十分详细。

二、APP功能补全

在环境搭建完成之后,在运行测试时,发现功能缺失的现象,在查找资料后,解决此问题:

①定位:app->res->values->styles

②在styles.xml中下滑到最后,可以看见:

③修改代码为:

  <style name="NoteActionBarStyle" parent="@android:style/Widget.Holo.Light.ActionBar.Solid">
    <!--    <item name="android:displayOptions" />-->
        <item name="android:visibility">visible</item>
    </style>

三、APP运行

小米便签运行视频-CSDN直播

四、源代码泛读

前置动作

由于个人习惯问题,我们在正式阅读代码之前,根据代码中的命名和参考网上的资料,将包、子包、类以及它们的作用绘制成表格,以此形成了一个大体的框架认识,其中添加标记的是我们认为是核心类的部分:

子包

主要作用

data

contact

联系人数据库

Notes

便签数据库,用于记录便签相关属性和数据

NotesProvider

便签信息提供类

NotesDatabaseHelper

数据库帮助类,用于辅助创建、处理数据库的条目

gtask

data

MetaData

关于同步任务的元数据

Node

同步任务的管理结点,用于设置、保存同步动作的信息

SqlData

数据库中基本数据,方法包括读取数据、获取数据库中数据、提交数据到数据库

SqlNode

数据库中便签数据,方法包括读取便签内容、从数据库中获取便签数据、设置便签内容、提交便签数据到数据库

Task

同步任务,将创建、更新和同步动作包装成JSON对象,用本地和远程的JSON对结点内容进行设置,获取同步信息,进行本地和远程的同步

TaskList

同步任务列表,将Task组织成同步任务列表进行管理

exception

ActionFailureException

动作失败异常

NetworkFailureException

网络异常失败

remote

GTaskAsyncTask

GTask异步任务,方法包括任务同步和取消,显示同步任务的进程、通知和结果

GTaskClient

GTask客户端,提供登录Google账户,创建任务和任务列表,添加和删除结点,提交、重置更新、获取任务列表等功能

GTaskManager

GTask管理者,提供同步本地和远端的任务,初始化任务列表,同步内容、文件夹,添加、更新本地和远端结点,刷新本地同步任务ID等功能

GTaskSyncService

GTask同步服务,用于提供同步服务 (开始、取消同步),发送广播

model

Note

单个便签项

WorkingNote

当前活动便签项

tool

BackupUtils

备份工具类,用于数据备份读取、显示

DataupUtils

便签数据处理工具类,封装如查找、移动、删除数据等操作

GTaskStringUtils

同步中使用的字符串工具类,为了jsonObject提供string对象

ResourceParser

界面元素的解析工具类,利用R.java这个类获取资源供程序调用

ui

AlarmAlertActivity

闹铃提醒界面

AlarmInitReceiver

闹铃提醒启动消息接收器

AlarmReceiver

闹铃提醒接收器

DateTimePicker

设置提醒时间的部件

DateTimePickerDialog

设置提醒时间的对话框界面

DropdownMenu

下拉菜单界面

FoldersListAdapter

文件夹列表链接器(链接数据库)

NoteEditActivity

便签编辑活动

NoteEditText

便签的文本编辑界面

NoteItemData

便签项数据

NotesListActivity

主界面,用于实现处理文件夹列表的活动

NotesListAdapter

便签列表链接器(链接数据库)

NotesPreferenceActivity

便签同步的设置界面

widget

NoteWidgetProvider

桌面挂件

NoteWidgetProvider_2x

2倍大小的桌面挂件

NoteWidgetProvider_4x

4倍大小的桌面挂件

 (一)用例图:通过用例图来描述小米便签的主要功能以及它们之间的关系

首先我们需要明晰例图是什么,里面有哪些元素,有哪些关系,它们又是用什么样的图像表示的?

带着这个问题,我们参考:UML图之例图-CSDN博客,完成了本次例图绘制:

(二)体系结构图(包图):通过绘制体系结构图来了解整个软件的总体设计思路

1、明晰包图的绘制方法:UML--包图详解_uml包图-CSDN博客

2、在绘制过程中,我们不可避免地参考了网上已有的体系结构图:

但在根据网上的体系结构图绘制过程了,也有了一些自己的体会:

(1)在绘制的包图的时候,特别是向小米便签这样,对现阶段的我相对大型的代码文件时,首先就是要初步地划分层次

上图中将小米便签分成了:界面层、业务层、模型层、数据层。其中很容易考虑到界面层和数据层,界面是最直接面对软件用户,而数据是最基础的部分。但是对于业务层(部分资料称之为:工具的集成与实现)和模型层就有些不能理解。

在咨询Cursor之后,发现了MVC架构:

于是在网上查找相关的资料:超详细的!!!MVC架构模式说明 - 知乎 (zhihu.com)

然后明晰为什么采取界面层、业务层、模型层、数据层这样的划分层次。

这样就可以得到一个初步的框架:

(2)在划分完层次之后,事情就变得简单了,那就是根据每一个类的功能将其填入对应的层级中

界面层:根据表格(在前置动作部分)中列出的主要功能,我们可以很轻松地将ui和widget填入其中,而res包含了所有的xml文件和相对应图片,属于MVC架构里面View部分,所以也应该填入界面部分。

业务层:根据MVC架构的逻辑,个人判断它应该担任是C(Control控制器)的角色:处理用户输入的信息。负责从视图读取数据,控制用户输入,并向模型发送数据,是应用程序中处理用户交互的部分。负责管理与用户交互交互控制。

因此根据表格中的主要功能,首先排除ui和widget,接着关于gtask.date,我们可以发现它大部分功能是与数据库交互,不符合业务层的要求,因此也排除,那么model嘛,看名字就知道是模型层的,最后只剩下tool、gtask.exception和gtask.remote。

tool:

gtask.exception和gtask.remote:

从正面来看,他们的确符合业务层的逻辑;从反面论证,首先他们必定不属于界面层和数据层,而模型层在于与数据层的交互,而它们并没有。

最后对于gtask.data为什么不属于数据层,而是模型层,以我现阶段基于小米便签源代码的理解就是:数据层只是单纯地对数据库进行操作(创建数据库,数据库内的增删改查等)而不涉及其他部分(如调用数据库),这一点可以通过对比表格内容发现。当然,后续核心类的分析,也可以很清楚发现data类只对数据库内部进行操作。

(三)类之间的调用关系图:通过绘制类之间的调用关系图来掌握小米便签的具体设计

 1、首先我们必须明确类间关系一种有几种?各自的含义是什么?如何通过图像表示出来?

类间关系一种有6种,分别为继承(extends)、实现(implements)、关联关系、聚合关系、组合关系、依赖关系

各自的含义是什么?如何通过图像表示出来?

由于继承和实现已经较为深入的学习并实践过,关系的判断可以通过单词(extends和implements)查询来完成,因此不赘述。

图例:

关联关系:某类作为另一类的成员变量,分为单向关联和双向关联。

eg:

单向联系:班级中增加了学生,但是学生中没有增加班级属性(他爱她,她不爱他?)

双向关联:班级中增加了学生,学生中也增加了班级属性(他爱她,她也爱他?)

 图例:

单向联系:(单相思?所以单箭头)

  

双向联系:(双向奔赴?但不是双箭头)

聚合关系:某类作为另一类的成员变量(整体和部分可分离,整体的生命周期和部分的生命周期不同)(你+你女朋友=情侣,可以分手?情侣关系结束,但你不会die)

eg:计算机与CPU、公司与员工的关系、班级和学生(班级里所有的学生共同组成班级,而关联关系描述的是单个学生与班级的关系)的关系

图例:

组合关系:某类作为另一类的成员变量(整体和部分不可分离,整体的生命周期和部分的生命周期相同)(你和你的恋爱脑?)

eg:人和四肢的关系

图例:(实心的,这段关系铁滴狠)

依赖关系:若类A使用类B(类B作为类A的方法的参数(或者局部变量)存在),则由类A指向类B,但是类B的变化会影响到类A

eg:人和他掌握技能(你和你的代码能力?)

图例:

以下是根据网上的例子画出的调用关系图:

data:

gtask.data:

gtask.remote:

model:

widget:

ui:

除开明确的继承和实现关系,对于调用关系图仍存在一些不理解的地方,如:

gtask.data中为什么是SqlNode->SqlData,而不是SqlData->SqlNode,或者SqlNode是SqlData的聚合,代码中明显有:

(四)核心类的主要作用:通过给出核心类的主要作用来进一步加深对软件设计的理解

Notes类:

(1)首先定义了小米便签应用中的一些常量和标识符:

其中:
AUTHORITY:用于标识便签应用的权限;
TAG:用于标识便签应用的标签
TYPE_NOTE、TYPE_FOLDER、TYPE_SYSTEM:定义了便签的类型,分别表示便签、文件夹和系统类型
ID_ROOT_FOLDER、ID_TEMPARAY_FOLDER、ID_CALL_RECORD_FOLDER、ID_TRASH_FOLER:定义了系统文件夹的标识符
INTENT_EXTRA_ALERT_DATE、INTENT_EXTRA_BACKGROUND_ID、INTENT_EXTRA_WIDGET_ID、INTENT_EXTRA_WIDGET_TYPE、INTENT_EXTRA_FOLDER_ID、INTENT_EXTRA_CALL_DATE:定义了意图中的额外数据键
TYPE_WIDGET_INVALIDE、TYPE_WIDGET_2X、TYPE_WIDGET_4X:定义了小部件的类型,包括无效类型、2倍大小和4倍大小类型

(2)接着定义了两个静态变量:

其中:
CONTENT_NOTE_URI:表示便签(Note)的内容URI,用于访问便签相关数据。
CONTENT_DATA_URI:表示数据(Data)的内容URI,用于访问数据相关信息。
这些URI通过解析包含权限(AUTHORITY)和路径("note"或"data")的字符串来创建,用于在应用中访问和操作便签和数据的内容。
(3)定义了两个接口:

通过阅读具体的代码,可以发现:这两个接口主要用于定义便签和数据表的列名和数据类型,以便在应用中进行数据库操作和数据存储
NoteColumns接口:
定义了便签(Note)数据表的列名和数据类型,包括便签的唯一ID、父级ID、创建日期、修改日期、提醒日期、内容摘要、小部件ID、小部件类型、背景颜色ID、附件标识、便签数量、类型、同步ID、本地修改标识、原始父级ID、GTask ID和版本号等。
DataColumns接口:
定义了数据(Data)表的列名和数据类型,包括数据的唯一ID、MIME类型、关联的便签ID、创建日期、修改日期、内容、以及5个通用数据列(data1至data5)用于不同类型的数据存储。

(4)定义了两个方法,都引用了DataColumns接口:

TextNote类:

其中,对于DataColumns接口的继承体现在DATA1(MIME类型)为整型数据类型,即:


CallNote类:

其中,对于DataColumns接口的继承体现在DATA3(MIME类型)为TEXT数据类型,即:


(5)定义了静态内部类DataConstants:

NotesDatabaseHelper类:

(1)对Notes类中DataColumns、DataConstants、NoteColumns进行引用:

(2)定义了数据库名称、版本号、表名称以及类的标签和实例变量:

其中:
DB_NAME:定义了数据库的名称为"note.db"。
DB_VERSION:定义了数据库的版本号为4。
TABLE接口:定义了两个表的名称,分别为"note"和"data"。
TAG:定义了一个标签为"NotesDatabaseHelper"。
mInstance:定义了一个静态变量mInstance,用于表示NotesDatabaseHelper类的实例。

(3)定义了SQL语句分别用于创建便签表、数据表、包含ID、便签和数据的表格:

(4)定义了对数据库进行增删改查等工作的SQL语句:

将笔记移动到文件夹时增加文件夹的笔记数:

从文件夹中移动笔记时减少文件夹的笔记计数:

在文件夹中插入新笔记时增加文件夹的笔记数:

从文件夹中删除笔记时减少文件夹的笔记计数:

插入类型为{DataConstants.Note}的数据时更新注释的内容:

当{DataConstants.Note}类型的数据发生更改时,更新注释的内容:

删除{DataConstants.Note}类型的数据后,更新注释的内容:

删除数据属于已删除的注释:

删除笔记属于已删除的文件夹:

移动笔记属于已移动到垃圾文件夹的文件夹:

(5)定义创建数据库的方法:

createNoteTable:


createDataTable:


createNoteTable(SQLiteDatabase db):创建便签表,包括执行创建表的SQL语句、重新创建表的触发器、创建系统文件夹等操作。
reCreateNoteTableTriggers(SQLiteDatabase db):重新创建便签表的触发器。
createSystemFolder(SQLiteDatabase db):创建系统文件夹,包括通话记录文件夹、默认文件夹、临时文件夹和回收站文件夹。
createDataTable(SQLiteDatabase db):创建数据表,包括执行创建表的SQL语句、重新创建表的触发器和创建数据表的索引。
reCreateDataTableTriggers(SQLiteDatabase db):重新创建数据表的触发器。
getInstance(Context context):获取NotesDatabaseHelper类的实例。
onCreate(SQLiteDatabase db):在数据库创建时调用,执行创建便签表和数据表的操作。

(6)定义数据库升级更新的方法:

onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion):在数据库升级时调用,根据旧版本和新版本执行相应的升级操作。
upgradeToV2(SQLiteDatabase db):升级数据库到版本2的操作。
upgradeToV3(SQLiteDatabase db):升级数据库到版本3的操作,包括删除未使用的触发器、添加GTask ID列和添加回收站系统文件夹。
upgradeToV4(SQLiteDatabase db):升级数据库到版本4的操作,添加版本号列到便签表中。

NoteProvider类:

(1)引用了Notes.DataColumns、Notes.NoteColumns、NotesDatabaseHelper.TABLE接口:

(2)NoteProvider类继承了ContentProvider:

由于本次实验主要为代码泛读,因此关于ContentProvider类的内容就不过多展开,此处引入一个较为详细的链接以便于后续学习:Carson带你学Android:关于ContentProvider的知识都在这里了!_自定义contentprovider 找不到class-CSDN博客
(3)设置URI匹配规则、定义搜索结果的投影和查询搜索便签摘要的SQL语句:


(4)处理便签应用中的数据访问和操作,包括查询、插入、删除和更新等操作:

query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder):处理查询操作,根据URI匹配不同的查询类型,包括便签、数据和搜索结果的查询。
insert(Uri uri, ContentValues values):处理插入操作,根据URI匹配不同的插入类型,包括便签和数据的插入,并通知数据变化。
delete(Uri uri, String selection, String[] selectionArgs):处理删除操作,根据URI匹配不同的删除类型,包括便签和数据的删除,并通知数据变化。
update(Uri uri, ContentValues values, String selection, String[] selectionArgs):处理更新操作,根据URI匹配不同的更新类型,包括便签和数据的更新,并通知数据变化。
parseSelection(String selection):辅助方法,用于解析查询条件。
increaseNoteVersion(long id, String selection, String[] selectionArgs):辅助方法,用于增加便签版本号。
getType(Uri uri):获取URI的MIME类型,暂未实现。

Notes类:

(1)在阅读代码时,发现ContentValues并不是像NoteData一样属于自定义的,因此上网查找了其相关资料:android开发系列之由ContentValues看到的 - 蔡鸿军 - 博客园 (cnblogs.com)

(2)NoteData的内部类:管理便签中的文本数据和通话数据的操作,包括设置数据内容、ID,判断是否有本地修改以及将数据推送到ContentResolver中进行同步。

(3)创建一个新的笔记id,用于将新笔记添加到数据库:

WorkingNote类

主要用于管理工作便签的各种属性和操作,包括创建、加载、保存便签数据,设置提醒日期、背景颜色、小部件信息等,以及定义便签设置变化时的回调方法,被NoteEditActivity和NoteListActivity调用。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值