1. 程式人生 > >最佳實踐(1):安卓開發

最佳實踐(1):安卓開發

這篇文章主要為Futurice公司Android開發者總結的經驗教訓。遵循這些規範可以避免無謂的重複勞動。如果對iOS或Windows Phone平臺的開發感興趣,請檢視《iOS開發最佳實踐》和《Windows客戶端最佳實踐》。

歡迎反饋,但請先閱讀反饋規範

摘要

  • 使用Gradle和Gradle預設的專案結構
  • 將密碼和敏感資料放在gradle.properties中
  • 不要實現自己的HTTP客戶端,使用Volley或者OkHttp庫
  • 使用Jackson庫解析JSON資料
  • 由於65K的方法空間限制,避免使用Guava並使用盡可能少的庫
  • 用Fragment來顯示UI
  • Activity只用來管理Fragment
  • XML也是程式碼,管理好XML程式碼
  • 使用樣式來減少佈局XML程式碼中重複屬性
  • 將樣式寫在多個檔案中,避免把樣式全部寫在單一的大檔案當中
  • 保持colors.xml檔案的簡短乾淨,只定義調色盤
  • 同樣也保持dimens.xml簡短乾淨,只定義通用的常量
  • 避免深層級的ViewGroup
  • 避免客戶端處理WebView要顯示的內容,並且注意記憶體洩露
  • 使用Robolectric進行單元測試,使用Robotium進行連線裝置(UI)的測試
  • 使用Genymotion模擬器
  • 一直使用ProGuard或者DexGuard

Android SDK

Android SDK存放在home目錄或者其他跟應用開發無關的位置。一些IDE在安裝時包含了SDK,這時SDK可能存放在IDE的安裝目錄下。而這是很不好的做法,特別是當你需要升級(或者重新安裝)或更換IDE時。同時也要避免把SDK存放在系統目錄下,否則,當普通使用者(不是root)使用IDE時就需要獲取sudo許可權。

編譯系統

編譯系統首選Gradle。相比於Gradle,Ant更加的侷限並且更加繁瑣。使用Gradle編譯系統可以很簡單的做到:

  • 將應用編譯成不同的版本
  • 完成簡單的類似指令碼的任務
  • 管理和下載依賴
  • 自定義祕鑰倉庫
  • 其他…

Google正積極的開發安卓Gradle外掛,作為新的標準編譯系統。

專案結構

主要有兩個主流的專案結構:舊的Ant專案結構和Eclipse ADT專案結構,較新的Gradle和Android Studio專案結構。當然選擇新的專案結構。如果你的專案正在用舊的專案結構,考慮放棄舊的結構,轉移到新的專案結構下吧。

舊專案結構:

Java
12345678910 old-structure├─assets├─libs├─res├─src│└─com/futurice/project├─AndroidManifest.xml├─build.gradle├─project.properties└─proguard-rules.pro

新的專案結構:

Java
1234567891011121314151617 new-structure├─library-foobar├─app│├─libs│├─src││├─androidTest│││└─java│││└─com/futurice/project││└─main││├─java│││└─com/futurice/project││├─res││└─AndroidManifest.xml│├─build.gradle│└─proguard-rules.pro├─build.gradle└─settings.gradle

新舊專案結構最大的不同點是新專案結構更加合理的分開了程式碼集(main, androidTest)。例如,你可以在程式碼集src資料夾下新增’paid’和’free’資料夾,分別用於存放付費版應用程式碼和免費版應用的程式碼。

頂層app資料夾用於將你的應用和其他庫(例如:library-foobar)區分開來。Settings.gradle中儲存了app/build.gradle需要用到的庫的引用。

Gradle配置

普通專案結構。遵循Google安卓Gradle規範
簡單任務。可以用Gradle完成一些簡單任務,而不用特地去寫(shell, Python, Perl等)指令碼。具體參考Gradle文件
密碼。你需要在build.gradle中配置應用發行版本的簽名配置。以下這些情況是需要避免的:

不要這樣做。也許你會在版本控制系統中這樣做。

Java
12345678 signingConfigs{release{storeFile file("myapp.keystore")storePassword"password123"keyAlias"thekey"keyPassword"password789"}}

換一種方式,新建一個gradle.properties檔案,檔案內容如下。注意,不要把Gradle.properties新增到版本控制系統中。

KEYSTORE_PASSWORD=password123
KEY_PASSWORD=password789

Gradle會自動匯入gradle.properties檔案,所以你可以在build.gradle中這樣寫:

Java
12345678910111213 signingConfigs{release{try{storeFile file("myapp.keystore")storePassword KEYSTORE_PASSWORDkeyAlias"thekey"keyPassword KEY_PASSWORD}catch(ex){thrownewInvalidUserDataException("You should define KEYSTORE_PASSWORD andKEY_PASSWORD ingradle.properties.")}}}

使用Maven管理專案依賴,而不是直接匯入jar檔案。如果你顯式的匯入jar檔案到專案中,那這些依賴的jar檔案只會是某個固定的版本,例如2.1.1。下載jar檔案並管理更新這種方式笨拙不堪,而Maven完全解決了這個問題,並且,Maven可以整合在安卓Gradle編譯系統中。你可以指定版本的範圍,例如2.2.+,然後Maven就會自動更新到版本範圍內的最新版本。例如:

Java
123456789 dependencies{compile'com.netflix.rxjava:rxjava-core:0.19.+'compile'com.netflix.rxjava:rxjava-android:0.19.+'compile'com.fasterxml.jackson.core:jackson-databind:2.4.+'compile'com.fasterxml.jackson.core:jackson-core:2.4.+'compile'com.fasterxml.jackson.core:jackson-annotations:2.4.+'compile'com.squareup.okhttp:okhttp:2.0.+'compile'com.squareup.okhttp:okhttp-urlconnection:2.0.+'}

IDE和文字編輯器

不管用什麼編輯器,它都必須要能夠很好的顯示專案結構。編譯器的選擇看個人喜好,但是編輯器必須要能夠顯示專案結構和編譯。

現在最為推薦的IDE時Android Studio,因為Android Studio由Google開發,最為接近Gradle,預設使用新的專案結構,也終於釋出了beta版,可以說是為Android開發量身定做的IDE。

當然你也可以使用Eclipse ADT,但是需要重新配置,因為Ecplise ADT預設使用舊的專案結構和使用Ant編譯。甚至,可以使用純文字編輯器,比如Vim, Sublime Text, 或者Emacs。如果使用純文字編輯器,就需要在命令列中使用Gradle和adb。如果Eclipse整合Gradle後仍舊不能工作,你可以選擇在命令列中編譯,或者遷移至Android Studio。

不管使用什麼IDE和文字編輯器,確保使用Gradle和新的專案結構來編譯應用程式,同時避免把編譯器的配置檔案新增到版本控制系統當中。例如,避免新增Ant的配置檔案build.xml。還有需要強調的一點,如果你在Ant中更改了編譯配置,不要忘記更新build.gradle,使其能夠完成編譯。另外,對其他的開發者友好一點,不要強迫他們去改變他們的工具的偏好設定。

Jackson是一個用於將物件轉換成JSON或者將JSON轉換成物件的Java庫。為了解決JSON和物件相互轉換的問題,Gson是一個受歡迎的選擇。但是我們發現,自從Jackson支援多種JSON處理方式:流,記憶體中的樹模型和傳統的JSON-POJO資料繫結,Jackson更加高效。請記住,Jackson是一個比GSON大的庫,所以請根據你自己的實際情況做出選擇。考慮到65K的方法空間限制,你可能會偏向於選擇GSON。其他選擇:Json-smartBoon JSON

網路,快取和圖片。現在已經有許多經過實踐證明的向後端伺服器請求資料的解決方案。你應該考慮使用這些解決方案來實現自己的客戶端。使用Volley或者Retrofit。Volley也提供了載入和快取圖片的幫助類。如果你選擇Retrofit,考慮使用Picasso來載入和快取圖片,使用OkHttp來實現高效的HTTP請求。Retrofit,Picasso和OkHttp都由同一個公司實現,所以這三者契合的特別好。OkHttp也可以和Volley配套使用。

RxJava是一個用於響應式程式設計的庫,也即是,處理非同步事件的庫。RxJava這個範例非常強大,而且前途光明。RxJava非常與眾不同,因此使用RxJava時可能會令人迷惑。我們推薦在把RxJava部署到整個應用前先花一些時間瞭解RxJava。現在已經有一些專案是利用RxJava來完成的,如果你需要幫助,請向這些人詢問:Timo Tuominen, Olli Salonen, Andre Medeiros, Mark Voit, Antti Lammi, Vera Izrailit, Juha Ristolainen。另外,我們也寫了一些部落格:[1], [2], [3], [4].

如果你沒有使用Rx的經驗,請從應用Rx的響應API開始。或者,從應用Rx的UI事件處理開始,比如點選事件或者在搜尋框中的鍵盤事件。如果你對使用Rx很有信心,想要把Rx應用到整個應用程式當中,請在比較難處理、容易令人迷惑的部分寫明Javadocs。記住,其他不熟悉RxJava的程式設計師維護專案時可能會非常困難。請盡力去幫助他去理解你的程式碼和Rx。

Retrolambda是一個在Android平臺或者其他低於JDK8的平臺上處理Lambda表示式語法的Java庫。利用這個庫,可以保持你的程式碼的整潔嚴謹並且具有可讀性,特別是當你使用了函數語言程式設計風格(functional style),例如使用了RxJava。使用前,先安裝JDK8,在Android Studio專案結構對話方塊中將它設定為你的SDK路徑,設定JAVA8_HOME和JAVA7_HOME環境變數,然後在專案根目錄下build.gradle中增加以下內容:

Java
123 dependencies{classpath'me.tatarka:gradle-retrolambda:2.4.+'}

然後在每一個模組下的build.gradle中,增加以下內容:

Java
12345678910111213 apply plugin:'retrolambda'android{compileOptions{sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}retrolambda{jdk System.getenv("JAVA8_HOME")oldJdk System.getenv("JAVA7_HOME")javaVersion JavaVersion.VERSION_1_7}

Android Studio支援對Java8的lambda智慧提示。如果你是第一次使用lambda,從以下兩條規則開始:

  • 所有隻有一個方法的介面都是「lambda友好」的,能夠被轉換成更加整潔嚴謹的語法。
  • 如果你不確定引數或者其他資訊,寫一個普通的匿名內部類,然後讓Android Studio將它轉換成一個lamdba表示式。

請注意dex方法限制,避免使用過多的庫。被打包成dex檔案的安卓應用,都有一個硬性的限制:最多能有65536個方法引用[1] [2] [3]。如果你超出了這個限制,在編譯的時候你就會看到一個嚴重的編譯錯誤。因此,使用盡量少的庫,並使用dex-method-counts工具來決定在保證不超出限制的前提下,有哪些庫可以使用。特別要避免使用Guava庫,因為它包含了超過13k個方法。

在Android應用開發中,首選Fragment來顯示UI。Fragment是可重用的使用者互動介面,並且可以將Fragment組合在一起。我們推薦使用Fragment來顯示使用者互動介面,而不是使用Activity。以下是一些理由:

  •  實現多檢視佈局。將手機應用擴充套件至平板的主要方法便是利用Fragment。利用Fragment,可以讓檢視A和B都顯示在一個平板螢幕上,而在手機螢幕上,檢視A和B都佔一整塊螢幕。如果你的應用從一開始就用Frament來實現,那麼你很容易就能將你的應用適配到螢幕大小不同的裝置上。
  • 屏與屏之間的通訊。 安卓API並沒有提供一個恰當的方法將複雜的資料(例如,一些Java物件)從一個Activity傳送到另外一個Activity中。但是利用Fragment時,以activity例項為通訊管道,可以實現該activity下的子fragment之間的通訊。即使這種方法優於Activity之間的通訊,你可能仍舊需要一個事件匯流排的架構,考慮使用Otto或者greenrobot EventBus
  • Fragment有更好的普適性,而不僅僅只是實現UI。你可以實現一個沒有UI的fragment,作為activity後臺執行的「工人」。你也可以將這個點子發揮的更淋漓盡致一點,比如建立一個fragment專門用於實現fragment的改變邏輯,而不是將這些邏輯寫在activity中。
  • 甚至ActionBar也可以在fragment中管理。你可以建立一個沒有UI的fragment,只用於管理ActionBar,或者在每一個當前可見的fragment中把自己需要的action項新增到父activity的ActionBar上。閱讀更多內容

雖然我們建議使用fragment,但是我們不建議大量使用巢狀的fragment,因為可能會引起“套娃式bug”(matryoshka bugs)。只在合理的情況下(例如,水平滑動的ViewPager中的fragment巢狀在一個模擬螢幕的fragment中)或者經過深思熟慮時,才使用巢狀的fragment。

從架構層面來講,你的應用應該有一個頂層的activity,其中activity中包含了大部分的業務相關的fragment。你也可以有其他的輔助activity,只要這些activity和主activity的通訊足夠簡單,能夠通過Intent.setData()或者Intent.setAction()或者其他簡單的方式實現即可。

Java包結構

Android應用程式的Java包結構可以用基本上近似於模型-檢視-控制器結構。對於Android,Fragment和Activity實際上就是控制類。同時,這兩者也是使用者互動介面的一部分,因此,這兩者也是檢視。

由於上述原因,將fragment(或者activity)嚴格的歸類為控制器或者是檢視是非常困難,不合理的。所以,更合理的做法是把fragment存放在專有的fragment包內。如果你遵循了前一部分的建議,那麼可以將activity存放在最頂層的包下。如果你計劃建立多於2個或3個activity,那麼建立一個activities包。

否則(譯者注:如果沒有fragment和activity),包結構看起來就是一個典型的MVC結構。有一個models包,存放主要用於JSON解析時API返回值的POJO物件;一個views包,存放你自定義的檢視,通知,action bar檢視和小部件等。Adapter的歸類比較模糊,是處於資料和檢視之間的位置。但是,一般情況下,adapter需要在getView()函式中引入一些檢視,所以可以在views包下建一個adapters包來存放adpater。

一些控制類是整個應用程式都需要使用到的,也更加接近安卓系統底層。這些控制類存放在managers包下。各種資料處理類,例如「DateUtils」,存放在utils包下。負責與後端伺服器進行互動的類存放在network包下。

總之,按靠近後端伺服器到靠近使用者的順序排列,包結構如下:

Java
1234567891011 com.futurice.project├─network├─models├─managers├─utils├─fragments└─views├─adapters├─actionbar├─widgets└─notifications

 資源

命名。遵循以型別作為字首的習慣,像type_foo_bar.xml。例如:fragment_contact_details.xml,view_primary_button.xml,activity_main.xml。

管理好佈局XML程式碼。如果你不確定如何按照一定的格式來管理XML,可以參考以下幾個習慣:

  • 一個屬性佔單獨的一行,縮排4個空格
  • android:id總是第一個屬性
  • android:layout_****屬性放在頂部
  • style屬性放在底部
  • 標籤關閉/>獨佔一行,便於調整屬性的順序和增加屬性
  • 不要在android:text中硬編碼字串,考慮使用Android Studio中提供的Designtime attributes功能
123456789101112131415161718192021 <?xml version="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextViewandroid:id="@+id/name"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:text="@string/name"

相關推薦

最佳實踐1開發

這篇文章主要為Futurice公司Android開發者總結的經驗教訓。遵循這些規範可以避免無謂的重複勞動。如果對iOS或Windows Phone平臺的開發感興趣,請檢視《iOS開發最佳實踐》和《Windows客戶端最佳實踐》。 歡迎反饋,但請先閱讀反饋規範。 摘要 使用Gr

學習1——搭建開發環境Eclipse+ADT+Android SDK

安裝JDK 這裡可以參考我之前寫的一篇關於安裝JDK的教程, 請看下面連結吧。 安裝Eclipse Eclipse 是一個開放原始碼的、基於Java的可擴充套件開發平臺。就其本身而言,它只是一個框架和一組服務,用於通過外掛元件構建開發環境。幸運的是,Eclipse 附帶了一個標準的外掛集,包括Java開發工

最佳實踐3Windows應用開發

這是Futurice公司的Windows 8.x 和 Windows Phone 8.x 應用開發者的經驗教訓。通過參考這些指南能夠避免重複造輪子。如果你對iOS或者Android開發感興趣,一定也要去看一下他們的《iOS開發最佳實踐》和《安卓開發最佳實踐》。 歡迎

Android項目實戰應用程序退出的三種方法

eat 延遲 用戶 pre html port length tst 二次 原文:Android項目實戰(二):安卓應用程序退出的三種方法現在的APP退出的時候都不是讓用戶點擊了“後退鍵”就退出。防止用戶點錯了後退鍵而造成的用戶體檢不好。 一年前搞

高效運維最佳實踐03Redis叢集技術及Codis實踐 (轉)

專欄介紹 “高效運維最佳實踐”是InfoQ在2015年推出的精品專欄,由觸控科技運維總監蕭田國撰寫,InfoQ總編輯崔康策劃。 前言 誠如開篇文章所言,高效運維包括管理的專業化和技術的專業化。前兩篇我們主要在說些管理相關的內容,本篇說一下技術專業化。希望讀者朋友們能適應這個轉

大型網站的 HTTPS 實踐1HTTPS 協議和原理

1 前言 百度已經於近日上線了全站 HTTPS 的安全搜尋,預設會將 HTTP 請求跳轉成 HTTPS。本文重點介紹 HTTPS 協議, 並簡單介紹部署全站 HTTPS 的意義。 2 HTTPS 協議概述 HTTPS 可以認為是 HTTP + TLS。HTTP 協議

最佳實踐2iOS開發

這份文件就像軟體專案一樣,如果我們不維護它就會逐漸腐壞。歡迎大家跟我們一起來維護它——只需提交 issue 或者發 pull request 即可! 為什麼要寫這篇文件? iOS 開發在上手時可能會有些令人生畏。無論是 Objective-C 還是 Swift 在別處都沒有廣

Vuejs 最佳實踐1

有了前面文章的鋪墊,相信一路看過來的新手的你開發一箇中型的 Vuejs 應用已經不在話下,包括 Vuejs 生態核心工具(vue-router,vuex)的使用也不成問題。但是在實際專案開發過程中,我們要做的工作不僅僅是完成我們的業務程式碼,當一個需求完成後,我們還需要考慮更多後期優化工作,本篇主要講述程式碼

自動化測試最佳實踐從紡錘模型到金字塔模型

一、當前軟體開發的趨勢 開篇我們先簡要介紹一些近幾年在企業開發中出現的重要概念,以便引入持續測試的主旨。這些概念中最重要的兩個便是DevOps和微服務。兩者都是目前軟體開發中的最佳實踐和方法論,旨在為企業提供更高的靈活性,提升運營效率。 1.1 DevOps DevOps是一套實踐方法論和文化,提

老牛知點所以然-LinuxUbuntu配置開發環境及過程中常見問題解決

[TOC] 題記: 這篇部落格基本上是半年多實踐過程中積累到筆記中的。在第二次配置完開發環境後,我就有意識的把大概的配置過程形成了一個筆記,這半年多將近一年的時間裡,陸續發現了一些不足和謬誤,還有以前踩過的坑沒有及時記下來,最近又踩過的,逐漸補充了過來,算是

NS-3教程1NS-3開發環境搭建

前言 在現代網路通訊技術的教學和科研中,迫切希望有一種先進的網路模擬技術。在網路模擬工具的研究和開發方面國內所做的工作較少,但是國外早已出現了很多研究成果和模擬工具,如ns-2、OMNet++、OPNET、GloMoSim、GTNetS、QualNet

21天實戰人工智慧系列人工智慧產品經理最佳實踐3

往期回顧:1前言打算面向想從事人工智慧產品經理職位的人,寫一個系列的專題,對人工智慧產品經理做一

十二Hibernate中的多表操作1單向多對一

art 保存 int gen round t對象 情況 映射文件 拋出異常 由“多”方可知“一”方的信息,比如多個員工使用同一棟公寓,員工可以知道公寓的信息,而公寓無法知道員工的信息。 案例一: pojo類 public class Department {

Python學習手冊筆記1Python對象類型

python 在Python中一切皆對象,Python程序可以分解為模塊、語句、表達式及對象。如下所示:1 程序由模塊組成2 模塊包含語句3 語句包含表達式4 表達式建立並處理對象 內置對象(核心類型):1)數字:>>> 2+2 #整數加法4>>&g

Canvas入門1繪制矩形、圓、直線、曲線等基本圖形

dsm etc win cti b2c 創建 例如 .com courier 來源:http://www.ido321.com/968.html 一、Canvas的基礎知識 Canvas是HTML 5中新增的元素,專門用於繪制圖形。canvas元素就相當於一塊“畫布

Pro Android學習筆記 ActionBar1Home圖標區

ces tom 新的 方便 find rac vertica lba manifest ?? Pro Android學習筆記(四八):ActionBar(1):Home圖標區 2013年03月10日 ? 綜合 ? 共 3256字 ? 字號 小 中 大 ? 評論關閉

python每日一類1pathlib

one pre 面向 iss open log python href reg 每天學習一個python的類(大多數都是第三方的),聚沙成金。 -----------------------------------------------------------------

【開源】OSharp框架學習系列1總體設計及系列導航

正是 html 組織 內聚性 權限 是什麽 enc 3-0 分發 OSharp是什麽?   OSharp是個快速開發框架,但不是一個大而全的包羅萬象的框架,嚴格的說,OSharp中什麽都沒有實現。與其他大而全的框架最大的不同點,就是OSharp只做抽象封裝,不做實現。依賴註

uboot命令1mmc命令

當前 .com 設備 十六進制 mci rgs 開發平臺 通過 硬件 版權聲明 更新:2017-06-07博主:LuckyAlan聯系:[email protected]/* */聲明:吃水不忘挖井人,轉載請註明出處! 1 文章介紹 今天在進行Android分區

idea1安裝配置

idea idea安裝配置 二、配置2.1、激活Help --> Register...2.2、皮膚及字體File-->Settings...-->2.2.1、皮膚 2.2.2、字體 2.3、git在https://github.com/中註冊一個賬號IDEA還需要Git客戶端,官方