1.簡(jiǎn)介
1.1 系統(tǒng)架構(gòu)
Android大概分為4層架構(gòu):
- Linux內(nèi)核層
提供底層基本硬件驅(qū)動(dòng)- 系統(tǒng)運(yùn)行層
通過(guò)C/C++提供數(shù)據(jù)庫(kù)、3D、瀏覽器等主要特性- 應(yīng)用框架層
提供構(gòu)建應(yīng)用程序所需API- 應(yīng)用層
手機(jī)上的應(yīng)用程序
1.2 現(xiàn)行版本
主要以5.0在內(nèi)以后的版本居多
1.3 開發(fā)特色
- 四大組件:Activity、Server、BordercastReceiver、ContentProvider
- 豐富的系統(tǒng)控件:可以自己定制
- SQLite數(shù)據(jù)庫(kù):輕量級(jí)、運(yùn)算速度快的數(shù)據(jù)庫(kù),支持SQL語(yǔ)法
- 強(qiáng)大的多媒體
2. 開發(fā)環(huán)境
出問(wèn)題問(wèn)度娘,使用官方的AndroidStudio開發(fā)。
3. 第一個(gè)安卓項(xiàng)目
當(dāng)你打開MyApplication項(xiàng)目會(huì)看到這樣字的目錄

但實(shí)際上的目錄需要把Android換成Project

新版的IDE將目錄簡(jiǎn)化了,所以開發(fā)起來(lái)會(huì)很快。剛開始學(xué)的時(shí)候不會(huì)很明白
下面對(duì)目錄中所有的內(nèi)容進(jìn)行講解
3.1 項(xiàng)目外層目錄
| 文件名 | 解釋 |
|---|---|
| .grand/.idea | AS自動(dòng)生成的文件 |
| app | 項(xiàng)目中的代碼、資源 |
| build | 編譯時(shí)自動(dòng)生成的文件 |
| gradle | 包含了Gradle wrapper文件安裝后沒(méi)有需要手動(dòng)下載 |
| .gitigonore | 用來(lái)將指定目錄或文件排除在版本控制之外 |
| build.grade | 項(xiàng)目布局的gradle構(gòu)建腳本 |
| gradle.properties | gradle配置文件 |
| HelloWorld.iml | 所有的IntelliJ IDEA都會(huì)生成的文件 |
| setting.gradle | 用于指頂項(xiàng)目中所有引用的模塊 |
3.2 app目錄
| 文件名 | 解釋 |
|---|---|
| build | 這個(gè)目錄和外層的build類似,但是文件更多 |
| libs | 如果項(xiàng)目中有第三方j(luò)ar包,就要把jar包放到這里,jar包會(huì)被自動(dòng)添加到項(xiàng)目中 |
| androidTest | 可以對(duì)項(xiàng)目自動(dòng)化測(cè)試 |
| res | 項(xiàng)目中的圖片、布局、字符串資源都在這里,這里也可以添加權(quán)限聲明 |
| test | 編寫UnitTest用,對(duì)項(xiàng)目進(jìn)行自動(dòng)化測(cè)試的另一種方式 |
| .gitigonre | 用于將app模塊內(nèi)指定目錄或文件排除在版本控制之外,和外層的.gitignore類似 |
| app.iml | IDE自動(dòng)生成的文件 |
| build.gradle | 是app獲取模塊的腳本,這個(gè)文件中會(huì)制指定很多項(xiàng)目構(gòu)建相關(guān)配置 |
| proguard-rules.pro | 這個(gè)文件用于制定代碼項(xiàng)目的混淆規(guī)則,當(dāng)代碼開發(fā)完成之后打包成軟件安裝包 |
3.3 HelloWorld是如何運(yùn)行的
打開Android-Mainfest.xml文件,可以看到
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
這段代碼對(duì)MainActivity進(jìn)行注冊(cè),沒(méi)有在這個(gè)文件中注冊(cè)的Activity是不能用的。其中<intent-filter>包含的代碼很重要,<action ...>,<category ...>表示MainActively是這個(gè)項(xiàng)目的主Activity,在手機(jī)上點(diǎn)擊圖標(biāo)啟動(dòng)的就是這個(gè)。
Activity,凡是顯示在應(yīng)用界面內(nèi)的東西都是Activity里的,注冊(cè)看完了那就去看一看MainActivity.kt的代碼
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
首先,MainActivity繼承自AppCompatActivity,AppCompatActivity是AndroidX提供的一種向下兼容的Activity,可以讓Activity在不同版本中保持一致的功能。Activity是Android提供的一個(gè)基類,所有自定義Activity只有繼承它或者它的子類才能獲得Activity的特性,而AppCompatActivity是Activity的一個(gè)子類。
再往下看,我們會(huì)看到一個(gè)onCreate()方法,這個(gè)方法是Activity被創(chuàng)建時(shí)必須執(zhí)行的方法。
然而我們發(fā)現(xiàn),這個(gè)文件中沒(méi)有HelloWord,HelloWorld在哪里呢?
在布局文件res/layout/activity_main.xml這個(gè)文件中。因?yàn)檫@里的布局文件和Activity是分開的,在布局中邊界界面,然后在Activity中引入。
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
布局代碼中,中間有個(gè)<TextView ... />這個(gè)是用來(lái)顯示文字的控件。在這些代碼中,我們終于看到了HelloWorld
找個(gè)HelloWorld都這么費(fèi)勁
3.4 詳解項(xiàng)目中的資源
打開res目錄

發(fā)現(xiàn)有很多mipmap開頭命名的文件夾,它們都是用來(lái)存放圖標(biāo)的目錄。為了讓程序兼容各種設(shè)備,Drawable目錄中的文件也是一樣的道理。所以我們自己在開發(fā)的時(shí)候應(yīng)該自己創(chuàng)建drawable-hdip、drawable-xhdpi、drawable-xxhdip。在作圖的時(shí)候把一個(gè)圖標(biāo)準(zhǔn)備多種分辨率。好麻煩大多數(shù)情況下就放在drawable-xxhdip目錄下就行啦。
3.5 使用這些資源-修改圖標(biāo)
打開res/values/strngs.xml文件
<resources>
<string name="app_name">My Application</string>
</resources>
helloword這個(gè)初始項(xiàng)目中只有這三行代碼,這里看到<string ...>中包含的My Application就是我們的項(xiàng)目名稱。有以下兩種方式去引用它們:
- 在代碼中通過(guò)
R.tring.app_name可以獲得該字符串的引用 - 在XML中通過(guò)
@string/app_name可以獲得該字符串的引用
其中string是可以替換的,圖片就替換成drawable,圖標(biāo)就替換成mipmap,引用的布局文件可以換成layout。
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
...
</application>
在AndroidManifest.xml文件,找到<application>中包裹的代碼。HelloWorld的項(xiàng)目應(yīng)用圖標(biāo)就是通過(guò)android:icon屬性指定的
3.6 build.gradle文件
因?yàn)锳S是使用gradle來(lái)構(gòu)建項(xiàng)目,我們有兩個(gè)build.geadle文件,一個(gè)在外層目錄下、一個(gè)在app目錄中。
先來(lái)看看外層目錄下的build.gradle
buildscript {
ext.kotlin_version = "1.4.0"
repositories {
google()
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:4.0.1"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
這些代碼是自動(dòng)生成的,其中兩處repositories閉包中都聲明了google()和jcenter()這兩行進(jìn)行配置。這兩個(gè)包都對(duì)應(yīng)一個(gè)代碼倉(cāng)庫(kù),google倉(cāng)庫(kù)就是他們自家的擴(kuò)展依賴,jecnter是第三方的開源庫(kù),聲明之后就可以在項(xiàng)目中使用了。
dependencies閉包使用的classpath聲明了兩個(gè)插件:gradle插件和kotlin插件,因?yàn)槿绻獦?gòu)建Android項(xiàng)目需要找到gradle專門用來(lái)構(gòu)建Android的插件,后面的數(shù)字是插件的版本號(hào)。Kotlin插件的意思也差不多一樣,用Kotlin進(jìn)行開發(fā)然后是版本號(hào)。如果使用的是Java開發(fā)就不需要聲明這個(gè)
除非像添加一些全局項(xiàng)目構(gòu)建配置就不需要改動(dòng)這個(gè)文件
接下來(lái)是app目錄下的build.gradel文件,代碼如下:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 30
buildToolsVersion "30.0.2"
defaultConfig {
applicationId "com.example.myapplication"
minSdkVersion 16
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.1'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
第一行應(yīng)用了一個(gè)插件,一般有兩種值可選
- com.android.applaction 表示這是一個(gè)應(yīng)用程序模塊,可以直接運(yùn)行
- com.android.library 表示這是一個(gè)庫(kù)模塊,只能作為代碼庫(kù)運(yùn)行
接下來(lái)兩行應(yīng)用了kotlin-android和kotlin-android-extentions兩個(gè)插件。如果用kotlin開發(fā)安卓,第一個(gè)是必用的。第二個(gè)是Kotlin擴(kuò)展,在后續(xù)開發(fā)時(shí)會(huì)非常的方便。
然后是個(gè)Android閉包閉包中可以配置各種屬性,compileSdkVersion用于指頂項(xiàng)目的編譯版本,后續(xù)跟著的數(shù)字就對(duì)應(yīng)指定版本。
android包里面有defaultConfig,這個(gè)閉包可以進(jìn)行更多細(xì)節(jié)的配置。其中applicationId就是每一個(gè)應(yīng)用的唯一標(biāo)識(shí)符,不能重復(fù),默認(rèn)會(huì)使用我們創(chuàng)建項(xiàng)目時(shí)指定的包名。
minSdkVersion指定兼容的最低版本
targetSdkVersion+指定的值表示系統(tǒng)會(huì)根據(jù)最新系統(tǒng)指定新的特性
versionCode指定項(xiàng)目版本號(hào)
versionName指定項(xiàng)目的版本名
testInstrumentationRunner用于在當(dāng)前項(xiàng)目中啟用JUnit測(cè)試
接下來(lái)看buildTypes閉包,這個(gè)閉包用于指定生成安裝文件的相關(guān)配置,通常會(huì)有兩個(gè)子閉包:debug和release。
debug很明顯能明白它的意思了,release用于指定生成正式版安裝文件的配置。debug可以忽略不寫的。其中release內(nèi)的minifyEnabled用于指定是否對(duì)項(xiàng)目的的代碼進(jìn)行混淆,t混淆,f不混淆。proguardFile執(zhí)行混淆時(shí)使用的規(guī)則文件。這里指定了'proguard-android-optimize.txt'和 'proguard-rules.pro'
總而言之這部分內(nèi)容有點(diǎn)長(zhǎng),不是很像寫
4 log工具
android.unit.log類中提供了5個(gè)方法打印日志
大概的使用方法
Log.d("MainActivity","onCreate execute");
第一個(gè)參數(shù)tag:一般傳入當(dāng)前類名就好,主要用于隊(duì)打印信息進(jìn)行過(guò)濾.
第二個(gè)參數(shù):msg,具體想打印的內(nèi)容
| function | trans |
|---|---|
| Log.v() | 打印最瑣碎的日志 |
| Log.d() | 打印調(diào)試信息 |
| Log.i() | 打印重要信息 |
| Log.w() | 打印警告信息 |
| Log.e() | 打印錯(cuò)誤信息 |
4.1 在hello World中添加log工具
打開hello World的MainActivity,在onCreate方法中添加一行打印日志語(yǔ)句:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d("MainActivity","onCreated execute")
}
運(yùn)行之后在log cat中會(huì)看到一些日志信息
2020-09-17 10:58:01.559 8491-8533/com.example.myapplication D/EGL_emulation: eglMakeCurrent: 0xe17040c0: ver 2 0 (tinfo 0xe1703290)
2020-09-17 10:58:01.622 8491-8533/com.example.myapplication D/EGL_emulation: eglMakeCurrent: 0xe17040c0: ver 2 0 (tinfo 0xe1703290)
2020-09-17 10:58:01.742 8491-8533/com.example.myapplication D/EGL_emulation: eglMakeCurrent: 0xe17040c0: ver 2 0 (tinfo 0xe1703290)
免責(zé)信息
本書內(nèi)容為《第一行代碼》第三版學(xué)習(xí)筆記,本文如有侵權(quán)請(qǐng)練習(xí)我。我會(huì)第一時(shí)間刪除
歡迎學(xué)習(xí)討論,轉(zhuǎn)載請(qǐng)注明連接作者謝謝(鞠躬