本文算是一篇漫談,談一談關(guān)于android開發(fā)中工程初始化的時(shí)候如何在初期我們就能搭建一個(gè)好的架構(gòu)。 關(guān)于android架構(gòu),因?yàn)槭謾C(jī)的限制,目前我覺得也確實(shí)沒什么大談特談的,但是從開發(fā)的角度,看到整齊的代碼,優(yōu)美的分層總是一種舒服的享受的。 從藝術(shù)的角度看,其實(shí)我們是在追求一種美。
本文先分析幾個(gè)當(dāng)今比較流行的android軟件包,最后我們汲取其中覺得優(yōu)秀的部分,搭建我們自己的通用android工程模板。 1. 微盤 2. 久憶日記 3.網(wǎng)易新聞 4.小米應(yīng)用
1.微盤 微盤的架構(gòu)比較簡(jiǎn)單,我把最基本,最主干的畫了出來(lái):
第一層:com.sina.VDisk:com.sina(公司域名)+app(應(yīng)用程序名稱) 。 第二層:各模塊名稱(主模塊VDiskClient和實(shí)體模塊entities) 第三層:各模塊下具體子包,實(shí)現(xiàn)類。 從圖中我們能得出上述分析中一個(gè)最簡(jiǎn)單最經(jīng)典的結(jié)構(gòu),一般在應(yīng)用程序包下放一些全局的包或者類,如果有多個(gè)大的模塊,可以分成多個(gè)包,其中包括一個(gè)主模塊。 在主模塊中定義基類,比如BaseActivity等,如果主模塊下還有子模塊,可以在主模塊下建立子模塊相應(yīng)的包。說(shuō)明一點(diǎn),有的時(shí)候如果只有一個(gè)主模塊,我們完全可以省略掉模塊這一層,就是BaseActivity.java及其子模塊直接提至第二層。 在實(shí)體模塊中,本應(yīng)該定義且只定義相應(yīng)的實(shí)體類,供全局調(diào)用(然而實(shí)際情況可能不是這樣,后面會(huì)說(shuō)到)。在微盤應(yīng)用中,幾乎所有的實(shí)體類是以xxx+info命名的,這種命名也是我贊成的一種命名,從語(yǔ)義上我覺得xxxModel.java這種命名更生動(dòng)更真實(shí),xxxModel給我一種太機(jī)械太死板的感覺,這點(diǎn)完全是個(gè)人觀點(diǎn),具體操作中以個(gè)人習(xí)慣為主。還有一點(diǎn),在具體的xxxInfo,java中有很多實(shí)體類中是沒有g(shù)et/set的方法,而是直接使用public的字段名。這一點(diǎn),我是推薦這種方式的,特別是在移動(dòng)開發(fā)中,get/set方法很多時(shí)候是完全沒有必要的,而且是有性能消耗的。當(dāng)然如果需要對(duì)字段設(shè)置一定的控制,get/set方法也是可以酌情使用的。
2. 久憶日記 相比于微盤的工程結(jié)構(gòu),久憶日記的結(jié)構(gòu)稍微復(fù)雜了一些。如下圖: 1).第一層和前面微盤一樣的. 2).第二層則沒有模塊分類,直接把需要的具體實(shí)現(xiàn)類都放在下面,主要日記的一些日記相關(guān)的Activity。 3).第二層的實(shí)體包命令為model包,里面不僅存放了實(shí)體類xxx.java,而且存放了更高一級(jí)的實(shí)體類的相關(guān)類,比如xxxManager.java,xxxFactory.java.關(guān)于這一點(diǎn),我們可以參考一下android.jar中結(jié)構(gòu),我們發(fā)現(xiàn),Activity.java和ActivityManager.java,View.java和ViewManager.java,Bitmap.java和BitmapFactory.java等等N多類似的一對(duì)類都在同一個(gè)包下,我個(gè)人覺得實(shí)體包下存放實(shí)體類相應(yīng)的Manager和Factoty類也是正確的,是我們應(yīng)該采納的一種結(jié)構(gòu)。這里就打破了前面微盤中說(shuō)的實(shí)體包下存放且只存放實(shí)體類的說(shuō)法了。在現(xiàn)實(shí)中,從靈活和合理的角度,久憶日記的這種實(shí)體包中存放對(duì)象內(nèi)容更加實(shí)用。 4).第二層中增加了前面微盤中沒有涉及到的config,constant和common包。第一,其中config中存儲(chǔ)一些系統(tǒng)配置,比如名稱,應(yīng)用參數(shù)等系統(tǒng)級(jí)的常量或者靜態(tài)變量,當(dāng)然,如果你有其他大模塊的配置,比如如果擁有復(fù)雜的用戶管理模塊的話,完全可以增加一個(gè)UserConfig.java中存儲(chǔ)用戶的一些配置信息等等。第二,constant包,此包下存放的都是public static final常量,定義狀態(tài),類型等等。出于性能考慮,android開發(fā)中我不推薦使用枚舉。common包中定義一個(gè)公用庫(kù),這里因?yàn)閼?yīng)用單一,無(wú)法很好的說(shuō)明common包內(nèi)容結(jié)構(gòu)。 5).common包要涉及后面多個(gè)軟件比較后我們?cè)俚贸鼋Y(jié)論。 通過(guò)久憶日記的分析,借鑒到了不少的東西,使我們的架構(gòu)更豐滿更強(qiáng)大了。
3.網(wǎng)易新聞 網(wǎng)易新聞確實(shí)做的不錯(cuò),從應(yīng)用的角度看,是我最欣賞的應(yīng)用之一。它的工程結(jié)構(gòu)是怎么樣的呢? 網(wǎng)易新聞的工程結(jié)構(gòu)和前面2各app又有很多的不同,它并沒有按照模塊來(lái)分,而是主要按照組件的類型來(lái)分的,然后把此類型所有的類全部放在其下。那么這種把所有activity全部放在activity包下的分法的確在android開發(fā)中比較普遍。 1).第一層被分成了兩層,可以看出來(lái),這里肯定是采用了公用包jar,如此說(shuō)來(lái),我們開發(fā)公用包的時(shí)候也應(yīng)該按照"公司域名+公用模塊名稱"組合方式來(lái)命名比較好。 2).第三層(綠色層)中activity和service包下都是存放所有的activity組件和service組件,其實(shí)這里面包含了一種代碼習(xí)慣。往往activity相關(guān)的類如監(jiān)聽器,線程,適配器等非常多的類,這些不好直接丟在activity包下,而是直接寫在相應(yīng)的activity中以匿名或者內(nèi)部類形式定義,否則activity包和service包看上去會(huì)比較雜亂。 因?yàn)閍ndroid的app很可能不是很大,activity或者service包也不會(huì)雜亂,所以網(wǎng)易新聞的這種方式也是很有參考借鑒價(jià)值的。
4.小米應(yīng)用 小米應(yīng)用包括3個(gè)應(yīng)用,小米分享,小米閱讀,小米標(biāo)簽,從實(shí)際代碼開發(fā)來(lái)看,我感覺不是同一個(gè)團(tuán)隊(duì),或者同一組人開發(fā)的。 這種情況下,他們的架構(gòu)又使如何? 上面的結(jié)構(gòu)以及結(jié)構(gòu)內(nèi)部的細(xì)節(jié)其實(shí)很多地方我都是不大茍同的,但是能做出來(lái)好東西就是值得大家學(xué)習(xí)的,所以我只把其中我認(rèn)為最值得學(xué)習(xí)的一點(diǎn)拿出來(lái)說(shuō)。 首先,widget,provider這些特殊模塊分類建立單獨(dú)的模塊包即可,這里久不多說(shuō)什么。 第二,通過(guò)觀察,我們發(fā)現(xiàn)小米分享中每個(gè)應(yīng)用都有common包,不僅有應(yīng)用程序級(jí)別的common包,而且有應(yīng)用程序內(nèi)級(jí)別的common包。我想說(shuō)的是,android開發(fā)中隨著項(xiàng)目開發(fā)的積累,確能提取到很多公用的方法、類、功能模塊。各個(gè)項(xiàng)目之間如此,各個(gè)項(xiàng)目?jī)?nèi)部也是如此,所以針對(duì)項(xiàng)目類被各個(gè)模塊調(diào)用的方法,類也可以提取出相應(yīng)的公用庫(kù)。 那么這里有個(gè)問(wèn)題,公用common包的內(nèi)部包可能涉及到很多的內(nèi)容,是否要分包分級(jí)呢,又如何分包分級(jí)?我覺得,這個(gè)因情況而已,一般來(lái)說(shuō)移動(dòng)開發(fā),為了減少包的大小,我們會(huì)控制common包的膨脹,往往common包僅僅包括一些最簡(jiǎn)潔最經(jīng)典的東西,東西又很少的話就無(wú)需分包,但是如果貴公司開發(fā)成百上千,每個(gè)項(xiàng)目都用到行為分析,意見反饋等公用模塊,分一下包會(huì)更清楚一點(diǎn)??偠灾?,分不分包無(wú)關(guān)緊要,盡量讓你的代碼結(jié)構(gòu)清晰,思路了然就好。
5.聚各家之長(zhǎng),集大家之成。 上面粗略的分析之后,我們應(yīng)該對(duì)android程序的架構(gòu)有一個(gè)感覺,清晰而雜亂。我也沒有去了看更多其他應(yīng)用的結(jié)構(gòu),暫時(shí)就總結(jié)一下,得出一個(gè)我們自己的通用的工程結(jié)構(gòu)。 假如公司名為tianxia,目前公司準(zhǔn)備開發(fā)讀書應(yīng)用,交友應(yīng)用,生活服務(wù)應(yīng)用。 第一時(shí)間我們應(yīng)該得出下面這種整個(gè)的架構(gòu)(具體的app開發(fā)當(dāng)然要分開):
公司下開發(fā)3個(gè)應(yīng)用reader,friend,life,其中common包為這三個(gè)應(yīng)用共用,config,oauth為可選,view存放一些最通用的自定義view,比如對(duì)話框,定制的列表等,如果你覺得有些view可能不會(huì)通用,最好把它放在應(yīng)用程序類的common包下。 如果各位看過(guò)Android學(xué)習(xí)系列(6)--App模塊化及工程擴(kuò)展的話,對(duì)于這種多應(yīng)用模式,應(yīng)該存在android庫(kù)共用情況,來(lái)解決資源替換,工程復(fù)用的問(wèn)題。所以我又修改如下: 其中BaseApplication做一些所有app都會(huì)用到的基礎(chǔ)初始化或者配置。之后其他應(yīng)用的application應(yīng)該都繼承此BaseApplication。
base是一個(gè)android庫(kù),也是一個(gè)完整的android工程,而common只是一個(gè)jar文件,當(dāng)然你也可以根據(jù)需要作為android庫(kù)來(lái)開發(fā)。其他主工程reader,friend,life應(yīng)該引用base工程。 ad包存放公司自定義的一些軟廣告。 feedback包下存儲(chǔ)一些用戶反饋等通用功能模塊。 其實(shí),很多情況下,upgrade模塊也可以添加到base工程下,制定統(tǒng)一的軟件升級(jí)機(jī)制。 接下來(lái)我們以reader為例子,來(lái)詳細(xì)完成它的工程結(jié)構(gòu)的設(shè)計(jì)。 其中,config包下的AppConfig.java存放應(yīng)用程序的根配置,比如版本,目錄配置等等。 module包下分為各個(gè)模塊,blog為博客模塊,bbs為論壇模塊,person為整站個(gè)人信息模塊,widget表示一種特殊功能模塊。 common包下存放一些工具類,本應(yīng)用程序的一些自定義View等等。 再結(jié)合之前所講的內(nèi)容,我們把整個(gè)串起來(lái),完善一個(gè)reader的最后的架構(gòu)如下(兩外兩個(gè)freind和life亦是類似如此):
注意:1).功能模塊和類型模塊均可以劃分,如果沒有需要的話,模塊的劃分都可以省略。 2).activity和service這類組件劃分,如果沒有需要的話,組件的劃分都可以省略。 3).所有的劃分,如果沒有需要的話,所有的劃分都可以省略。 但是,但是,這種分類,我個(gè)人還是覺得層次清晰,架構(gòu)明朗,值得參考的,當(dāng)然其中很多細(xì)節(jié)我也沒有仔考慮,如有不妥,還請(qǐng)發(fā)現(xiàn)者指出。
|