編輯:關於Android編程
一個Gradle項目的構建過程定義在build.gradle文件中,位於項目的根目錄下。
一個最簡單的Gradle純Java項目的build.gradle文件包含以下內容:
apply plugin: 'java'這裡引入了Gradle的Java插件。這個插件提供了所有構建和測試Java應用程序所需要的東西。
buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.11.1' } } apply plugin: 'android' android { compileSdkVersion 19 buildToolsVersion 19.0.0 }這裡包括了Android build file的3個主要部分:
上面提到的基本的構建文件需要一個默認的文件夾結構。Gradle遵循約定優先於配置的概念,在可能的情況盡可能提供合理的默認配置參數。
基本的項目開始於兩個名為“source sets”的組件,即main source code和test code。它們分別位於:
* src/main/
* src/androidTest/
裡面每一個存在的文件夾對應相應的源組件。
對於Java plugin和Android plugin來說,它們的Java源代碼和資源文件路徑如下:
* java/
* resources/
但對於Android plugin來說,它還擁有以下特有的文件和文件夾結構:
* AndroidManifest.xml
* res/
* assets/
* aidl/
* rs/
* jni/
注意:src/androidTest/AndroidManifest.xml是不需要的,它會自動被創建。
3.2.1 Configuring the Structure(配置項目結構)
當默認的項目結構不適用的時候,你可能需要去配置它。根據Gradle文檔,重新為Java項目配置sourceSets可以使用以下方法:
sourceSets { main { java { srcDir 'src/java' } resources { srcDir 'src/resources' } } }注意:srcDir將會被添加到指定的已存在的源文件夾中(這在Gradle文檔中沒有提到,但是實際上確實會這樣執行)。
sourceSets { main.java.srcDirs = ['src/java'] main.resources.srcDirs = ['src/resources'] }
android { sourceSets { main { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = ['src'] resources.srcDirs = ['src'] aidl.srcDirs = ['src'] renderscript.srcDirs = ['src'] res.srcDirs = ['res'] assets.srcDirs = ['assets'] } androidTest.setRoot('tests') } }
以上也是將舊構建系統項目遷移到新構建系統需要做的遷移工作。
添加一個插件到構建文件中將會自動創建一系列構建任務(build tasks)去執行(注:gradle屬於任務驅動型構建工具,它的構建過程是基於Task的)。Java plugin和Android plugin都會創建以下task:
* assemble:這個task將會組合項目的所有輸出。
* check:這個task將會執行所有檢查。
* build:這個task將會執行assemble和check兩個task的所有工作
* clean:這個task將會清空項目的輸出。
實際上assemble,check,build這三個task不做任何事情。它們只是一個Task標志,用來告訴android plugin添加實際需要執行的task去完成這些工作。
這就允許你去調用相同的task,而不需要考慮當前是什麼類型的項目,或者當前項目添加了什麼plugin。
例如,添加了findbugs plugin將會創建一個新的task並且讓check task依賴於這個新的task。當check task被調用的時候,這個新的task將會先被調用。
在命令行環境中,你可以執行以下命令來獲取更多高級別的task:
gradle tasks
gradle tasks --all
Java plugin主要創建了兩個task,依賴於main task(一個標識性的task):
* assemble
* jar:這個task創建所有輸出
* check
* test:這個task執行所有的測試。
jar task自身直接或者間接依賴於其他task:classes task將會被調用於編譯java源碼。
testClasses task用於編譯測試,但是它很少被調用,因為test task依賴於它(類似於classes task)。
通常情況下,你只需要調用到assemble和check,不需要其他task。
你可以在Gradle文檔中查看java plugin的全部task。
Android plugin使用相同的約定以兼容其他插件,並且附加了自己的標識性task,包括:
* assemble:這個task用於組合項目中的所有輸出。
* check:這個task用於執行所有檢查。
* connectedCheck:這個task將會在一個指定的設備或者模擬器上執行檢查,它們可以同時在所有連接的設備上執行。
* deviceCheck:通過APIs連接遠程設備來執行檢查,這是在CL服務器上使用的。
* build:這個task執行assemble和check的所有工作。
* clean:這個task清空項目的所有輸出。
這些新的標識性task是必須的,以保證能夠在沒有設備連接的情況下執行定期檢查。
注意build task不依賴於deviceCheck或者connectedCheck。
一個Android項目至少擁有兩個輸出:debug APK(調試版APK)和release APK(發布版APK)。每一個輸出都擁有自己的標識性task以便能夠單獨構建它們。
* assemble:
* assembleDebug
* assembleRelease
它們都依賴於其它一些tasks以完成構建一個APK需要多個步驟。其中assemble task依賴於這兩個task,所以執行assemble將會同時構建出兩個APK。
小提示:gradle在命令行終端上支持駱駝命名法的task簡稱,例如,執行gradle aR命令等同於執行gradle assembleRelease。
check task也擁有自己的依賴:
* check:
* lint
* connectedCheck:
* connectedAndroidTest
* connectedUiAutomatorTest(目前還沒有應用到)
* deviceCheck: 這個test依賴於test創建時,其它實現測試擴展點的插件。
最後,只要task能夠被安裝(那些要求簽名的task),android plugin就會為所有構建類型(debug,release,test)安裝或者卸載。
Android plugin提供了大量DSL用於直接從構建系統定制大部分事情。
通過SDL可以配置一下manifest選項:
* minSdkVersion
* targetSdkVersion
* versionName
* packageName
* package Name for the test application
* Instrumentation test runner
例如:
android { compileSdkVersion 19 buildToolsVersion 19.0.0 defaultConfig { versionCode 12 versionName 2.0 minSdkVersion 16 targetSdkVersion 16 } }
def computeVersionName() { ... } android { compileSdkVersion 19 buildToolsVersion 19.0.0 defaultConfig { versionCode 12 versionName computeVersionName() minSdkVersion 16 targetSdkVersion 16 } }
如果一個屬性沒有使用DSL進行設置,一些默認的屬性值將會被使用。以下表格是可能使用到的值:
Property Name Default value in DSL object Default value versionCode -1 value from manifest if present versionName null value from manifest if present minSdkVersion -1 value from manifest if present targetSdkVersion -1 value from manifest if present packageName packageName value from manifest if present testPackageName null app package name + “.test” testInstrumentationRunner null android.test.InstrumentationTestRunner signingConfig null null proguardFile N/A (set only) N/A (set only) proguardFiles N/A (set only) N/A (set only)
如果你在構建腳本中使用自定義代碼邏輯請求這些屬性,那麼第二列的值將非常重要。例如,你可能會寫:
if (android.defaultConfig.testInstrumentationRunner == null) { // assign a better default... }如果這個值一直保持null,那麼在構建執行期間將會實際替換成第三列的默認值。但是在DSL元素中並沒有包含這個默認值,所以,你無法查詢到這個值。
android { buildTypes { debug { applicationIdSuffix .debug } jnidebug.initWith(buildTypes.debug) jnidebug { packageNameSuffix .jnidebug jnidebugBuild true } } }
以下是一些可能使用到的屬性和默認值:
Property name Default values for debug Default values for release / other debuggable debuggable false jniDebugBuild false false renderscriptDebugBuild false false renderscriptOptimLevel 3 3 packageNameSuffix null null versionNameSuffix null null signingConfig android.signingConfigs.debug null zipAlign false true runProguard false false proguardFile N/A (set only) N/A (set only) proguardFiles N/A (set only) N/A (set only)
src/這意味著BuildType名稱不能是main或者androidTest(因為這兩個是由plugin強制實現的),並且他們互相之間都必須是唯一的。/
android { sourceSets.jnidebug.setRoot('foo/jnidebug') }
android { signingConfigs { debug { storeFile file(debug.keystore) } myConfig { storeFile file(other.keystore) storePassword android keyAlias androiddebugkey keyPassword android } } buildTypes { foo { debuggable true jniDebugBuild true signingConfig signingConfigs.myConfig } } }以上代碼片段修改debug keystory的路徑到項目的根目錄下。在這個例子中,這將自動影響其他使用到debug構建類型的構建類型。
android { buildTypes { release { runProguard true proguardFile getDefaultProguardFile('proguard-android.txt') } } productFlavors { flavor1 { } flavor2 { proguardFile 'some-other-rules.txt' } } }
java虛擬機運行一般都有一個內存界限,超過這個界限,就會報outofmemory。這個時候一般都是存在內存洩漏。解決內存洩漏問題,竊以為分為兩個步驟:分析應用程序是否真
書接上回,我們已經了解了一些關於適配的一些相關概念,接下來我們會了解一下,在設置布局時我們應該注意的地方。盡量不去設定具體的尺寸值。為了確保布局適應各種尺寸的屏幕,在保證
著手開發一款應用的時候,設置或者菜單頁面是可能需要的,但是,那重復的布局會很令人苦惱。新手可能會一項項的重復繪制,有經驗的你或許會用到include,或者用到組合控件。除
1、Handler的由來當程序第一次啟動的時候,Android會同時啟動一條主線程( Main Thread)來負責處理與UI相關的事件,我們叫做UI線程。Android