2024年Android最新百度T6团队实力打造!Gradle-与-Android-构建入门-系统教程,2024年最新2024Android最新大厂面试真题总结

最后

希望大家能有一个好心态,想进什么样的公司要想清楚,并不一定是大公司,我选的也不是特大厂。当然如果你不知道选或是没有规划,那就选大公司!希望我们能先选好想去的公司再投或内推,而不是有一个公司要我我就去!还有就是不要害怕,也不要有压力,平常心对待就行,但准备要充足。最后希望大家都能拿到一份满意的 offer !如果目前有一份工作也请好好珍惜好好努力,找工作其实挺累挺辛苦的。

这里附上上述的面试题相关的几十套字节跳动,京东,小米,腾讯、头条、阿里、美团等公司19年的面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。

由于篇幅有限,这里以图片的形式给大家展示一小部分。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

无论是否意识到 Gradle 的存在,每位 Android 程序员都会直接或间接的与 Gradle 打交道。每当通过 Android Studio 新建一个工程时,AS 都会自动创建一个通用的目录结构,然后就可以进行开发,在 app 的 build.gradle 中添加一些依赖,点击右上角的 Sync Now,编写代码,点击绿色小箭头 Run 运行代码,一切都这么美好,除了偶尔Sync Now 会失败变为 Try Again,如果经过几次 Try Again,问题还没有解决,打开浏览器,粘贴对应报错,查找解决方案,复制粘贴解决方案,点击 Try Again,问题解决,生活还是那么美好。

如果你想要了解问题为什么会发生,为什么这样做会解决问题,那么你需要脱离 AS 那几个常见的按钮,探索它背后的秘密—Gradle,这一自动化构建工具。

本文将介绍:

  1. 为什么需要自动化构建工具?
  2. 默认创建的 Android 工程都有什么
  3. 依赖管理
  4. 打包流程

通过阅读本文,可以大致了解 Gradle 是如何工作,可以有针对性搜索相关内容,更加快速的解决常见编译错误

为什么需要自动化构建工具?

以下命令只是示例,方便说明问题,具体使用方式请查找相关命令手册用法

我们知道,一个 APK 包其实是一个 zip 包,包含代码和资源。那么我们可以编写一个Shell 脚本,命名为 assemble.sh,任何人只要通过执行这个脚本就可以得到 apk 包,完美:

  1. 将 .java 文件转换为 .class 文件,执行命令: javac xxx.java
  2. Android 还会将 .class 文件转换为 .dex 文件: dx xxx.class
  3. 打包成 apk: zip xxx.apk [需要打包的代码和资源]

在 Android 中代码对资源是通过 R.java 文件引用,于是需要继续添加命令,并要求这个命令在 javac 命令前执行。在实际开发中我们不可能所有功能都自己实现,有可能会依赖优秀的开源库,修改后的伪代码如下:

  1. 生成 R.java: aapt [资源文件]
  2. 将 .java 文件转换为 .class 文件,执行命令: javac xxx.java R.java -classpath xxx.jar
  3. Android 还会将 .class 文件转换为 .dex 文件: dx xxx.class R.class xxx.jar
  4. 打包成 apk: zip xxx.apk [需要打包的代码和资源]

一切似乎都尽在掌握之中,真的吗?让我们看看 Android APK 实际打包的流程是什么样的:

想想实现如此复杂流程的 Shell 脚本是不是有些头大?别急,实现后还会遇到下面这些问题:

  • 对于多个工程,每个工程都需要拷贝上述 Shell 脚本
  • 对于单个工程,每次添加一个功能都需要在原有流程中插入一段代码,随着需求增加,脚本难以维护
  • 如何管理引入的外部依赖?如何打 debug、release 包?如何打多渠道包?

此时我们需要一个简化上述过程的工具,通过一些约定,如将代码、资源等放在指定目录,再辅以构建脚本就可以快速得到最终的构建产物,这就是自动化构建工具,而 Gradle 就是其中一个。

对照刚刚那个简单的例子,每一个工程在 Gradle 中叫做一个 Project,每一个需要执行的任务,如生成 R 文件、编译 java 文件等,在 Gradle 中叫做一个 Task。通过 TaskA.dependsOn(TaskB)可以实现先执行 TaskB 再执行 TaskA 的效果。同时 Gradle 也提供 doFirst、doLast 允许在每个 Task 前和后执行一些代码。

至此,我们知道为什么需要自动化构建工具:

  • 防止手动介入构建
  • 创建可重复的构建
  • 以及最重要的:提升编程效率,将精力集中在需求开发上

默认创建的 Android 工程都有什么

每当通过 Android Studio 新建一个工程时,AS 都会自动创建如上图所示的目录结构,图片中简单介绍了各个目录是干什么的,接下来为大家详细介绍每一个目录或者文件的含义:

.gradle 与 .idea

.gradle 与 .idea 存放 Gradle 和 AS 对于当前工程的缓存。

最常见的一个应用就是点击 sync 后,AS 会在每个工程下生成 .iml 文件,他们与 .gradle、.idea 配合为我们提供了代码提示等常见功能。所以如果你的代码飘红而你确认依赖没有问题,可以尝试下面步骤清除 AS 缓存:

  • 删.idea 删.gradle 文件
  • 命令行执行 ./gradlew clean
  • 选择 File -> invalidate caches/restart
  • Sync

gradle/wrapper 与 gradlew gradlew.bat

当我们初次配置 Android 环境时,需要安装 Java,安装 AS,但并不需要安装 Gradle,这其中就是 gradle/wrapper 的功劳。

当执行 gradlew 脚本时,它可以保证每个项目都使用自己期望的 Gradle 版本,而其中的奥秘就在 gradlew 的这段代码中

exec “ J A V A C M D " " JAVACMD" " JAVACMD""{JVM_OPTS[@]}” -classpath “ C L A S S P A T H " o r g . g r a d l e . w r a p p e r . G r a d l e W r a p p e r M a i n " CLASSPATH" org.gradle.wrapper.GradleWrapperMain " CLASSPATH"org.gradle.wrapper.GradleWrapperMain"@”

gradlew 并没有直接启动 Gradle 而是启动 gradle-wrapper.jar,它会判断如果没有 Gradle 环境,从 gradle-wrapper.properties 中的 distributionUrl 中下载相应环境,并启动 Gradle。

因为 Gradle 允许命令行启动时附加参数来自定义 Gradle 的运行环境,所以百度app通过自定义 gradle-wrapper.jar,实现通过配置文件为不同内存大小的电脑、debug/release 包指定不同 gradle 运行内存,提升大家编译速度。

setting.gradle

setting.gradle 中最关键的就是其提供的 include 方法,通过这个方法可以指定哪些工程需要参与编译,每一个参与编译的工程 Gradle 会为它创建一个 Project 对象

根目录 build.gradle

首先是 buildscript 代码块: gradle 默认是自顶向下执行,无论 buildscript 代码块在哪,它都会第一个执行

接下来是 repositories 和 dependencies: repositories 表示 dependencies 声明的依赖去哪些仓库找,google、jcenter、mavenCentral 都是第三方 Maven 仓库。同时,也可以通过 maven 方法添加自己的 Maven 仓库。需要注意的是,不应该假设组件一定会从特定仓库拉取,如果 Gradle 请求一个仓库超时,它会自动请求其他仓库。

dependencies:代表 Gradle 执行需要哪些依赖。比如需要 Android Gradle Plugin 插件为我们打包 apk 包,就需要添加: classpath ‘com.android.tools.build:gradle:3.4.0’

最后是 allprojects 和 repositories: 在 allprojects 中的配置会对所有工程生效而里面的 repositories 则表示工程声明的 dependencies 去哪些仓库查找

app build.gradle

首先可以看到 apply plugin: ‘com.android.application’,当应用这个插件后,它会为我们创建一系列 Task,比如 assembleDebug、assembleRelease,执行这些 Task,就会得到最终的 APK。

android 代码块是插件为我们提供的 API允许我们修改 Task 的行为。

dependencies 代码块的内容决定当前 Project 依赖哪些组件,而不同的依赖声明会有不同的结果,具体内容我们在下一节分析。

依赖管理

依赖配置

在 Android Gradle Plugin 3.0 时代,Google 使用 implementation 和 api 选项取代过去的 compile 选项。既然接口都变了,Google 索性将其他的配置项也进行了改名,方便大家理解其配置的含义。需要注意的是,老版本的接口没有被立刻删除,但是在下一个主要版本中会被删除。下面是各个配置项的官方中文解释:

举个例子: 假设 A 依赖 B,B 依赖 C。
如果 B 对 C 使用 implementation 依赖,则 A 无法调用 C 的代码
如果 B 对 C 使用 api 依赖,则 A 可以调用 C 的代码
如果 B 对 C 使用 compileOnly 依赖,则 A 无法调用 C 的代码,且 C 的代码不会被打包到 APK 中
如果 B 对 C 使用 runtimeOnly 依赖,则 A、B 无法调用 C 的代码,但 C 的代码会被打包到 APK 中

实际上每一个组件都有自己的 compileClasspath 和 runtimeClasspath
当一个组件参与编译时,Gradle 就会将其放在 compileClasspath 中
当一个组件参与打包时,Gradle 就会将其放在 runtimeClasspath 中

不同的依赖配置项,其实就是将声明的依赖放入不同组件的不同的 classpath 中,回到上面的例子 对于 implementation ,其实就是将 C 放入 B 的 compileClasspath 和 runtimeClasspath,放入 A 的 runtimeClasspath 中,从而实现 A 如果调用 C 的代码,在 A 的编译阶段 javac 报错,但最终 C 会被打包到 APK 包中

对于 api、compileOnly、runtimeOnly 原理相同

源码与二进制

当想要依赖一个源码工程时只需要这样写: implementation project(‘:demo:mylibrary’)

而且我们可以明确知道 mylibrary 中的依赖都会被正确打包到 APK 中

当我们依赖二进制需要这样写: implementation ‘androidx.appcompat:appcompat:1.0.2’

当执行依赖命令(只输出 release 包的 runtimeClasspath):
./gradlew :app:dependencies --configuration releaseRuntimeClasspath > dependencies.txt

输出依赖关系图时会看到并不是仅仅依赖一个 appcompat 组件(只显示部分依赖),还包含该组件自己的依赖,以及依赖的依赖,直到组件自身没有依赖,这样的特性叫做依赖传递

releaseRuntimeClasspath - Resolved configuration for runtime for variant: release

— androidx.appcompat:appcompat:1.0.2

±-- androidx.annotation:annotation:1.0.0

±-- androidx.core:core:1.0.1

| ±-- androidx.annotation:annotation:1.0.0

| ±-- androidx.collection:collection:1.0.0

| | — androidx.annotation:annotation:1.0.0

| ±-- androidx.lifecycle:lifecycle-runtime:2.0.0

| | ±-- androidx.lifecycle:lifecycle-common:2.0.0

| | | — androidx.annotation:annotation:1.0.0

| | ±-- androidx.arch.core:core-common:2.0.0

| | | — androidx.annotation:annotation:1.0.0

| | — androidx.annotation:annotation:1.0.0

| — androidx.versionedparcelable:versionedparcelable:1.0.0

| ±-- androidx.annotation:annotation:1.0.0

| — androidx.collection:collection:1.0.0 (*)

±-- androidx.collection:collection:1.0.0 (*)

±-- androidx.cursoradapter:cursoradapter:1.0.0

那么 Gradle 是怎么确定这些依赖呢?当使用Maven 规范上传组件时,不单单会上传组件的二进制,还会上传一个 pom.xml 文件,依赖信息就在这个文件当中。

题外话

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在IT学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多程序员朋友无法获得正确的资料得到学习提升,故此将并将重要的Android进阶资料包括自定义view、性能优化、MVC与MVP与MVVM三大框架的区别、NDK技术、阿里面试题精编汇总、常见源码分析等学习资料。

【Android思维脑图(技能树)】

知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。

希望我能够用我的力量帮助更多迷茫、困惑的朋友们,帮助大家在IT道路上学习和发展~

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 27
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值