文章目录
- 项目目录分析
- app目录分析
- AndroidManifest.xml 分析
- MainActivity.kt 分析
- build.gradle 分析
- 最外层目录下的 build.gradle
- app 目录下的 build.gradle
项目目录分析
我们来看一下 src/main/res
下的一些文件:
.gradle
和.idea
:这两个目录下放置的都是 Android Studio 自动生成的一些文件,我们无须关心,也不要去手动编辑。.app
:项目中的代码、资源等内容几乎都是放置在这个目录下的,我们后面的开发工作也基本都是在这个目录下进行的。build
:主要包含了一些在编译时自动生成的文件。gradle
:包含了gradle wrapper
的配置文件,使用gradle wrapper
的方式不需要提前将graqe
下载好,而是会自动根据本地的缓存情况决定是否需要联网下载gradle
。Android Studio 款认没有启用 gradle wrapper 的方式,如果需要打开,可以点击 Android Studio导航栏→File–>Settings→Build,Execution, Deployment→Gradle,进行配置更改。.gitignore
:这用来将指定的目录或文件排除在版本控制之外。build.gradle
:项目全局的gradle
构建脚本,通常这个文件中的内容是不需要修改的。gradle.properties
:全局的gradle
配置文件,在这里配置的属性将会影响到项目中所有的gradle
编译脚本。gradlew
和gradlew.bat
:这两个文件是用来在命令行界面中执行gradle
命令的,其中gradlew
是在 Linux 或 Mac 系统中使用的,gradlew.bat
是在 Windows 系统中使用的。local.properties
:用于指定本机中的 Android SDK 路径,通常内容都是自动生成的、并不需要修改。除非你本机中的 Android SDK 位置发生了变化,那么就将这个文件中的路径改成新的位置即可。settings.gradle
:这个文件用于指定项目中所有引入的模块。由于本项目中就只有一个 app 模块,因此该文件中也就只引入了 app 这一个模块。通常情况下模块的引人都是自动完成的,需要我们手动去修改这个文件的场景可能比较少。
app目录分析
build
:这个目录和外层的build
目录类似,主要也是包含了一些在编译时自动生成的文件,不过它里面的内容会更多更杂,我们不需要过多关心。libs
:如果你的项目中使用到了第三方 jar 包,就需要把这些 jar 包都放在 libs 目录下,放在这个目录下的 jar 包都会被自动添加到构建路径里去。androidTest
:此处是用来编写 Android Test 测试用例的,可以对项目进行一些自动化测试。java
:放置 Java 代码的地方。res
:drawable
系:存放图片。layout
系:存放布局文件的。mipmap
系:用来放置图标,有多个版本的文件夹,是为了适应不同的设备,提高了代码兼容性。values
系:存放字符串、样式、颜色等配置。
AndroidManifest.xml
:整个项目的配置文件,在程序中定义的四大组件(Activity、Service、Broadcast Receiver、Content Provider)都需要在这个文件中注册,还可在此给程序添加权限声明。test
:此处是用来编写 Unit Test 测试用例的,是对项目进行自动化测试的另一种方式。.gitignore
:用于将 app 模块内的指定的目录或文件排除在版本控制之外,作用和外层的 .gitignore 文件类似。build.gradle
:这是 app 模块的 gradle 构建脚本,这个文件中会指定很多项目构建相关的配置。proguard-rules.pro
:用于指定项目代码的混淆规则,当代码开发完成后打成安装包文件,如果不希望代码被别人破解,通常会将代码进行混淆,从而让破解者难以阅读。
举个例子,打开 res/values/strings.xml
文件:
<resources><string name="app_name">Hello Android</string>
</resources>
这里定义了一个应用程序名的字符串,我们有以下两种方式来引用它:
- 在代码中通过
R.string.app_name
可以获得该字符串(intent-test
)的引用。 - 在 XML 中通过
@string/app_name
可以获得该字符串(intent-test
)的引用。
其中 string
部分是可以替换的,如果是引用的图片资源就可以替换成 drawable
,如果是引用的应用图标就可以替换成 mipmap
,如果是引用的布局文件就可以替换成 layout
,以此类推。
AndroidManifest.xml 分析
android:allowBackup
属性:Android 2.2中引入的一个系统备份的功能。允许用户备份系统应用和第三方应用的 apk 安装包和应用数据,以便在刷机或者数据丢失后恢复应用,用户即可通过 adb backup 和 adb restore 来进行对应用数据的备份和恢复。android:icon
属性:指定项目的应用图标。android:label
属性:指定应用的名称。这里对资源引用的方式正是上面讲strings.xml
文件时提到的在 XML 中引用资源的语法。android:roundIcon
属性:与android:icon
类似,只是指定项目的圆形图标,适配为 Android 8.0 新增的mipmap-anydpi-v26
。(详情见:application中 android:icon 和 android:roundIcon 的区别)android:supportsRtl
属性:声明项目是否支持从右到左(RTL,Right-to-Left)的布局。从 Android 4.2 开始,Android SDK 支持一种从右到左(RTL,Right-to-Left)UI布局的方式,尽管这种布局方式经常被使用在诸如阿拉伯语、希伯来语等环境中,中国用户很少使用。android:theme
属性:指定项目的主题。(详情见:Android Theme 常见主题风格详解)<activity/>
:表示对MainActivity
进行注册,没有注册的活动是不能使用的。android:name
指定具体注册哪一个活动,由于最外层的<manifest>
标签中已经通过package
属性指定了用户的包名,所以用.
表示省略包名。android:label
指定活动中的标题栏的内容。需要注意的是,给主活动指定的label
不仅会成为标题栏,而且还会成为Laucher
中应用程序的名称。intent-filter
是拦截器,定义了整个项目的主Activity
,其中的<action …… />
和<category …… />
两行语句定义该活动为程序的主活动。打开应用首先启动的就是这个活动。- 如果一个程序没有主活动,那么一般这样的程序都是作为第三方服务供其他应用在内部进行调用的。
MainActivity.kt 分析
MainActivity.kt
是用 kotlin
实现的代码文件,可以类比于 C++/JAVA
的 main
文件/函数:
上图红框的意义是:MainActivity
继承了 AppCompatActivity
。
那么什么是
AppCompatActivity
呢?
AppCompatActivity
是 Acitivity
的子类。Android 21
(也就是 Android 5
)之后引入了 Material Design
的设计方式,为了支持 Material Color 、调色板、toolbar 等各种新特性,AppCompatActivity
就应运而生,其不仅兼容旧有的 ActionBarActivity
,更是引入了AppCompatDelegate
类的设计,可以在普通的 Acitivity
中使用 AppCompate
的相关特性。
那么什么是
Acitivity
呢?
Activity类
是 Android
提供的一个基类,项目中所有程序员自定义的 Activity
都必须继承 基类Activity
或者 基类Activity的子类
,从而获得一个 Activity
的特性。
onCreate
与Create
在 view类
中,Create
是虚函数、由框架调用,用来 生成一个窗口的子窗口。 而 OnCreate
函数是用来表示 一个窗口正在生成,是一个活动被创建时必定要执行的方法。
一个窗口创建(Create
)之后,会向操作系统发送 WM_CREATE
消息,OnCreate()
函数主要是用来响应此消息的,因此又被叫做消息响应函数。其只是在窗口显示前设置窗口的属性,如风格、位置颜色等;实现我们要在窗口里面增加的东西,例如按扭,状态栏,工具栏等。这些子窗口一般定义成类中的一个成员变量,以保证生命周期的正确性。
Android
中Bundle类
的作用.
Bundle类
类似于 Map
,用于存放 key-value
键值对形式的值。相对于 Map
,它提供了各种常用类型的 put/get
方法,如:putString()/getString()
和 putInt()/getInt()
,put()
用于往 Bundle
对象放入数据,get()
方法用于从 Bundle
对象里获取数据。Bundle
的内部实际上使用了 HashMap类型
的变量来存放 put()
方法放入的值。
savedInstanceState
和onSaveInstanceState()
在 Activity
的生命周期中,只要离开了可见阶段,或者说失去了焦点,Activity
就很可能被进程 KILL 掉,这时候,就需要一种能保存当时的状态的机制—— savedInstanceState
。当一个 Activity
在 PAUSE 时,被 KILL 之前,它可以调用 onSaveInstanceState()
来保存当前 Activity
的状态信息。用来保存状态信息的 Bundle
会同时传给两个 method
,即 onRestoreInstanceState()
和 onCreate()
。
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {// override 确保该函数(即onCreate)为基类(即Activity)的虚函数并在此进行重写。super.onCreate(savedInstanceState)// 调用其父类Activity的onCreate方法来实现对界面的图画绘制工作。// 其实这条语句放在子类中的onCreate方法中的任何位置都可,问题只是该语句必须要被执行,所以,最好放在第一行,避免遗忘。// Activity中的onCreate方法中已经实现了一些基本操作,如果子类没有缺少super.onCraete,会导致子类中的onCreate方法功能不全。setContentView(R.layout.activity_main)// 作用:加载一个界面。Android讲究逻辑与视图分离,所以在Activity是不写界面的,界面是放在局部文件里面的。// 该方法中传入的参数是”R.layout.activity_main“,其含义为R.java类中静态内部类layout的静态常量activity_main的值,// 而该值是一个指向res目录下的layout子目录下的activity_main.xml文件的标识符,// 因此代表着显示activity_main.xml所定义的画面/布局。}
}
我们来看一下上面代码提到的 activity_main.xml
:
<TextView/>
:该控件用于在布局中显示文字。
build.gradle 分析
Android Studio 采用 Gradle 来构建项目的。Gradle 是一个非常先进的项目构建工具,它使用了一种基于 Groovy 的领域特定语言(DSL)来声明项目设置,摒弃了传统基于 XML(如 Ant 和 Maven)的各种烦琐配置。
在上文我们提到项目中有两个 build.gradle
文件,一个是在最外层目录下的,一个是在 app 目录下的。
最外层目录下的 build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {repositories {google()jcenter()}dependencies {classpath "com.android.tools.build:gradle:4.1.3"// NOTE: Do not place your application dependencies here; they belong// in the individual module build.gradle files}
}allprojects {repositories {google()jcenter()}
}task clean(type: Delete) {delete rootProject.buildDir
}
repositories
闭包:声明项目托管的仓库。jcenter()
配置:是一个代码托管仓库,很多 Android 开源项目都会选择将代码托管到 jcenter 上,声明了这行配置之后,我们就可以在项目中轻松引用任何 jcenter上的开源项目了。
dependencies
闭包:声明项目的依赖关系。classpath
环境变量:因为 Gradle 并不是专门为构建 Android 项目而开发的,Java、C++ 等很多种项目都可以使用 Gradle 来构建。因此如果我们要想使用它来构建 Android 项目,则需要声明 com.android.tools.build:gradle:4.1.3 这个插件。数字部分是插件的版本号。
app 目录下的 build.gradle
plugins {id 'com.android.application'
}android {compileSdkVersion 30buildToolsVersion "30.0.0"defaultConfig {applicationId "com.example.intent_test"minSdkVersion 16targetSdkVersion 30versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}
}dependencies {implementation 'androidx.appcompat:appcompat:1.1.0'implementation 'com.google.android.material:material:1.1.0'implementation 'androidx.constraintlayout:constraintlayout:1.1.3'testImplementation 'junit:junit:4.+'androidTestImplementation 'androidx.test.ext:junit:1.1.1'androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
plugins
闭包:有两种插件可供选择 ——'com.android.application'
表示这是一个应用程序模块,可以直接运行;com.android.library
表示这是一个库模块,只能依附别的应用程序模块来运行。android
闭包:compileSdkVersion
:用于指定项目的编译版本,这里指定成 30 表示使用 Android 11.0 系统的 SDK 编译。buildToolsVersion
:用于指定项目构建工具的版本。
android
闭包内嵌的defaultConfig
闭包:applicationId
:用于指定项目的包名,在创建项目的时候其实已经指定过包名了,如果后续想对其进行修改,那么就是在这里修改的。minSdkversion
:用于指定项目最低兼容的 Android 系统版本,这里指定成 16 表示最低兼容到 Android 4.1 系统。(具体设置应该根据下载的模拟器)targetSdkVersion
:应用程序会启用指定版本上最新的功能和特性。比如说 Android 6.0 系统中引人了运行时权限这个功能,如果你将 targetSdkVersion 指定成 23 或者更高,那么系统就会为你的程序启用运行时权限功能,而如果你将 targetSdkVersion 指定成 22,那么就说明你的程序最高只在 Android 5.1 系统上做过充分的测试,Android 6.0 系统中引入的新功能自然就不会启用了。versionCode
:用于指定项目的版本号。versionName
:用于指定项目的版本名。testInstrumentationRunner
:指定测试模块。
buildTypes
闭包:用于指定生成安装文件的相关配置,通常只会有两个子闭包,一个是debug
,一个是release
。debug 闭包用于指定生成测试版安装文件的配置,release 闭包用于指定生成正式版安装文件的配置。另外,debug 闭包是可以忽略不写的,因此我们看到上面的代码中就只有一个 release 闭包。release
闭包:minifyEnabled
:用于指定是否对项目的代码进行混淆,true 表示混淆,false 表示不混淆。proguardFiles
:用于指定混淆时使用的规则文件,这里指定了两个文件,第一个proguard-android-optimize.txt
是proguard-android.txt
的功能增加版本,在 Android SDK 目录下,里面不仅包含所有项目通用的混淆规则,而且开启了Proguard optimize
的功能;第二个proguard-rules.pro
是在当前项目的根目录下的,里面可以编写当前项目特有的混淆规则。
compileOptions
闭包:用于调试跟踪和测试。dependencies
闭包:可以指定当前项目所有的依赖关系。通常 Android Studio 项目一共有 3 种依赖方式:- 本地依赖可以对本地的 Jar 包或目录添加依赖关系;
- 库依赖可以对项目中的库模块添加依赖关系;
- 远程依赖则可以对 jcenter 库上的开源项目添加依赖关系。