赞
踩
目录
1.首先从SonarQube官网https://www.sonarsource.com/products/sonarqube/上下载SonarQube软件包。(这边下载的是8.9.10版本)
2.解压后运行bin\Window-x86-64目录下的StartSonar.bat文件启动SonarQube服务器(本机为Windows64位操作系统)。
运行至出现如下图输出时表示服务器已经建立:
3.访问http://localhost:9000并使用账户admin进行登陆,成功后即连接上SonarQube服务器。
输入账号密码后,进入如下图的界面:
点击创建项目,添加项目密钥:
生成令牌:
4.为了方便在本地的AndroidStudio中进行代码质量分析,下一步在AndroidStudio中配置SonarLint插件,该插件可以按照SonarQube中的规则对代码进行分析。
选择Settings中的Plugins搜索SonarLint插件进行下载:
绑定SonarQube:
选择Settings中的Tools的SonarLint,点击+号,绑定服务器:
点击下一步,可以选择Token方式登录或者用户密码的方式登录,输入Token或是账号密码即可:(这里选择账号密码)
配置本地端和服务端建立远端关联:
Android App构建脚本配置:
在工程的build.gradle添加以下语句:
maven {url "https://plugins.gradle.org/m2/"}
classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.0"
如下图:
在App的build.gradle添加以下语句:
apply plugin: 'org.sonarqube'
sonarqube {
properties {
//Sonar服务器地址
property "sonar.host.url", "*****************************"
//Token模式
property "sonar.login","**********************************"
//账号密码模式
//property "sonar.login","*******"
//property "sonar.password","******"
property "sonar.sourceEncoding", "UTF-8"
property "sonar.projectKey", "Android_DuoApp"
property "sonar.projectName", project.name
//需要扫描的上传检测代码的模块,可以选择也可以配置哪一些需要或者不需要上传的模块(这里指APP模块下面的java包里面的全部)
property "sonar.sources", "src/main/java"
property "sonar.projectVersion", project.version
}}
如下图:
执行扫描并且上传分析
在终端使用命令./gradlew sonarqube:
build成功:
build成功之后就可以检查服务器端:
述参与者或子系统之间自上而下(时间维度)的交互。交互主要通过对象之间发送消息来实现。顺序图也可以用来展示出用例图的行为顺序,当参与者执行/触发一个用例时,都会有一条消息从触发者发送给接收者,从而引起状态转换。因为顺序图是按照时间顺序现实对象之间的交互,所以顺序图只能应用于顺序逻辑中,对于并发、异步等场景显得无能为力。
顺序图有四部分:参与者/对象、生命周期线、激活期和消息。
用于从Android设备上的联系人数据库中获取特定电话号码对应联系人姓名的Java类
这段代码的时间复杂度主要取决于数据库查询操作的效率,假设查询操作的平均时间复杂度为O(n),n为数据库中联系人的数量,那么整体的时间复杂度也可以认为是O(n)。
2. Notes.java (定义一些常量和标识符)
这个Notes类主要是一个常量类,定义了一些常量,这里有用于定义与笔记相关的各种常量和标识符,这些常量使代码更加清晰、易于维护,并提高了代码的可读性以及可重用性。
1) NotesDatabaseHelper.java (用于管理便签应用的数据库)
NotesDatabaseHelper类是一个用于管理SQLite数据库的Android帮助类,这个类继承自SQLiteOpenHelper,它提供了创建和管理数据库的方法。
3)NotesProvider.java (用于向数据库提供各种功能(增,删,改,查))
NotesProvider类用于管理应用程序中的笔记数据。
它首先定义了一个投影Projection,指定从数据库查询时应返回哪些列,然后,定义SQL查询,用于从TABLE.NOT中检索满足特定条件的记录,查询基于NoteColumns.SNIPPET进行匹配,用onCreate()方法确保正确处理上下文和生命周期事件。
ContentProvider的实现用到了query(),insert(),update(),delete(),和getType()等方法。
query()方法首先函数定义,在初始化变量,使用switch语句根据URI的类型执行不同的查询
insert()该方法接受一个Uri对象和一个ContentValues对象作为参数,Uri对象用于标识要插入数据的表,而ContentValues对象则包含要插入的实际数据。
其是向数据库插入数据并返回新URI的方法,从逻辑上看,时间复杂度可以认为是O(1)。
delete()
用于从SQLite数据库中删除数据,该方法接受三个参数:一个Uri对象,用于标识要删除的数据的位置;一个selection字符串,用于定义删除数据的条件;以及一个selectionArgs字符串数组,用于提供selection字符串中所需的参数值。
URI_DATA:删除DATA表中的数据。
URI_DATA_ITEM:根据提供的ID删除DATA表中的数据。
default:如果URI不匹配任何已知的类型,则抛出IllegalArgumentException异常。
update()
update方法用于更新数据库中的数据。
gtask.data
处理与任务相关的元数据而设计的。它有一个私有变量mRelatedGid来存储相关的ID,并提供了设置和获取这个ID的方法。
2. Node.java (各种数据对象)
Node类是一个抽象类,定义了一个可以同步的数据节点的基本结构和行为,这个类包含了一些表示节点属性和状态的成员变量,以及一些抽象方法和普通方法,用于操作这些属性和状态。
3.SqlData.java (处理数据库的数据)
4.SqlNote.java (处理数据库的便签数据)
用于处理与笔记相关的数据库操作的工具类,它定义了一些常量来简化数据库查询和日志记录,并可能包含一些方法来执行实际的数据库操作。
PROJECTION_NOTE:一个字符串数组,包含了从NoteColumns类中引用的列名,这些列名对应于数据库中的字段,用于指定数据库查询应该返回哪些列。
接下来构造了三个函数:
1)第一个构造函数:public SqlNote(Context context),用于创建一个新的笔记对象。
2)第二个构造函数:public SqlNote(Context context, Cursor c),用于从一个Cursor对象加载笔记数据。
3)第三个构造函数:public SqlNote(Context context, long id),用于根据给定的ID从数据库加载笔记数据。
涉及到三个私有方法:loadFromCursor(long id), loadFromCursor(Cursor c) 和 loadDataContent()
loadFromCursor(Cursor c)这个方法接收一个Cursor对象作为参数,并从该Cursor中读取笔记数据
公共方法setContent,目的是从传入的JSONObject中解析和设置内容
公共方法getContent,它返回一个JSONObject,根据给定的笔记类型和其他相关属性(如ID、日期等)来构建一个JSON对象,如果mType是Notes.TYPE_NOTE,则还会包括一个数据列表,如果在创建或处理JSON对象时发生错误,该方法将返回null。
setParentId(long id)用于处理某种形式的笔记数据的创建、更新和检索,提供了设置和获取笔记字段的方法,以及提交更改到数据库的方法。
5. Task.java (表示任务对象)
该类继承自Node类
getCreateAction方法,创建动作所需信息的 JSON 对象,这个对象可能用于与服务器通信,以创建一个新的任务,通过使用try-catch块和适当的异常处理,代码确保了即使在生成 JSON 对象时发生错误,也能提供有用的错误信息。
getUpdateAction(int actionId)方法,根据给定的actionId创建一个包含任务更新信息的JSONObject。
setContentByRemoteJSON(JSONObject js)从一个远程传入的JSONObject中设置任务的内容。
getSyncAction的Java方法,该方法接受一个Cursor对象c作为参数,并返回一个整型SYNC_ACTION_*常量,表示同步操作的类型。
时间复杂度主要取决于Cursor对象c的列访问操作和一系列的条件判断,在最佳情况下,所有条件都不满足,代码将直接返回,时间复杂度为O(1),在最坏情况下,代码将执行所有的条件判断,但由于每个条件判断都是独立的,并且不依赖于输入数据的规模,因此整体时间复杂度仍为O(1)。
6.TaskList.java (表示任务列表对象)
TaskList类也是继承自Node类。
getCreateAction方法用于生成一个描述创建新任务列表的JSON对象,用于与服务器通信或进行其他需要JSON表示的任务列表创建操作
getUpdateAction(int actionId) 根据提供的actionId生成一个包含更新操作的JSONObject。
setContentByRemoteJSON(JSONObject js)从传入的JSONObject中提取数据并设置到当前对象中。
setContentByLocalJSON(JSONObject js)方法从JSON对象中读取信息并设置内容,getLocalJSONFromContent()方法则从当前内容生成一个JSON对象。
removeChildTask方法从列表中移除一个指定的Task对象,moveChildTask(Task task, int index) 方法用于列表中移动任务,findChildTaskByGid(String gid) 方法
用于根据全局唯一标识符查找任务。
getChildTaskIndex(Task task) getChildTaskByIndex(int index) getChilTaskByGid(String gid) getChildTaskList() setIndex(int index) getIndex()方法共同构成了一个处理Task对象集合的实用工具集,提供了查找、获取和设置与Task对象相关的索引和属性的功能。
gtask.exception
类继承自RuntimeException,ActionFailureException类可能用于表示在执行某个操作或任务时发生的失败,由于它继承自RuntimeException,这意味着它通常表示编程错误,而不是应用程序应该尝试捕获的异常情况,当在代码中遇到无法恢复的错误时,可以抛出此异常。
2. NetworkFailureException.java (支持小米便签运行过程中的网络异常处理)
继承于Exception类,NetworkFailureException类是一个自定义异常类,用于表示网络请求失败的情况,它提供了三个构造函数,可以根据需要提供不同级别的错误信息,因为其继承自Exception,所以检查型异常,需要在代码中适当处理,通过提供详细的错误信息,NetworkFailureException可以帮助开发者更好地理解和处理网络请求失败的情况。
gtask.remote
login方法的用于处理用户的登录逻辑,与 UI 交互。
tryToLoginGtask的方法,它的主要目的是尝试使用提供的authToken登录到Gtask,如果登录失败,它会尝试刷新或重新获取authToken并再次尝试登录。
用createHttpPost()方法创建一个新的 HTTP POST 请求,并设置了其 URL 和两个请求头:Content-Type 和 AT,然后,它返回这个 HTTP POST 请求对象,以便其他方法可以使用它来发送请求。
getResponseContent(HttpEntity entity) 方法这个方法读取 HTTP 响应的内容,并返回其内容作为字符串。
postRequest()方法在用户已登录的情况下,发送一个包含指定JSON对象的HTTP POST请求到服务器,并返回从服务器响应中解析出的JSON对象。
3. GTaskManager.java (实现本地同步和远端同步等方法)
mInstance:用于实现单例模式的静态成员变量。
mActivity和mContext:分别用于存储与Activity和Context相关的对象,用于访问应用的各种资源和功能。
mContentResolver:ContentResolver对象,用于访问Android内容提供者提供的数据。
mSyncing和mCancelled:分别表示当前是否正在同步和是否已取消同步的布尔变量。
mGTaskListHashMap、mGTaskHashMap、mMetaHashMap:这些HashMap用于存储不同类型的对象(如TaskList、Node和MetaData),键通常是字符串,而值是对应的对象。
mMetaList:一个TaskList对象,用于存储元数据。
mLocalDeleteIdMap:一个HashSet,用于存储要删除的ID。
mGidToNid和mNidToGid:两个HashMap,用于建立全局ID和节点ID之间的映射关系。
上面公共sync()方法是用与 Google Task 服务进行同步,它首先检查同步是否正在进行,然后初始化所需的变量,接着执行同步操作,并在过程中处理可能出现的异常,无论同步是否成功,它都会执行一些清理工作,并确保返回适当的同步状态码。
私有方法initGTaskList(),它的主要功能是初始化一个任务列表
n个任务列表中有m个任务,那么整个操作将执行n * m次基本操作,所以时间复杂度是O(n * m)。
syncContent的私有方法,它的目的是同步内容,主要处理两种类型的笔记同步:一是本地已删除但仍在垃圾桶中的笔记,其次是数据库中存在但不在垃圾桶中的笔记。
首先处理垃圾桶中的记录,然后同步文件夹,最后处理数据库中的笔记记录,根据是否在垃圾桶中来决定执行不同的同步操作,且通过不同的哈希映射来维护记录之间的关联关系,以便后续的同步操作。
syncFolder的私有方法,用于同步文件夹,它主要处理两种类型的文件夹:根文件夹和通话记录文件夹。它通过与内容提供者的交互获取文件夹信息,并根据这些信息执行相应的同步操作,代码采用了良好的错误处理和资源管理实践,确保了稳定性和效率。
GTaskSyncService.java (一段不定的时间运行在后台,不和用户交互的应用组件)
这个服务主要用于同步任务(如与 Google 任务),主要功能是响应两种类型的请求:开始同步和取消同步。当收到开始同步的请求时,它会创建一个新的异步任务并开始执行;当收到取消同步的请求时,它会尝试取消正在进行的同步任务。服务还通过广播来通知其他组件同步的状态和进度
1.BackupUtils
这段代码的主要功能是将指定文件夹(由folderId标识)下的所有便签(Notes)导出到文本格式,并输出到提供的PrintStream对象ps中。导出内容包括每个便签的最后修改日期以及便签的详细内容。代码实现思路是基于Android的内容提供者(ContentProvider)机制,通过ContentResolver查询特定条件下的数据。在查询结果集上,代码通过遍历Cursor对象来逐条处理便签记录。对于每条记录,代码首先提取所需的信息(如最后修改日期和便签ID),然后调用其他方法(如exportNoteToText)来导出文本。
2. BackupUtils
这段代码定义了一个batchDeleteNotes方法,用于批量删除多个便签(Notes)。它接受一个ContentResolver对象和一个包含要删除的便签ID的HashSet作为参数。方法首先检查传入的ID集合是否为空,如果为空或传入null,则记录日志并返回true(虽然这里返回true可能并不合适,因为实际上没有执行任何删除操作)。接下来,方法遍历ID集合,并为每个ID创建一个删除操作,这些操作被添加到operationList列表中。在遍历过程中,如果某个ID等于系统根文件夹的ID(Notes.ID_ROOT_FOLDER),则记录一条错误日志并跳过该ID。最后,方法尝试使用ContentResolver的applyBatch方法执行这些批量删除操作,并根据执行结果返回相应的布尔值。该方法时间复杂度为O(n), 空间复杂度是O(n)。
1. Note.java
这段代码的主要功能是在数据库中创建一条新的便签记录,并返回这条新记录的ID。它首先构建了一个ContentValues对象来存储新便签的各项属性(如创建时间、修改时间、类型、本地修改标记和父文件夹ID),然后通过ContentResolver的insert方法将这条记录插入到数据库中,并从返回的Uri对象中提取新记录的ID。代码的实现思路是遵循Android的数据存储和访问机制。首先,它构建了一个包含新便签数据的ContentValues对象。然后,通过ContentResolver将这些数据插入到数据库中,并获取一个表示新插入数据的Uri对象。接着,从Uri中提取新便签的ID。在整个过程中,代码还进行了必要的异常处理和ID有效性检查。这段代码没有涉及复杂的算法或数据结构,复杂度较低。
这段代码的主要功能是将文本数据(以键值对的形式存储在mTextDataValues中)与特定的便签ID(noteId)关联起来,并将这些数据保存到数据库中。如果mTextDataId为0,说明这是新的数据,需要插入一条新记录;如果mTextDataId不为0,说明已经存在对应的数据库记录,需要更新这条记录。实现思路基于Android的内容提供者(ContentProvider)机制。它首先判断是否需要插入新记录或更新现有记录,然后根据情况执行相应的数据库操作。在插入新记录时,它使用了ContentResolver的insert方法;在更新记录时,它使用了ContentProviderOperation来构建批量操作。
2.WorkingNote.java
这段代码的主要功能是加载指定ID的笔记的详细数据。它使用Android的内容解析器(ContentResolver)查询具有特定ID的笔记数据,并根据数据的MIME类型进行处理,以提取出不同类型的笔记数据(如文本内容、模式、以及其他数据ID等)。代码实现思路基于Android的内容提供者(ContentProvider)机制。通过ContentResolver发起查询请求,并使用Cursor遍历查询结果。根据每条记录的MIME类型,代码执行不同的逻辑分支以处理不同类型的笔记数据。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。