文章目錄
- 項目目錄分析
- 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 庫上的開源項目添加依賴關系。