自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

為什么要開發(fā)Android庫?

移動開發(fā) Android
這次分享由我們的 Emanuele Zattin 分享一些他在開發(fā) Java 和 C/C++ 庫上的一些最佳實踐。探討下 API 設(shè)計,CI 技術(shù),以及對于性能的看法,你會了解到對你工作很有幫助的一些工具。

不論是你要執(zhí)行一個特定的任務(wù),模塊化你的代碼,或者只是為了更優(yōu)雅地重用你的代碼,有些時候,作為開發(fā)者,通常會考慮開發(fā)庫來實現(xiàn)。但開發(fā)庫是個挺困難的事情。由 Bay Android Dev Group 主辦,這次分享由我們的 Emanuele Zattin 分享一些他在開發(fā) Java 和 C/C++ 庫上的一些***實踐。探討下 API 設(shè)計,CI 技術(shù),以及對于性能的看法,你會了解到對你工作很有幫助的一些工具。

為什么要開發(fā)Android庫?

為什么要開發(fā) Android 庫?

為了追求更簡潔的代碼和更好的代碼管理,我們通常需要把代碼拆分成不同的邏輯單元,所以,開發(fā) Android 庫的***個原因就是為了模塊化。這也引申出我們開發(fā)庫的第二個原因:代碼重用。一旦你的代碼模塊化后,你可以將它用在很多不同的地方。相比高耦合度的代碼,基于庫的代碼管理讓你更容易的替換其中的代碼,以適應(yīng)不同的場景。還有一個原因,其實就是 “虛榮”,如果你有一個很不錯的想法或者提出一種新的解決特定問題的方案,寫個庫會是一個將這個想法分享給全世界,并且讓大家都能用到的一個好辦法。

為什么是開發(fā) Android 庫而不是 Java 庫呢?如果你的庫要和 Android 的 UI,消息系統(tǒng),設(shè)備傳感器,或者原生代碼打交道,那么你只能開發(fā) Android 庫,而不是 Java 庫。

我們開始前,首先,打開你的 Android Studio,并且新建一個項目!Android Studio 并不支持直接新建一個新的庫,這里有幾種解決辦法,如下:

方法一 - Hack 方案:

  • 創(chuàng)建 Application Project
  • 添加 Library Project
  • 刪除 Application Module

簡單粗暴效果好

方法二 - 使用命令行,Android 自帶了很多很多的工具,創(chuàng)建 Android 庫也是其中的一個命令。傳入一個 ID 參數(shù)允許你指定特定的編譯 版本,也可以通過傳參指定項目包名,以及你想要運行的 Gradle 的版本。 Gradle 是一個極其有用和靈活的自動化構(gòu)建工具,你可以非常容易地運行各種插件,來加速你的開發(fā),比 Maven 和 Ant 不知道高到哪里去了。

第二步: 代碼,代碼,代碼!

在開發(fā)庫的時候,API 設(shè)計非常重要, Joshua Bloch 是這方面的專家,他的 Effective Java 盡管是基于 Java 1.5, 但仍然有很多有價值的技巧。他曾經(jīng)做過一個 名叫 如何設(shè)計優(yōu)秀的 API,為何如此重要 的精彩的演講,因此我想分享一些他在 API 設(shè)計上的一些觀點。

那么,一個好的 API 應(yīng)該具備哪些特點?

簡單易學(xué),你并不想讓開發(fā)者不斷地去查看文檔,因此你在設(shè)計時候的命名法、類名和參數(shù)名一定要盡可能的不言自明。

  • API 要少出錯,所以要把 API 設(shè)計得堅如磐石。
  • API 一定要易讀,易維護,畢竟你在很長一段時間內(nèi)要和這些代碼打交道,特別是它一旦流行開以后,你會收到很多的新功能的請求和漏洞報告。
  • API 的可擴展性也至關(guān)重要。想想 Jenkins :雖然不是一個 API,但是他是一個非常成功的開源項目,一部分原因是因為他易于擴展,以及為他開發(fā)插件。
  • ***,你一定要明確你的受眾,不論受眾是你自己、你的團隊、你工作所在的公司或是整個世界,你的 API 都要做到對你的受眾友好。

測試很重要,對庫而言更加重要,因為你無法預(yù)知你的受眾將如何去使用它們。很幸運的是,在 Android 上測試庫跟測試 App 差異并不大。你可以使用 Android TestCase ,也可以用一些其他的 Android 測試工具框架來做測試。

Android 的測試組件一個不好的地方就是大家通常會卡到 JUnit 3 上,尤其是你發(fā)現(xiàn)你不能用類似 Robolectric 這樣不支持 Native 代碼的工具。JUnit3 不支持一個對庫開發(fā)很重要的測試特性:參數(shù)化測試。如果你想用一些列測試參數(shù)來測試的方法,你可以試試用 Square 開發(fā)的一個叫: Burst 的庫。它很好地解決了這個問題。

自動化你的測試! Jenkins 是一個非常贊的工具來解決實現(xiàn)自動化測試。他提供了超過 1000 個插件,其中一些專為 Android 開發(fā)設(shè)計。我強烈推薦以下插件:

  • Job Config History 插件, 它可以在出狀況的時候通過配置文件重新恢復(fù)現(xiàn)場。
  • Git 插件,以及與他類似的一些插件,比如: GitHub , GitHub pull request , GitLab , 等等。
  • 讓執(zhí)行任務(wù)和自動化變得簡單的 Gradle 插件。Gradle 非常擅長自動化,你可以在 Jenkins 的 Gradle 里運行很多你自己的操作邏輯。
  • Android Emulator 插件,這個不僅僅是個模擬器。 當你想要測試不同屏幕分辨率以及內(nèi)存使用的時候,這個插件非常有用。

另一個測試方案是寫測試用的 App。這種方案在很多時候都很有用:它可以幫你驗證你的測試用例,間接地測試,而且可以確保你的 App 不會崩潰或者無響應(yīng)。想要做測試 App,推薦用 Gradle 的 這個插件 ,它同時支持發(fā)送指令給不同的 Android 設(shè)備。

在你準備要發(fā)布你的庫的時候,你會作何選擇?目前有兩個選擇:發(fā)布 Jar, 或者發(fā)布 Aar(Android 歸檔文件),如果你還不知道 Aar,我來做個簡單介紹,Aar 是 Google 為了能讓庫文件包含 UI 元素而提出的一種文件格式,他可以讓你不僅僅包含 Java 類,還可以存儲數(shù)據(jù)和資源在里面。他在 Android 和 Android Studio 上非常有用,Ant 和 Eclipse 并不支持這種格式。

一個不好的事情是盡管使用本地的 Aar 是可行的,有兩種方案來實現(xiàn)這個,但他們都很麻煩。尤其是你想用你剛剛生成的 Aar 來做 App 測試。所以,如何選擇發(fā)布哪種格式,***就歸結(jié)為,你是否必須要支持 Eclipse,如果是,那么沒得選,只能用 Jar。

問題產(chǎn)生的原因就是因為 Android Gradle 插件產(chǎn)生的是 Aar,而不是 Jar 文件,盡管如此,事實上 Jar 文件舊包含在 Aar 文件里,其實你只要復(fù)制出來 Jar 文件,然后重命名他就好了。下面的代碼就是一個簡單的 Gradle Demo 來做這件事情: 拷貝文件(通常會被命名為:’classes.jar’),然后重命名成你想要的名字。

 

  1. task generateJar(type: Copy) { 
  2.     group 'Build' 
  3.     description 'blah blah...' 
  4.     dependsOn assemble 
  5.     from 'build/intermediates/bundles/release/classes.jar' 
  6.     into 'build/libs' 
  7.     rename('classes.jar''awesome-library.jar'

 

下一個問題是:我們應(yīng)該發(fā)布在哪?如果你計劃開源它,那么想都不用想,就用酷炫的 Bintray 。Bintray 盡管需要你準備更多的東西,但依舊用起來非常簡單。僅僅需要一個源碼 Jar 文件,以及一個 Javadoc 的 Jar 文件,這兩個都非常容易生成。這樣一來,你基本上只要指定代碼路徑,就可以遍歷所有的 Variant。

 

  1. // sources Jar 
  2. task androidSourcesJar(type: Jar) { 
  3.     from android.sourceSets.main.java.srcDirs  
  4.  
  5. // Javadoc Jar 
  6. android.libraryVariants.all { variant -> 
  7.     task("javadoc${variant.name.capitalize()}", type: Javadoc) { 
  8.         description "Generates Javadoc for $variant.name." 
  9.         group 'Docs' 
  10.         source = variant.javaCompile.source 
  11.         ext.androidJar = files(plugins 
  12.                                 .findPlugin("com.android.library"
  13.                                 .getBootClasspath()) 
  14.         classpath = files(variant.javaCompile.classpath.files) + 
  15.                     ext.androidJar 
  16.         exclude '**/BuildConfig.java' 
  17.         exclude '**/R.java' 
  18.     } 

Bintray 也為生產(chǎn)發(fā)布提供了一個很精美卻不是那么好用的 Gradle 插件 ,尤其是你只是一個 Gradle 新手的話…… 另外,帶 Web 界面的發(fā)布工具也很是有用。你只要上傳這三個文件,再填一些信息,就可以了。一開始,你可以使用那些 web 方案,當你對 Gradle 插件的使用和自動化非常熟悉的時候,就讓 Jenkins 去幫你做這些發(fā)布工作吧。

Advanced Topics

注解處理技術(shù)( Annotation processing technologies )現(xiàn)在已經(jīng)非常流行了。在編譯的時候,Javac 通常會找到你定義的注解并且在他們之上做操作,因此你能做的通常就是生成新的類和 Java 文件。你可以寫你自己的注解處理器。雖然很不簡單,但是可行。

注解技術(shù)非常擅長處理兩件事情。一是減少重復(fù)代碼(boilerplate),另一件拿手的就是優(yōu)化運行時的反射(introspection)。在運行時執(zhí)行反射操作是非常慢的,因此你***能在編譯時期就去優(yōu)化你的程序,推薦一些比較流行的用注解來處理數(shù)據(jù)的庫: Dagger , Butter Knife , AutoValue / Autoparcel , 以及 Realm 。

一個不好的消息是:Android API 不能給注解提供正確的包路徑。解決這個問題的方法是創(chuàng)建兩個子項目,一個用來指向注解,另一個指向注解處理器。注解同時需要注解處理器和你的代碼。因此,你的 Android 庫項目,將會有兩個子項目。創(chuàng)建完兩個子項目后,你需要將他們都打包在一起,最終打包出來的東西不僅僅是你的 jar 文件,同時還有注解和注解處理器。你還需要修改 javadoc 任務(wù),把注解部分的文檔也添加進去,以便讓開發(fā)者能夠讀到所有的文檔。

 

  1. // Jar 
  2. task androidJar(type: Jar) { 
  3.     dependsOn assemble 
  4.     group 'Build' 
  5.     description 'blah blah' 
  6.     from zipTree( 
  7.         'build/intermediates/bundles/release/classes.jar'
  8.     from zipTree( 
  9.         '../annotations-processor/build/libs/processor.jar'
  10.     from zipTree( 
  11.         '../annotations/build/libs/annotations.jar')  
  12.  
  13. // javadoc tasks 
  14. android.libraryVariants.all { variant -> 
  15.     task("javadoc${variant.name.capitalize()}", type: Javadoc) { 
  16.         description "Generates Javadoc for $variant.name." 
  17.         group 'Docs' 
  18.         source = variant.javaCompile.source 
  19.         source "../annotations/src/main/java" 
  20.         ext.androidJar = files(plugins 
  21.                                 .findPlugin("com.android.library"
  22.                                 .getBootClasspath()) 
  23.         classpath = files(variant.javaCompile.classpath.files) 
  24.                     + ext.androidJar 
  25.         exclude '**/BuildConfig.java' 
  26.         exclude '**/R.java' 
  27.     }  

Native Code 基本上都是和 NDK 打交道,整個工作流掌握起來很多很麻煩。如果你了解 C/C++,那***不過,不然你要花大量的時間去學(xué)習新東西。Gradle 和 Android Studio 對 NDK 的支持并不好,當你嘗試著去使用 NDK 模塊的時候,他會警告你說:當前 NDK 已經(jīng)不被支持了。Google 現(xiàn)在在盡可能的去讓 Gradle 支持去支持 Native 插件。在此之前,我們還是必須得手動的搭建整個工具鏈,手動的編譯以及把編譯出來的文件拷貝到正確的位置。

遇到 NDK 不被支持的警告要做呢?一個方法是忽略警告,因為它依然可以工作。得留意的是,現(xiàn)在沒有對 ldFlags 的定義,因此你不能為鏈接器指定 flag 參數(shù)。如果你需要這些參數(shù),另一個方法是使用 Native 插件。這個方法可能很快就被廢棄了,他需要你自己處理單獨的工具鏈的搭建以及將生成文件從一個項目轉(zhuǎn)移到對應(yīng)的項目下。

如果你使用 jar 文件,如何才能包含基于 Native 實現(xiàn)的庫呢?其實只用在 Building 的時候動動手腳就好了。如下所示,修改你的 “jar” 任務(wù)就可以了。

 

  1. task androidJar(type: Jar, dependsOn: ['assemble']) { 
  2.     group 'Build' 
  3.     description 'blah blah' 
  4.     from zipTree('build/intermediates/bundles/release/classes.jar'
  5.     from(file('src/main/jniLibs')) { 
  6.         into 'lib' 
  7.     } 
  • 擁抱 Gradle:可能需要花時間學(xué)習,但是非常值。
  • 探索 Gradle 插件!有數(shù)不清的插件,總有一款適合你。
  • 自動化你的測試。盡可能的用 Jenkins和自動化工具。
  • 如果你要開源你的炫酷組件,Bintray 是個好選擇。

Q: Jenkins 上用 Gradle 的優(yōu)勢有哪些? Emanuele:優(yōu)勢就是 Gradle 有一些設(shè)置選項,包括你在你電腦上運行的 Gralde 或者 Gradle Wrapper 版本,插件能在出問題的時候讓你通過 log 更容易的定位到問題所在。

Q: 你提到注解很有用,因為他們是在編譯的時候處理問題,那么運行時的注解有沒有什么特殊之處? Emanuele: 如果你想的話,你也可以在運行時調(diào)用注解,執(zhí)行反射操作。但是相比于在編譯時期處理慢很多。在 Android 上就更慢了,所以你用著用著就不想這么搞了。

Q: 你之前介紹了這么多有用的庫,他們都會對 Android 性能產(chǎn)生很大影響么? Emanuele:不,我只是說你可以在編譯時做反射優(yōu)化。有的時候,只有運行時反射才能拿到一些你程序執(zhí)行時候需要的信息,所以那種情況你也只能那樣做了。

Q: 在處理注解的時候, Javapoet 是個不錯的庫,但依然要讀取注解并且在類繼承關(guān)系中尋找,你有沒有處理這個的好的方案? Emanuele: 很不幸,沒有。事實上,javapoet 只能在你生成新的類的時候幫到你。如果沒有那么多的代碼量,你也可以不用任何的庫,只用模板。問題通常出在對象反射的限制上。你可以拿到注解的類,等等,但是往往無法反射內(nèi)部的方法。為了實現(xiàn)這個,你需要操作字節(jié)碼,聽起來很可怕,但是是可行的。有一個叫 Morpheus 的庫,可以幫你做這些。

Q: 我嘗試過創(chuàng)建一個庫,遇到了一個路徑設(shè)置的問題,當時沒有辦法讓 Gradle 明白我是在創(chuàng)建庫而不是一個 App,你之前有見過這樣的問題么? Emauele: 遇見過,你需要正確使用 Google Android 的 Gradle 插件,探索一下他在哪里存儲你需要的信息,你需要對這個比較了解。

Q: 你更傾向用哪個 Jenkins 服務(wù)提供方?還是你通常在你本地運行? Emanule: 我通常自己跑他們。之所以這么做,是因為我搭建了一個沒有任何 executro 的 Master 機器,同時搭建了一堆本地 Slave 機器當做 Excutor,Master 機器可以使非常小的機器,不用那么強勁,無須處理任何編譯的事情。

責任編輯:未麗燕 來源: 由Realm提供的移動開發(fā)資訊
相關(guān)推薦

2017-05-19 16:40:41

AndroidKotlin開發(fā)者

2022-01-17 16:09:43

Go語言開發(fā)

2013-07-04 10:01:04

2021-11-01 22:33:45

區(qū)塊鏈智慧城市元宇宙

2016-01-08 10:17:10

Android開發(fā)

2015-08-06 10:14:15

造輪子facebook

2022-08-15 08:27:02

基站網(wǎng)絡(luò)

2013-03-12 14:30:09

Ubuntu操作系統(tǒng)

2012-07-04 09:55:55

Windows Pho

2020-06-22 07:18:21

Java語言開發(fā)

2019-10-08 14:56:46

微軟Andorid手機

2024-10-17 16:41:57

KafkaZooKeeper

2014-08-25 10:00:18

開源

2015-05-12 11:04:42

Java EE學(xué)習Java EE

2019-03-19 08:59:13

物聯(lián)網(wǎng)IOT技術(shù)

2019-11-27 10:25:15

SaaS云端IT架構(gòu)

2021-02-11 13:30:56

Nodejs源碼c++

2017-04-05 16:40:45

2019-01-14 07:28:56

大數(shù)據(jù)云計算互聯(lián)網(wǎng)

2019-09-30 07:50:51

ITOps云端ITOM
點贊
收藏

51CTO技術(shù)棧公眾號