Phần 4 - Setting project
Trong bài viết này, chúng ta sẽ tìm hiểu cách khai báo và cài đặt các thuộc tính trong Gradle và sử dụng chúng trong quá trình phát triển một Android project. Setting project properties Khi chúng ta muốn khai báo một thuộc tính trong Gradle chúng ta có thể sử dụng khối block ext{} trong ...
Trong bài viết này, chúng ta sẽ tìm hiểu cách khai báo và cài đặt các thuộc tính trong Gradle và sử dụng chúng trong quá trình phát triển một Android project.
Setting project properties
Khi chúng ta muốn khai báo một thuộc tính trong Gradle chúng ta có thể sử dụng khối block ext{} trong build.gradle. Tuy nhiên nếu muốn loại bỏ các biến này khỏi build file thì chúng ta có thể sử dụng gradle.properties hoặc sử dụng -P flag từ command line của Gradle. Gradle build files cung cấp một cách đơn giản để định nghĩa thuộc tính là sử dụng khối ext (viết tắt của extra). Đây là một cách thế hiện thuộc tính một lần nhanh chóng và có thể sử dụng trong toàn bộ file gradle build này. Ví dụ sau định nghĩa khai báo một thuộc tính version cho thư viện ngoài:
ext { def AAVersion = '4.0-SNAPSHOT' // change this to your desired version } dependencies { apt "org.androidannotations:androidannotations:$AAVersion" implementation "org.androidannotations:androidannotations-api:$AAVersion" }
Từ khóa def ở đây sẽ chỉ ra property AAVersion là 1 biến cục bộ và chỉ được sử dụng trong file build gradle này. Nếu muốn được sử dụng ở các file gradle build khác thì chúng ta chỉ cần loại bỏ từ khóa def. Một hướng khác khi chúng ta không muốn thể hiện một số thuộc tính ngay trong build file, chúng ta xem xét ví dụ sau:
repositories { maven { url 'http://repo.mycompany.com/maven2' credentials { username 'user' password 'password' } } }
Nếu chúng ta điền 2 giá trị username và password ở ngay đây thì được gọi là giá trị hardcoded, điều này là không tốt khi lập trình vì dễ bị lộ thông tin và khó bảo trì. Thay vào đó, chúng ta có thể sử dụng một file sẵn có khi tạo project Android bằng Android Studio là gradle.properties.
login='user' pass='my_long_and_highly_complex_password'
Và trong khối credentials ở trên sẽ thành
repositories { maven { url 'http://repo.mycompany.com/maven2' credentials { username login password pass } } }
Một cách khác chúng ta có thể gán giá trị từ command line bằng -P flag. Theo ví dụ trên, chúng ta có thể chạy dòng command sau
./gradlew -Plogin=me -Ppassword=this_is_my_password assembleDebug
Để hiểu rõ hơn các cách thế hiện properties trong gradle, chúng ta sẽ thực hiện một task nhỏ trong project của chúng ta, mở file build.gradle và thêm đoạn mã sau
ext { if (!project.hasProperty('user')) { user = 'user_from_build_file' } if (!project.hasProperty('pass')) { pass = 'pass_from_build_file' } } task printProperties() { doLast { println "username=$user" println "password=$pass" } }
Hai dòng lệnh if có tác dụng check xem có 2 thuộc tính đó hay ko, và printProperties() là một Custom Task để in ra các giá trị thuộc tính.
- Trường hợp 1 chúng ta sử dụng ext block
./gradlew printProperties
Kết quả thu được:
> Task :app:printProperties username=user_from_build_file password=pass_from_build_file
- Trường hợp 2 chúng ta khai báo hai thuộc tính user và pass trong gradle.properties
user=tuannt pass=tuan@
Kết quả thu được khi chạy lại task printProperties
> Task :app:printProperties username=tuannt password=tuan@
- Trường hợp 3 chúng ta khai báo thuộc tính ngay trong command line
./gradlew -Puser=user_from_pflag -Ppass=pass_from_pflag printProperties
Kết quả sẽ là:
> Task :app:printProperties username=user_from_pflag password=pass_from_pflag
Như vậy chúng ta đã hiểu rõ hơn về 3 cách khai báo thuộc tính trong một project Android. Vấn đề tiếp theo là làm thế nào để chúng ta tránh được việc bị duplicate và có thể reuse các gradle setting của các module trong một project Android.
Sharing Settings Among Projects
Gradle đã hỗ trợ sẵn cho việc chia sẻ các gradle setting giữa các module bằng từ khóa allprojects và subprojects trong file build.gradle. Khi khởi tạo project Android, trong file top-level build.gradle luôn có một khối allprojects
allprojects { repositories { google() jcenter() } }
Khối allprojects trên được sử dụng cho tất cả các project sử dụng Gradle chứ không duy nhất dành cho Android project. Như vậy tất cả các module nhỏ của project hiện tại sẽ có thể sử dụng được các thuộc tính nằm trong khối này. Ở ví dụ trên thì chúng ta không cần lặp lại việc khai báo khối repositories trong module của project. Một cách khác thay thế chúng ta có thể sử dụng subprojects. Ví dụ
subprojects { apply plugin: 'com.android.library' }
Như vậy trong trường hợp chúng ta có nhiều Android library, mỗi Android library cần khai báo apply plugin: 'com.android.library' trong file build.gradle của library đó. Tuy nhiên với cách trên chúng ta có thể không cần lặp lại việc đó. Điều này giúp dự án của chúng ta được clean and clear hơn và có khả năng reuse tốt hơn.