一直想系统的总结一下Android的学习,从浅入深,循序渐进的,对自己目前做一个知识的梳理,明确自己的知识学习体系,为后续拓展体系明确方向,而不是学了新的忘记了旧的,也为以后面试复习的时候提供一个靠谱的知识库。最近,打算坚持看书,做好读书笔记,首先从最基础的郭霖的《第一行代码》开始。
Android系统架构大致可以分为4层5块。Linux内核层,系统运行库层,应用框架层,应用层。
Android系统是基于Linux内核的,这一层为Android设备的各种硬件提供了底层的驱动,如显示驱动,音频驱动,相机驱动,蓝牙驱动,WiFi驱动等等。
这一层通过一些C/C++库来为Android系统提供了主要的特性支持。如SQLit库提供了数据库的支持,OpenGL|es库提供了3d绘图支持,webkit库提供了浏览器内核的支持。
这一层还有一个Android运行时库,主要提供了一些核心库,能够允许开发者使用java语言来编写Android应用。另外,Android运行时库还包含了dalvik虚拟机(5.0之后为art运行环境),它使得每一个Android应用都能够运行在独立的进程当中,并且拥有一个自己的dalvik虚拟机实例。
这一层主要提供了构建应用程序时可能用到的各种API。
所有安装在手机上的应用程序都属于这一层。
参考博客,https://www.jianshu.com/p/69f0d25c727a
Android提供了那些东西可供使用,来开发出优秀的应用程序?
Android系统四大组件,活动Activity,服务Service,广播接收器Broadcast Reciver,内容提供器Content Provider。其中活动是所有Android应用程序的门面,凡是在应用中看得到的东西都是放在活动中的。服务一直在后台默默运行,机试用户退出了应用,服务任然可以继续运行。广播接收器允许你的应用接收来自各处的广播消息,比如电话,短信等,当然你的应用也可以向外发出广播消息。内容提供者为应用程序之间共享数据提供了可能,如你想要读取系统电话本中的联系人,就需要通过内容提供者来实现。
系统控件和自定义控件。
支持标准SQL语法,通过Android封装好的API进行操作,让存储和读取数据变得非常方便。
音乐,视频,录音,拍照,闹铃等等。
手机内置GPS,可以定位。
先看一张图
默认as是这样的目录结构,但这并不是真实的项目结构,而是被as转换过的,这个结构简单明了,适合快速开发。可以切换到其他模式下查看目录,project下才是真实的目录结构。
切换到project下分析一下每个文件是什么负责功能的。
这两个目录下放置的都是as自动生成的一些文件,无需关心,不需要手动编辑。
项目的代码,资源等内容几乎都放在这个目录下,开发工作基本上都是在这个目录下进行的。稍后详细分析。
这个目录主要包含一些在编译时自动生成的文件,也无需关心。
这个目录下包含了gradle wrapper的配置文件,使用gradle wrapper的方式不需要提前将gradle下载好,而是会自动根据本地的缓存情况决定是否需要联网下载gradle。as默认没有启用gradlewrapper的方式。
这个文件是用来将指定的目录或文件排除在版本控制之外。
这是项目全局的gradle构建脚本,通常这个文件中的内容不需要修改。
这个文件是全局的gradle配置文件,在这里配置的属性将会影响到项目中所有的gradle编译脚本。
这两个文件是用来在命令行界面中执行gradle命令的,其中gradlew是在Linux或者mac中使用的,gradlew.bat是Windows系统中使用的。
iml文件是所有的IntelliJ IDEA项目都会自动生成的一个文件,as也是基于IntelliJ IDEA开发的,用于标识这是一个IntelliJ IDEA项目,不需要修改这个文件中的任何内容。
这个文件用于指定本机中的sdk路径,ndk路径,通常内容是自动生成的,并不需要修改,除非本机中的sdk位置发生了变化,那么将这个文件中的路径改成新的位置即可。
这个文件用于指定项目所有引入的模块。通常情况下模块的引入是自动完成的,需要手动修改这个文件的情况也非常少。
这个目录和外层的build目录类似,主要包含了一些在编译时自动生成的文件,不过它里面的内容更多更杂,不要关心。
如果项目中使用到了第三方jar包,需要把这些jar包都放在libs目录下,放在这个目录下的jar包都会自动被自动添加到构建路径里去。
用来编写Android Test测试用例的,可以对项目进行一些自动化测试。
防止java代码的地方。
下面的内容有点多,项目中用到的图片,布局,字符串等资源都要放在这个目录下。图片放在drawable目录下,布局放在layout目录下,字符串放在values目录下。
是整个Android项目的配置文件,程序中定义的四大组件都需要在这个文件里注册,还可以在文件中给应用程序添加权限声明。
其中intent-filter里面的内容非常重要,action配为MAIN,category配为LAUNCHER表示这个活动是项目的主活动,点击手机应用图标,首先启动这个活动。
此处用来编写unit test测试用例的。对项目进行自动化测试的另一种方式。
这个文件用于将app模块内的指定的目录或文件排除在版本控制之外,作用和外层的.gitignore文件类似。
IntelliJ IDEA项目自动生成的文件,不需要关心和修改这个文件中的内容。
这是app模块的gradle构建脚本,这个文件中会指定很多项目构建相关的配置,稍后分析里面具体的内容。
这个文件用于指定项目代码的混淆规则,当代码开发完成后达成安装包文件,不希望被别人破解,通常将代码进行混淆,从而让破解者难以阅读。
Android讲究逻辑和视图分离,不推介在活动中直接编写界面,通用做法是在布局文件中编写界面,然后再活动中引入进来。
drawable开头的,都是用来存放图片的。mipmap开头的用来放应用图标。values开头的存放字符串,样式,颜色等配置。layout存放布局文件。
之所以有这么多的mipmap开头的文件夹,主要是为了让程序能够更好的兼容各种设备。drawable也是相同的道理,drawable-hdpi,drawable-xhdpi,drawable-xxhdpi等文件夹。程序制作过程中最好能够给同一张图片提供几个不同分辨率的版本,分别放在这些文件夹下,然后当程序运行的时候,会自动根据当前运行设备分辨率的高低选择加载哪个文件夹下的图片。当然这是理想情况,更多的时候美工只会给一份图片,这个时候就把所有图片放在drawable-xxhdpi文件夹下就好了。
Android studio是采用Gradle来构建项目的。Gradle是一个非常先进的项目构建工具,它使用了一种基于Groovy的领域特定语言(DSL)来声明项目设置,摒弃了传统基于XML(如ant和maven)的各种繁琐配置。
项目中有两个build.gradle文件,一个是在最外层目录下的,一个是在app目录下的。这两个文件对构建Android studio项目都起到了至关重要的作用。
// 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:3.4.1'
// 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()这行配置,这个jcenter是什么意思呢?其实他是一个代码托管仓库,很多Android开源项目都会选择将代码托管到jcenter上,声明了这行配置之后,就可以在项目中轻松引用任何jcenter上的开源项目了。
接下来,dependencies闭包中使用classpath声明了一个Gradle插件。为什么要声明这个插件呢?因为Gradle并不是专门为构建Android项目而开发的,java,c++等很多种项目都可以使用Gradle来构建因此如果我们想要使用它来构建Android项目,则需要声明com.android.tools.build:gradlel:3.4.1这个插件。最后面的部分是插件的版本号。
这样,最外层的build.gradle文件就分析完了。通常情况下不需要修改这个文件中的内容,除非你想添加一些全局的项目构建配置。
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.xlabs.myhelloworld"
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
这个文件中的内容相对复杂一些,首先第一行应用了一个插件,一般有两种值可选:com.android.application 表示这是一个应用程序模块,com.android.library表示这是一个库模块。应用程序模块和库模块的最大区别在于,一个是可以直接运行的,一个只能作为代码库依赖于别的应用程序模块来运行。
接下来,是一个大的android闭包,在这个闭包中可以配置项目构建的各种属性。其中compileSdkVersion用于指定项目的编译版本,这里指定了28,表示使用Android9.0系统的sdk编译。buildToolsVersion(“28.0.3”)用于指定项目构建工具的版本,在最新的Android studio中可以不指定这个buildToolsVersion,会自动选择与项目的编译版本最匹配的项目构建工具的版本。
然后,在android闭包中嵌套了一个defaultConfig闭包,defaultConfig闭包中可以对项目的更多细节进行配置。其中applicationId用于指定项目的包名,包名一般在创建项目的时候已经指定了,如果后面想修改包名,就得这里进行修改。minSdkVersion用于指定最低兼容的版本,这里指定了21,表示最低兼容到android5.1系统。targetSdkVersion指定的值表示你在该目标版本上已经租了充分的测试,系统将会为你的应用程序启动一些新的功能和特性。比如android6.0系统中引入了运行时权限这个功能,如果你将targetSdkVersion指定成23或者更高,那么系统就会为你的程序启用运行时权限功能,而如果你将targetSdkVersion指定成22,那么久说明你的程序最高只在android5.1系统上做过充分的测试,android6.0系统中引入的新功能自然就不会启用了。** 最后versionCode用于指定版本号,versionName用于指定版本名。
下面是buildTypes闭包。buildTypes闭包中用于指定生成安装文件的相关配置,通常只会有两个子闭包,一个是debug,一个是release。debug闭包用于指定生成测试版安装文件的配置,release闭包用于指定生成正式版安装文件的配置。另外,debug闭包是可以忽略不写的。
看看release闭包中的具体内容,minifyEnabled用于指定是否对代码进行混淆,true表示混淆,false表示不混淆。proguardFiles用于指定混淆时使用的规则文件,这里指定了两个文件,第一个proguard-android-optimize.txt是在android sdk目录下的,里面是所有项目通用的混淆规则,第二个是proguard-rules.pro是在当前项目的根目录下,里面可以编写当前项目特有的混淆规则。需要注意的是,android studio直接运行项目生成的都是测试版安装文件。
这样,整个android闭包就分析完了,接下来是dependencies闭包。这个闭包的功能非常强大,它可以指定当前项目的所有依赖关系。通常android studio项目一共有3种依赖方式:本地依赖、库依赖、远程依赖。
本地依赖可以对本地的jar包或目录添加依赖关系,库依赖可以对项目中的库模块添加依赖关系,远程依赖则可以对jcenter库上的开源项目添加依赖关系。
观察dependencies闭包中的配置,第一行implementation fileTree就是一个本地依赖声明,implementation fileTree(dir: ‘libs’, include: [’*.jar’])它表示将libs目录下所有的.jar后缀的文件都添加到项目的构建路径当中。第二行的implementation则是远程依赖声明,implementation 'com.android.support:appcompat-v7:28.0.0’就是一个标准的远程依赖库格式,其中com.android.support是域名部分,用于和其他公司的库做区分;appcompat-v7是组名称,用于和同一个公司中不同的库做区分;28.0.0是版本号,用于和同一个库不的版本做区分。加上这句声明后,Gradle在构建项目时会首先检查一下本地是否已经有这个库的缓存,如果没有的话则会去联网下载,然后再添加到项目的构建路径当中。至于库依赖声明这里没有用到,它的基本格式是implementation project(path: ‘:downloadinstaller’),这句声明即可,依赖downloadinstaller这个库。