android開發(fā)規(guī)范

轉自(https://github.com/Blankj/AndroidStandardDevelop

摘要

1 前言

為了有利于項目維護驻右、增強代碼可讀性蓬推、提升 Code Review 效率以及規(guī)范團隊安卓開發(fā)瓦哎,故提出以下安卓開發(fā)規(guī)范,該規(guī)范結合本人多年的開發(fā)經驗并吸取多家之精華,可謂是本人的嘔心瀝血之作群叶,稱其為當前最完善的安卓開發(fā)規(guī)范一點也不為過,如有更好建議钝荡,歡迎到 GitHub 提 issue街立,原文地址:安卓開發(fā)規(guī)范(完結版)。后續(xù)可能會根據(jù)該規(guī)范出一個 CheckStyle 插件來檢查是否規(guī)范埠通,當然也支持在 CI 上進行檢查赎离。

2 AS 規(guī)范

工欲善其事,必先利其器端辱。

  1. 盡量使用最新版的 IDE 進行開發(fā)梁剔;
  2. 編碼格式統(tǒng)一為 UTF-8
  3. 編輯完 .java舞蔽、.xml 等文件后一定要 格式化(基本格式方面使用 AS 默認模板即可)荣病;
  4. 刪除多余的 import,減少警告出現(xiàn)渗柿,可利用 AS 的 Optimize Imports(Settings -> Keymap -> Optimize Imports)快捷鍵个盆;
  5. Android 開發(fā)者工具可以參考這里:Android 開發(fā)者工具

3 命名規(guī)范

代碼中的命名嚴禁使用拼音與英文混合的方式做祝,更不允許直接使用中文的方式砾省。正確的英文拼寫和語法可以讓閱讀者易于理解,避免歧義混槐。

注意:即使純拼音命名方式也要避免采用编兄。但 alibabataobao声登、youku狠鸳、hangzhou 等國際通用的名稱,可視同英文悯嗓。

3.1 包名

包名全部小寫件舵,連續(xù)的單詞只是簡單地連接起來,不使用下劃線脯厨,采用反域名命名規(guī)則铅祸,全部使用小寫字母。一級包名是頂級域名,通常為 com临梗、edu涡扼、govnet盟庞、org 等吃沪,二級包名為公司名,三級包名根據(jù)應用進行命名什猖,后面就是對包名的劃分了票彪,關于包名的劃分,推薦使用按功能分不狮,一開始我們也是按照層去分包的降铸,很坑爹。按照功能分可能你不是很好區(qū)分在哪個功能中荤傲,不過也比你按照層區(qū)分要好找很多垮耳,具體可以參考這篇博文:Package by features, not layers颈渊。且 PBF(按功能分包 Package By Feature)與 PBL(按層分包 Package By Layer)相比較有如下優(yōu)勢:

  • package 內高內聚遂黍,package 間低耦合

    哪塊要添新功能,只改某一個 package 下的東西俊嗽。

    按 class 職能分層(PBL)降低了代碼耦合雾家,但帶來了 package 耦合,要添新功能绍豁,需要改 model芯咧、dbHelper、view竹揍、service 等等敬飒,需要改動好幾個 package 下的代碼,改動的地方越多芬位,越容易產生新問題无拗,不是嗎?

    按功能分包(PBF)昧碉,featureA 相關的所有東西都在 featureA 包英染,feature 內高內聚高度模塊化,不同 feature 之間低耦合被饿,相關的東西都放在一起四康,還好找。

  • package 有私有作用域(package-private scope)

    你負責開發(fā)這塊功能狭握,這個目錄下所有東西都是你的闪金。

    PBL 的方式是把所有工具方法都放在 util 包下,小張開發(fā)新功能時候發(fā)現(xiàn)需要一個 xxUtil论颅,但它又不是通用的哎垦,那應該放在哪里喝检?沒辦法,按照分層原則撼泛,我們還得放在 util 包下挠说,好像不太合適,但放在其它包更不合適愿题,功能越來越多损俭,util 類也越定義越多。后來小李負責開發(fā)一塊功能時發(fā)現(xiàn)需要一個 xxUtil潘酗,同樣不通用杆兵,去 util 包一看,怎么已經有了仔夺,而且還沒法復用琐脏,只好放棄 xx 這個名字,改為 xxxUtil……缸兔,因為 PBL 的 package 沒有私有作用域日裙,每一個包都是 public(跨包方法調用是很平常的事情,每一個包對其它包來說都是可訪問的)惰蜜。

    如果是 PBF昂拂,小張的 xxUtil 自然放在 featureA 下,小李的 xxUtil 在 featureB 下抛猖,如果覺得 util 好像是通用的格侯,就去 util 包看看要不要把工具方法添進 xxUtil, class 命名沖突沒有了。

    PBF 的 package 有私有作用域财著,featureA 不應該訪問 featureB 下的任何東西(如果非訪問不可联四,那就說明接口定義有問題)。

  • 很容易刪除功能

    統(tǒng)計發(fā)現(xiàn)新功能沒人用撑教,這個版本那塊功能得去掉朝墩。

    如果是 PBL,得從功能入口到整個業(yè)務流程把受到牽連的所有能刪的代碼和 class 都揪出來刪掉驮履,一不小心就完蛋鱼辙。

    如果是 PBF,好說玫镐,先刪掉對應包倒戏,再刪掉功能入口(刪掉包后入口肯定報錯了),完事恐似。

  • 高度抽象

    解決問題的一般方法是從抽象到具體杜跷,PBF 包名是對功能模塊的抽象,包內的 class 是實現(xiàn)細節(jié),符合從抽象到具體葛闷,而 PBL 弄反了憋槐。

    PBF 從確定 AppName 開始,根據(jù)功能模塊劃分 package淑趾,再考慮每塊的具體實現(xiàn)細節(jié)阳仔,而 PBL 從一開始就要考慮要不要 dao 層,要不要 com 層等等扣泊。

  • 只通過 class 來分離邏輯代碼

    PBL 既分離 class 又分離 package近范,而 PBF 只通過 class 來分離邏輯代碼。

    沒有必要通過 package 分離延蟹,因為 PBL 中也可能出現(xiàn)尷尬的情況:

    ├── service
            ├── MainService.java
    

    按照 PBL, service 包下的所有東西都是 Service评矩,應該不需要 Service 后綴纲仍,但實際上通常為了方便哭尝,直接 import service 包,Service 后綴是為了避免引入的 class 和當前包下的 class 命名沖突高蜂,當然沥匈,不用后綴也可以蔗喂,得寫清楚包路徑,比如 new com.domain.service.MainService()咐熙,麻煩弱恒;而 PBF 就很方便,無需 import棋恼,直接 new MainService() 即可。

  • package 的大小有意義了

    PBL 中包的大小無限增長是合理的锈玉,因為功能越添越多爪飘,而 PBF 中包太大(包里 class 太多)表示這塊需要重構(劃分子包)。

當然拉背,我們大谷歌也有相應的 Sample:todo-mvp师崎,其結構如下所示,很值得學習椅棺。

com
└── example
    └── android
        └── architecture
            └── blueprints
                └── todoapp
                    ├── BasePresenter.java
                    ├── BaseView.java
                    ├── addedittask
                    │   ├── AddEditTaskActivity.java
                    │   ├── AddEditTaskContract.java
                    │   ├── AddEditTaskFragment.java
                    │   └── AddEditTaskPresenter.java
                    ├── data
                    │   ├── Task.java
                    │   └── source
                    │       ├── TasksDataSource.java
                    │       ├── TasksRepository.java
                    │       ├── local
                    │       │   ├── TasksDbHelper.java
                    │       │   ├── TasksLocalDataSource.java
                    │       │   └── TasksPersistenceContract.java
                    │       └── remote
                    │           └── TasksRemoteDataSource.java
                    ├── statistics
                    │   ├── StatisticsActivity.java
                    │   ├── StatisticsContract.java
                    │   ├── StatisticsFragment.java
                    │   └── StatisticsPresenter.java
                    ├── taskdetail
                    │   ├── TaskDetailActivity.java
                    │   ├── TaskDetailContract.java
                    │   ├── TaskDetailFragment.java
                    │   └── TaskDetailPresenter.java
                    ├── tasks
                    │   ├── ScrollChildSwipeRefreshLayout.java
                    │   ├── TasksActivity.java
                    │   ├── TasksContract.java
                    │   ├── TasksFilterType.java
                    │   ├── TasksFragment.java
                    │   └── TasksPresenter.java
                    └── util
                        ├── ActivityUtils.java
                        ├── EspressoIdlingResource.java
                        └── SimpleCountingIdlingResource.java

參考以上的代碼結構犁罩,按功能分包具體可以這樣做:

com
└── domain
    └── app
        ├── App.java 定義 Application 類
        ├── Config.java 定義配置數(shù)據(jù)(常量)
        ├── base 基礎組件
        ├── custom_view 自定義視圖
        ├── data 數(shù)據(jù)處理
        │   ├── DataManager.java 數(shù)據(jù)管理器,
        │   ├── local 來源于本地的數(shù)據(jù)两疚,比如 SP床估,Database,F(xiàn)ile
        │   ├── model 定義 model(數(shù)據(jù)結構以及 getter/setter诱渤、compareTo丐巫、equals 等等,不含復雜操作)
        │   └── remote 來源于遠端的數(shù)據(jù)
        ├── feature 功能
        │   ├── feature0 功能 0
        │   │   ├── feature0Activity.java
        │   │   ├── feature0Fragment.java
        │   │   ├── xxAdapter.java
        │   │   └── ... 其他 class
        │   └── ...其他功能
        ├── injection 依賴注入
        ├── util 工具類
        └── widget 小部件

3.2 類名

類名都以 UpperCamelCase 風格編寫。

類名通常是名詞或名詞短語递胧,接口名稱有時可能是形容詞或形容詞短語”希現(xiàn)在還沒有特定的規(guī)則或行之有效的約定來命名注解類型。

名詞缎脾,采用大駝峰命名法祝闻,盡量避免縮寫,除非該縮寫是眾所周知的遗菠, 比如 HTML治筒、URL,如果類名稱中包含單詞縮寫舷蒲,則單詞縮寫的每個字母均應大寫耸袜。

描述 例如
Activity Activity 為后綴標識 歡迎頁面類 WelcomeActivity
Adapter Adapter 為后綴標識 新聞詳情適配器 NewsDetailAdapter
解析類 Parser 為后綴標識 首頁解析類 HomePosterParser
工具方法類 UtilsManager 為后綴標識 線程池管理類:ThreadPoolManager
日志工具類:LogUtilsLogger 也可)
打印工具類:PrinterUtils
數(shù)據(jù)庫類 DBHelper 后綴標識 新聞數(shù)據(jù)庫:NewsDBHelper
Service Service 為后綴標識 時間服務 TimeService
BroadcastReceiver Receiver 為后綴標識 推送接收 JPushReceiver
ContentProvider Provider 為后綴標識 ShareProvider
自定義的共享基礎類 Base 開頭 BaseActivity, BaseFragment

測試類的命名以它要測試的類的名稱開始,以 Test 結束牲平。例如:HashTestHashIntegrationTest堤框。

接口(interface):命名規(guī)則與類一樣采用大駝峰命名法,多以 able 或 ible 結尾纵柿,如 interface Runnable蜈抓、interface Accessible

注意:如果項目采用 MVP昂儒,所有 Model沟使、View、Presenter 的接口都以 I 為前綴渊跋,不加后綴腊嗡,其他的接口采用上述命名規(guī)則。

3.3 方法名

方法名都以 lowerCamelCase 風格編寫拾酝。

方法名通常是動詞或動詞短語燕少。

方法 說明
initXX() 初始化相關方法,使用 init 為前綴標識蒿囤,如初始化布局 initView()
isXX(), checkXX() 方法返回值為 boolean 型的請使用 is/check 為前綴標識
getXX() 返回某個值的方法客们,使用 get 為前綴標識
setXX() 設置某個屬性值
handleXX(), processXX() 對數(shù)據(jù)進行處理的方法
displayXX(), showXX() 彈出提示框和提示信息,使用 display/show 為前綴標識
updateXX() 更新數(shù)據(jù)
saveXX() 保存數(shù)據(jù)
resetXX() 重置數(shù)據(jù)
clearXX() 清除數(shù)據(jù)
removeXX() 移除數(shù)據(jù)或者視圖等材诽,如 removeView()
drawXX() 繪制數(shù)據(jù)或效果相關的底挫,使用 draw 前綴標識

3.4 常量名

常量名命名模式為 CONSTANT_CASE,全部字母大寫脸侥,用下劃線分隔單詞建邓。那到底什么算是一個常量?

每個常量都是一個靜態(tài) final 字段湿痢,但不是所有靜態(tài) final 字段都是常量涝缝。在決定一個字段是否是一個常量時扑庞,考慮它是否真的感覺像是一個常量。例如拒逮,如果任何一個該實例的觀測狀態(tài)是可變的罐氨,則它幾乎肯定不會是一個常量。只是永遠不打算改變對象一般是不夠的滩援,它要真的一直不變才能將它示為常量栅隐。

// Constants
static final int NUMBER = 5;
static final ImmutableListNAMES = ImmutableList.of("Ed", "Ann");
static final Joiner COMMA_JOINER = Joiner.on(','); // because Joiner is immutable
static final SomeMutableType[] EMPTY_ARRAY = {};
enum SomeEnum { ENUM_CONSTANT }

// Not constants
static String nonFinal = "non-final";
final String nonStatic = "non-static";
static final SetmutableCollection = new HashSet();
static final ImmutableSetmutableElements = ImmutableSet.of(mutable);
static final Logger logger = Logger.getLogger(MyClass.getName());
static final String[] nonEmptyArray = {"these", "can", "change"};

3.5 非常量字段名

非常量字段名以 lowerCamelCase 風格的基礎上改造為如下風格:基本結構為 scopeVariableNameType。

scope:范圍

非公有玩徊,非靜態(tài)字段命名以 m 開頭租悄。

靜態(tài)字段命名以 s 開頭。

其他字段以小寫字母開頭恩袱。

例如:

public class MyClass {
    public int publicField;
    private static MyClass sSingleton;
    int mPackagePrivate;
    private int mPrivate;
    protected int mProtected;
}

使用 1 個字符前綴來表示作用范圍泣棋,1 個字符的前綴必須小寫,前綴后面是由表意性強的一個單詞或多個單詞組成的名字畔塔,而且每個單詞的首寫字母大寫潭辈,其它字母小寫,這樣保證了對變量名能夠進行正確的斷句澈吨。

Type:類型

考慮到 Android 中使用很多 UI 控件把敢,為避免控件和普通成員變量混淆以及更好達意,所有用來表示控件的成員變量統(tǒng)一加上控件縮寫作為后綴(文末附有縮寫表)谅辣。

對于普通變量一般不添加類型后綴修赞,如果統(tǒng)一添加類型后綴,請參考文末的縮寫表桑阶。

用統(tǒng)一的量詞通過在結尾處放置一個量詞柏副,就可創(chuàng)建更加統(tǒng)一的變量,它們更容易理解联逻,也更容易搜索搓扯。

例如,請使用 mCustomerStrFirstmCustomerStrLast包归,而不要使用 mFirstCustomerStrmLastCustomerStr

量詞列表 量詞后綴說明
First 一組變量中的第一個
Last 一組變量中的最后一個
Next 一組變量中的下一個變量
Pre 一組變量中的上一個
Cur 一組變量中的當前變量

說明:

集合添加如下后綴:List铅歼、Map公壤、Set

數(shù)組添加如下后綴:Arr

注意:所有的 VO(值對象)統(tǒng)一采用標準的 lowerCamelCase 風格編寫,所有的 DTO(數(shù)據(jù)傳輸對象)就按照接口文檔中定義的字段名編寫椎椰。

3.6 參數(shù)名

參數(shù)名以 lowerCamelCase 風格編寫厦幅,參數(shù)應該避免用單個字符命名。

3.7 局部變量名

局部變量名以 lowerCamelCase 風格編寫慨飘,比起其它類型的名稱确憨,局部變量名可以有更為寬松的縮寫译荞。

雖然縮寫更寬松,但還是要避免用單字符進行命名休弃,除了臨時變量和循環(huán)變量吞歼。

即使局部變量是 final 和不可改變的,也不應該把它示為常量塔猾,自然也不能用常量的規(guī)則去命名它篙骡。

3.8 臨時變量

臨時變量通常被取名為 ij丈甸、k糯俗、mn,它們一般用于整型睦擂;c得湘、de顿仇,它們一般用于字符型淘正。 如:for (int i = 0; i < len; i++)

3.9 類型變量名

類型變量可用以下兩種風格之一進行命名:

  1. 單個的大寫字母夺欲,后面可以跟一個數(shù)字(如:E, T, X, T2)跪帝。
  2. 以類命名方式(參考3.2 類名),后面加個大寫的 T(如:RequestT, FooBarT)些阅。

更多還可參考:阿里巴巴 Java 開發(fā)手冊

4 代碼樣式規(guī)范

4.1 使用標準大括號樣式

左大括號不單獨占一行伞剑,與其前面的代碼位于同一行:

class MyClass {
    int func() {
        if (something) {
            // ...
        } else if (somethingElse) {
            // ...
        } else {
            // ...
        }
    }
}

我們需要在條件語句周圍添加大括號。例外情況:如果整個條件語句(條件和主體)適合放在同一行市埋,那么您可以(但不是必須)將其全部放在一行上黎泣。例如,我們接受以下樣式:

if (condition) {
    body();
}

同樣也接受以下樣式:

if (condition) body();

但不接受以下樣式:

if (condition)
    body();  // bad!

4.2 編寫簡短方法

在可行的情況下缤谎,盡量編寫短小精煉的方法抒倚。我們了解,有些情況下較長的方法是恰當?shù)目涝瑁虼藢Ψ椒ǖ拇a長度沒有做出硬性限制托呕。如果某個方法的代碼超出 40 行,請考慮是否可以在不破壞程序結構的前提下對其拆解频敛。

4.3 類成員的順序

這并沒有唯一的正確解決方案项郊,但如果都使用一致的順序將會提高代碼的可讀性,推薦使用如下排序:

  1. 常量
  2. 字段
  3. 構造函數(shù)
  4. 重寫函數(shù)和回調
  5. 公有函數(shù)
  6. 私有函數(shù)
  7. 內部類或接口

例如:

public class MainActivity extends Activity {

    private static final String TAG = MainActivity.class.getSimpleName();

    private String mTitle;
    private TextView mTextViewTitle;

    @Override
    public void onCreate() {
        ...
    }

    public void setTitle(String title) {
        mTitle = title;
    }

    private void setUpView() {
        ...
    }

    static class AnInnerClass {

    }
}

如果類繼承于 Android 組件(例如 ActivityFragment)斟赚,那么把重寫函數(shù)按照他們的生命周期進行排序是一個非常好的習慣着降,例如,Activity 實現(xiàn)了 onCreate()拗军、onDestroy()任洞、onPause()蓄喇、onResume(),它的正確排序如下所示:

public class MainActivity extends Activity {
    //Order matches Activity lifecycle
    @Override
    public void onCreate() {}

    @Override
    public void onResume() {}

    @Override
    public void onPause() {}

    @Override
    public void onDestroy() {}
}

4.4 函數(shù)參數(shù)的排序

在 Android 開發(fā)過程中交掏,Context 在函數(shù)參數(shù)中是再常見不過的了妆偏,我們最好把 Context 作為其第一個參數(shù)。

正相反耀销,我們把回調接口應該作為其最后一個參數(shù)楼眷。

例如:

// Context always goes first
public User loadUser(Context context, int userId);

// Callbacks always go last
public void loadUserAsync(Context context, int userId, UserCallback callback);

4.5 字符串常量的命名和值

Android SDK 中的很多類都用到了鍵值對函數(shù),比如SharedPreferences熊尉、Bundle罐柳、Intent,所以狰住,即便是一個小應用张吉,我們最終也不得不編寫大量的字符串常量。

當時用到這些類的時候催植,我們 必須 將它們的鍵定義為 static final 字段肮蛹,并遵循以下指示作為前綴。

字段名前綴
SharedPreferences PREF_
Bundle BUNDLE_
Fragment Arguments ARGUMENT_
Intent Extra EXTRA_
Intent Action ACTION_

說明:雖然 Fragment.getArguments() 得到的也是 Bundle 创南,但因為這是 Bundle 的常用用法伦忠,所以特意為此定義一個不同的前綴。

例如:

// 注意:字段的值與名稱相同以避免重復問題
static final String PREF_EMAIL = "PREF_EMAIL";
static final String BUNDLE_AGE = "BUNDLE_AGE";
static final String ARGUMENT_USER_ID = "ARGUMENT_USER_ID";

// 與意圖相關的項使用完整的包名作為值的前綴
static final String EXTRA_SURNAME = "com.myapp.extras.EXTRA_SURNAME";
static final String ACTION_OPEN_USER = "com.myapp.action.ACTION_OPEN_USER";

4.6 Activities 和 Fragments 的傳參

ActivityFragment 傳遞數(shù)據(jù)通過 IntentBundle 時稿辙,不同值的鍵須遵循上一條所提及到的昆码。

ActivityFragment 啟動需要傳遞參數(shù)時,那么它需要提供一個 public static 的函數(shù)來幫助啟動或創(chuàng)建它邻储。

這方面赋咽,AS 已幫你寫好了相關的 Live Templates,啟動相關 Activity 的只需要在其內部輸入 starter 即可生成它的啟動器吨娜,如下所示:

public static void start(Context context, User user) {
      Intent starter = new Intent(context, MainActivity.class);
      starter.putParcelableExtra(EXTRA_USER, user);
      context.startActivity(starter);
}

同理脓匿,啟動相關 Fragment 在其內部輸入 newInstance 即可,如下所示:

public static MainFragment newInstance(User user) {
      Bundle args = new Bundle();
      args.putParcelable(ARGUMENT_USER, user);
      MainFragment fragment = new MainFragment();
      fragment.setArguments(args);
      return fragment;
}

注意:這些函數(shù)需要放在 onCreate() 之前的類的頂部宦赠;如果我們使用了這種方式陪毡,那么 extrasarguments 的鍵應該是 private 的,因為它們不再需要暴露給其他類來使用勾扭。

4.7 行長限制

代碼中每一行文本的長度都應該不超過 100 個字符缤骨。雖然關于此規(guī)則存在很多爭論,但最終決定仍是以 100 個字符為上限尺借,如果行長超過了 100,我們通常有兩種方法來縮減行長精拟。

  • 提取一個局部變量或方法(最好)燎斩。
  • 應用換行將一行換成多行虱歪。

不過存在以下例外情況:

  • 如果備注行包含長度超過 100 個字符的示例命令或文字網址,那么為了便于剪切和粘貼栅表,該行可以超過 100 個字符笋鄙。
  • 導入語句行可以超出此限制,因為用戶很少會看到它們(這也簡化了工具編寫流程)怪瓶。
4.7.1 換行策略

這沒有一個準確的解決方案來決定如何換行萧落,通常不同的解決方案都是有效的,但是有一些規(guī)則可以應用于常見的情況洗贰。

4.7.1.1 操作符的換行

除賦值操作符之外找岖,我們把換行符放在操作符之前,例如:

int longName = anotherVeryLongVariable + anEvenLongerOne - thisRidiculousLongOne
        + theFinalOne;

賦值操作符的換行我們放在其后敛滋,例如:

int longName =
        anotherVeryLongVariable + anEvenLongerOne - thisRidiculousLongOne + theFinalOne;
4.7.1.2 函數(shù)鏈的換行

當同一行中調用多個函數(shù)時(比如使用構建器時)许布,對每個函數(shù)的調用應該在新的一行中,我們把換行符插入在 . 之前绎晃。

例如:

Picasso.with(context).load("https://blankj.com/images/avatar.jpg").into(ivAvatar);

我們應該使用如下規(guī)則:

Picasso.with(context)
        .load("https://blankj.com/images/avatar.jpg")
        .into(ivAvatar);
4.7.1.3 多參數(shù)的換行

當一個方法有很多參數(shù)或者參數(shù)很長的時候蜜唾,我們應該在每個 , 后面進行換行。

比如:

loadPicture(context, "https://blankj.com/images/avatar.jpg", ivAvatar, "Avatar of the user", clickListener);

我們應該使用如下規(guī)則:

loadPicture(context,
        "https://blankj.com/images/avatar.jpg",
        ivAvatar,
        "Avatar of the user",
        clickListener);
4.7.1.4 RxJava 鏈式的換行

RxJava 的每個操作符都需要換新行庶艾,并且把換行符插入在 . 之前袁余。

例如:

public Observable<Location> syncLocations() {
    return mDatabaseHelper.getAllLocations()
            .concatMap(new Func1<Location, Observable<? extends Location>>() {
                @Override
                 public Observable<? extends Location> call(Location location) {
                     return mRetrofitService.getLocation(location.id);
                 }
            })
            .retry(new Func2<Integer, Throwable, Boolean>() {
                 @Override
                 public Boolean call(Integer numRetries, Throwable throwable) {
                     return throwable instanceof RetrofitError;
                 }
            });
}

5 資源文件規(guī)范

資源文件命名為全部小寫咱揍,采用下劃線命名法颖榜。

如果想對資源文件進行分包可以參考我這篇文章:Android Studio 下對資源進行分包

5.1 動畫資源文件(anim/ 和 animator/)

安卓主要包含屬性動畫和視圖動畫述召,其視圖動畫包括補間動畫和逐幀動畫朱转。屬性動畫文件需要放在 res/animator/ 目錄下,視圖動畫文件需放在 res/anim/ 目錄下积暖。

命名規(guī)則:{模塊名_}邏輯名稱藤为。

說明:模塊名 為可選,邏輯名稱 可由多個單詞加下劃線組成夺刑。

例如:refresh_progress.xml缅疟、market_cart_add.xmlmarket_cart_remove.xml遍愿。

如果是普通的補間動畫或者屬性動畫存淫,可采用:動畫類型_方向 的命名方式。

例如:

名稱 說明
fade_in 淡入
fade_out 淡出
push_down_in 從下方推入
push_down_out 從下方推出
push_left 推向左方
slide_in_from_top 從頭部滑動進入
zoom_enter 變形進入
slide_in 滑動進入
shrink_to_middle 中間縮小

5.2 顏色資源文件(color/)

專門存放顏色相關的資源文件沼填。

命名規(guī)則:類型_邏輯名稱桅咆。

例如:sel_btn_font.xml

顏色資源也可以放于 res/drawable/ 目錄坞笙,引用時則用 @drawable 來引用岩饼,但不推薦這么做荚虚,最好還是把兩者分開。

5.3 圖片資源文件(drawable/ 和 mipmap/)

res/drawable/ 目錄下放的是位圖文件(.png籍茧、.9.png版述、.jpg、.gif)或編譯為可繪制對象資源子類型的 XML 文件寞冯,而 res/mipmap/ 目錄下放的是不同密度的啟動圖標渴析,所以 res/mipmap/ 只用于存放啟動圖標,其余圖片資源文件都應該放到 res/drawable/ 目錄下吮龄。

命名規(guī)則:類型{_模塊名}_邏輯名稱俭茧、類型{_模塊名}_顏色

說明:模塊名 為可選螟蝙;類型 可以是可繪制對象資源類型恢恼,也可以是控件類型(具體見附錄UI 控件縮寫表);最后可加后綴 _small 表示小圖胰默,_big 表示大圖场斑。

例如:

名稱 說明
btn_main_about.png 主頁關于按鍵 類型_模塊名_邏輯名稱
btn_back.png 返回按鍵 類型_邏輯名稱
divider_maket_white.png 商城白色分割線 類型_模塊名_顏色
ic_edit.png 編輯圖標 類型_邏輯名稱
bg_main.png 主頁背景 類型_邏輯名稱
btn_red.png 紅色按鍵 類型_顏色
btn_red_big.png 紅色大按鍵 類型_顏色
ic_head_small.png 小頭像圖標 類型_邏輯名稱
bg_input.png 輸入框背景 類型_邏輯名稱
divider_white.png 白色分割線 類型_顏色
bg_main_head.png 主頁頭部背景 類型_模塊名_邏輯名稱
def_search_cell.png 搜索頁面默認單元圖片 類型_模塊名_邏輯名稱
ic_more_help.png 更多幫助圖標 類型_邏輯名稱
divider_list_line.png 列表分割線 類型_邏輯名稱
sel_search_ok.xml 搜索界面確認選擇器 類型_模塊名_邏輯名稱
shape_music_ring.xml 音樂界面環(huán)形形狀 類型_模塊名_邏輯名稱

如果有多種形態(tài),如按鈕選擇器:sel_btn_xx.xml牵署,采用如下命名:

名稱 說明
sel_btn_xx 作用在 btn_xx 上的 selector
btn_xx_normal 默認狀態(tài)效果
btn_xx_pressed state_pressed 點擊效果
btn_xx_focused state_focused 聚焦效果
btn_xx_disabled state_enabled 不可用效果
btn_xx_checked state_checked 選中效果
btn_xx_selected state_selected 選中效果
btn_xx_hovered state_hovered 懸停效果
btn_xx_checkable state_checkable 可選效果
btn_xx_activated state_activated 激活效果
btn_xx_window_focused state_window_focused 窗口聚焦效果

注意:使用 Android Studio 的插件 SelectorChapek 可以快速生成 selector漏隐,前提是命名要規(guī)范。

5.4 布局資源文件(layout/)

命名規(guī)則:類型_模塊名奴迅、類型{_模塊名}_邏輯名稱青责。

說明:模塊名 為可選。

例如:

名稱 說明
activity_main.xml 主窗體 類型_模塊名
activity_main_head.xml 主窗體頭部 類型_模塊名_邏輯名稱
fragment_music.xml 音樂片段 類型_模塊名
fragment_music_player.xml 音樂片段的播放器 類型_模塊名_邏輯名稱
dialog_loading.xml 加載對話框 類型_邏輯名稱
ppw_info.xml 信息彈窗(PopupWindow) 類型_邏輯名稱
item_song.xml 歌曲列表項 類型_邏輯名稱

5.5 菜單資源文件(menu/)

菜單相關的資源文件應放在該目錄下取具。

命名規(guī)則:{模塊名_}邏輯名稱脖隶,模塊名_ 為可選,例如:main_drawer.xml暇检、navigation_menu.xml产阱。

5.6 values 資源文件(values/)

values/ 資源文件下的文件都以 s 結尾,如 attrs.xml块仆、colors.xml构蹬、dimens.xml,起作用的不是文件名稱悔据,而是 <resources> 標簽下的各種標簽庄敛,比如 <style> 決定樣式,<color> 決定顏色科汗,所以藻烤,可以把一個大的 xml 文件分割成多個小的文件,比如可以有多個 style 文件,如 styles.xml隐绵、styles_home.xml之众、styles_item_details.xmlstyles_forms.xml依许。

5.6.1 colors.xml

<color>name 命名使用下劃線命名法,在你的 colors.xml 文件中應該只是映射顏色的名稱一個 ARGB 值缀蹄,而沒有其它的峭跳。不要使用它為不同的按鈕來定義 ARGB 值。

例如缺前,不要像下面這樣做:

  <resources>
      <color name="button_foreground">#FFFFFF</color>
      <color name="button_background">#2A91BD</color>
      <color name="comment_background_inactive">#5F5F5F</color>
      <color name="comment_background_active">#939393</color>
      <color name="comment_foreground">#FFFFFF</color>
      <color name="comment_foreground_important">#FF9D2F</color>
      ...
      <color name="comment_shadow">#323232</color>

使用這種格式蛀醉,會非常容易重復定義 ARGB 值,而且如果應用要改變基色的話會非常困難衅码。同時拯刁,這些定義是跟一些環(huán)境關聯(lián)起來的,如 button 或者 comment逝段,應該放到一個按鈕風格中垛玻,而不是在 colors.xml 文件中。

相反奶躯,應該這樣做:

  <resources>

      <!-- grayscale -->
      <color name="white"     >#FFFFFF</color>
      <color name="gray_light">#DBDBDB</color>
      <color name="gray"      >#939393</color>
      <color name="gray_dark" >#5F5F5F</color>
      <color name="black"     >#323232</color>

      <!-- basic colors -->
      <color name="green">#27D34D</color>
      <color name="blue">#2A91BD</color>
      <color name="orange">#FF9D2F</color>
      <color name="red">#FF432F</color>

  </resources>

向應用設計者那里要這個調色板帚桩,名稱不需要跟 "green""blue" 等等相同嘹黔。"brand_primary"账嚎、"brand_secondary""brand_negative" 這樣的名字也是完全可以接受的儡蔓。像這樣規(guī)范的顏色很容易修改或重構郭蕉,會使應用一共使用了多少種不同的顏色變得非常清晰。通常一個具有審美價值的 UI 來說喂江,減少使用顏色的種類是非常重要的召锈。

注意:如果某些顏色和主題有關,那就單獨寫一個 colors_theme.xml开呐。

5.6.2 dimens.xml

像對待 colors.xml 一樣對待 dimens.xml 文件烟勋,與定義顏色調色板一樣,你同時也應該定義一個空隙間隔和字體大小的“調色板”筐付。 一個好的例子卵惦,如下所示:

<resources>

    <!-- font sizes -->
    <dimen name="font_22">22sp</dimen>
    <dimen name="font_18">18sp</dimen>
    <dimen name="font_15">15sp</dimen>
    <dimen name="font_12">12sp</dimen>

    <!-- typical spacing between two views -->
    <dimen name="spacing_40">40dp</dimen>
    <dimen name="spacing_24">24dp</dimen>
    <dimen name="spacing_14">14dp</dimen>
    <dimen name="spacing_10">10dp</dimen>
    <dimen name="spacing_4">4dp</dimen>

    <!-- typical sizes of views -->
    <dimen name="button_height_60">60dp</dimen>
    <dimen name="button_height_40">40dp</dimen>
    <dimen name="button_height_32">32dp</dimen>

</resources>

布局時在寫 marginspaddings 時,你應該使用 spacing_xx 尺寸格式來布局,而不是像對待 string 字符串一樣直接寫值郑趁,像這樣規(guī)范的尺寸很容易修改或重構侮叮,會使應用所有用到的尺寸一目了然嚎花。 這樣寫會非常有感覺畜疾,會使組織和改變風格或布局非常容易赴邻。

5.6.3 strings.xml

<string>name 命名使用下劃線命名法,采用以下規(guī)則:{模塊名_}邏輯名稱啡捶,這樣方便同一個界面的所有 string 都放到一起姥敛,方便查找。

名稱 說明
main_menu_about 主菜單按鍵文字
friend_title 好友模塊標題欄
friend_dialog_del 好友刪除提示
login_check_email 登錄驗證
dialog_title 彈出框標題
button_ok 確認鍵
loading 加載文字
5.6.4 styles.xml

<style>name 命名使用大駝峰命名法瞎暑,幾乎每個項目都需要適當?shù)氖褂?styles.xml 文件彤敛,因為對于一個視圖來說,有一個重復的外觀是很常見的了赌,將所有的外觀細節(jié)屬性(colors墨榄、paddingfont)放在 styles.xml 文件中勿她。 在應用中對于大多數(shù)文本內容袄秩,最起碼你應該有一個通用的 styles.xml 文件,例如:

<style name="ContentText">
    <item name="android:textSize">@dimen/font_normal</item>
    <item name="android:textColor">@color/basic_black</item>
</style>

應用到 TextView 中:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/price"
    style="@style/ContentText"
    />

或許你需要為按鈕控件做同樣的事情逢并,不要停止在那里之剧,將一組相關的和重復 android:xxxx 的屬性放到一個通用的 <style> 中。

5.7 id 命名

命名規(guī)則:view縮寫_{模塊名}_邏輯名筒狠,例如: btn_main_search猪狈、btn_back

如果在項目中有用黃油刀的話辩恼,使用 AS 的插件:ButterKnife Zelezny雇庙,可以非常方便幫助你生成注解;沒用黃油刀的話可以使用 Android Code Generator 插件灶伊。

6 版本統(tǒng)一規(guī)范

Android 開發(fā)存在著眾多版本的不同疆前,比如 compileSdkVersionminSdkVersion聘萨、targetSdkVersion 以及項目中依賴第三方庫的版本竹椒,不同的 module 及不同的開發(fā)人員都有不同的版本,所以需要一個統(tǒng)一版本規(guī)范的文件米辐。

具體可以參考我寫的這篇博文:Android 開發(fā)之版本統(tǒng)一規(guī)范胸完。

如果是開發(fā)多個系統(tǒng)級別的應用,當多個應用同時用到相同的 so 庫時翘贮,一定要確保 so 庫的版本一致赊窥,否則可能會引發(fā)應用崩潰。

7 第三方庫規(guī)范

別再閉門造車了狸页,用用最新最火的技術吧锨能,安利一波:Android 流行框架查速表,順便帶上自己的干貨:Android 開發(fā)人員不得不收集的代碼

希望 Team 能用時下較新的技術址遇,對開源庫的選取熄阻,一般都需要選擇比較穩(wěn)定的版本,作者在維護的項目倔约,要考慮作者對 issue 的解決秃殉,以及開發(fā)者的知名度等各方面。選取之后跺株,一定的封裝是必要的复濒。

個人推薦 Team 可使用如下優(yōu)秀輪子:

8 注釋規(guī)范

為了減少他人閱讀你代碼的痛苦值,請在關鍵地方做好注釋乒省。

8.1 類注釋

每個類完成后應該有作者姓名和聯(lián)系方式的注釋,對自己的代碼負責畦木。

/**
 * <pre>
 *     author : Blankj
 *     e-mail : xxx@xx
 *     time   : 2017/03/07
 *     desc   : xxxx 描述
 *     version: 1.0
 * </pre>
 */
public class WelcomeActivity {
    ...
}

具體可以在 AS 中自己配制袖扛,進入 Settings -> Editor -> File and Code Templates -> Includes -> File Header,輸入

/**
 * <pre>
 *     author : ${USER}
 *     e-mail : xxx@xx
 *     time   : ${YEAR}/${MONTH}/${DAY}
 *     desc   :
 *     version: 1.0
 * </pre>
 */

這樣便可在每次新建類的時候自動加上該頭注釋十籍。

8.2 方法注釋

每一個成員方法(包括自定義成員方法蛆封、覆蓋方法、屬性方法)的方法頭都必須做方法頭注釋勾栗,在方法前一行輸入 /** + 回車 或者設置 Fix doc comment(Settings -> Keymap -> Fix doc comment)快捷鍵惨篱,AS 便會幫你生成模板,我們只需要補全參數(shù)即可围俘,如下所示砸讳。

/**
 * bitmap 轉 byteArr
 *
 * @param bitmap bitmap 對象
 * @param format 格式
 * @return 字節(jié)數(shù)組
 */
public static byte[] bitmap2Bytes(Bitmap bitmap, CompressFormat format) {
    if (bitmap == null) return null;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    bitmap.compress(format, 100, baos);
    return baos.toByteArray();
}

8.3 塊注釋

塊注釋與其周圍的代碼在同一縮進級別。它們可以是 /* ... */ 風格界牡,也可以是 // ... 風格(//后最好帶一個空格)簿寂。對于多行的 /* ... */ 注釋,后續(xù)行必須從 * 開始宿亡, 并且與前一行的 * 對齊常遂。以下示例注釋都是 OK 的。

/*
 * This is
 * okay.
 */

// And so
// is this.

/* Or you can
* even do this. */

注釋不要封閉在由星號或其它字符繪制的框架里挽荠。

Tip:在寫多行注釋時克胳,如果你希望在必要時能重新?lián)Q行(即注釋像段落風格一樣),那么使用 /* ... */圈匆。

8.4 其他一些注釋

AS 已幫你集成了一些注釋模板漠另,我們只需要直接使用即可,在代碼中輸入 todo臭脓、fixme 等這些注釋模板酗钞,回車后便會出現(xiàn)如下注釋。

// TODO: 17/3/14 需要實現(xiàn),但目前還未實現(xiàn)的功能的說明
// FIXME: 17/3/14 需要修正砚作,甚至代碼是錯誤的窘奏,不能工作,需要修復的說明

9 測試規(guī)范

業(yè)務開發(fā)完成之后葫录,開發(fā)人員做單元測試着裹,單元測試完成之后,保證單元測試全部通過米同,同時單元測試代碼覆蓋率達到一定程度(這個需要開發(fā)和測試約定骇扇,理論上越高越好),開發(fā)提測面粮。

9.1 單元測試

測試類的名稱應該是所測試類的名稱加 Test少孝,我們創(chuàng)建 DatabaseHelper 的測試類,其名應該叫 DatabaseHelperTest熬苍。

測試函數(shù)被 @Test 所注解稍走,函數(shù)名通常以被測試的方法為前綴,然后跟隨是前提條件和預期的結果柴底。

  • 模板:void methodName前提條件和預期結果()
  • 例子:void signInWithEmptyEmailFails()

注意:如果函數(shù)足夠清晰婿脸,那么前提條件和預期的結果是可以省略的。

有時一個類可能包含大量的方法柄驻,同時需要對每個方法進行幾次測試狐树。在這種情況下,建議將測試類分成多個類鸿脓。例如抑钟,如果 DataManager 包含很多方法,我們可能要把它分成 DataManagerSignInTest答憔、DataManagerLoadUsersTest 等等味赃。

9.2 Espresso 測試

每個 Espresso 測試通常是針對 Activity,所以其測試名就是其被測的 Activity 的名稱加 Test虐拓,比如 SignInActivityTest心俗。

10 其他的一些規(guī)范

  1. 合理布局,有效運用 <merge>蓉驹、<ViewStub>城榛、<include> 標簽;

  2. ActivityFragment 里面有許多重復的操作以及操作步驟态兴,所以我們都需要提供一個 BaseActivityBaseFragment狠持,讓所有的 ActivityFragment 都繼承這個基類。

  3. 方法基本上都按照調用的先后順序在各自區(qū)塊中排列瞻润;

  4. 相關功能作為小區(qū)塊放在一起(或者封裝掉)喘垂;

  5. 當一個類有多個構造函數(shù)甜刻,或是多個同名函數(shù),這些函數(shù)應該按順序出現(xiàn)在一起正勒,中間不要放進其它函數(shù)得院;

  6. 數(shù)據(jù)提供統(tǒng)一的入口。無論是在 MVP章贞、MVC 還是 MVVM 中祥绞,提供一個統(tǒng)一的數(shù)據(jù)入口,都可以讓代碼變得更加易于維護鸭限。比如可使用一個 DataManager蜕径,把 httppreference败京、eventpost兜喻、database 都放在 DataManager 里面進行操作,我們只需要與 DataManager打交道赡麦;

  7. 多用組合虹统,少用繼承;

  8. 提取方法隧甚,去除重復代碼。對于必要的工具類抽取也很重要渡冻,這在以后的項目中是可以重用的戚扳。

  9. 可引入 Dagger2 減少模塊之間的耦合性。Dagger2 是一個依賴注入框架族吻,使用代碼自動生成創(chuàng)建依賴關系需要的代碼帽借。減少很多模板化的代碼,更易于測試超歌,降低耦合砍艾,創(chuàng)建可復用可互換的模塊;

  10. 項目引入 RxAndroid 響應式編程巍举,可以極大的減少邏輯代碼脆荷;

  11. 通過引入事件總線,如:EventBus懊悯、AndroidEventBus蜓谋、RxBus,它允許我們在 DataLayer 中發(fā)送事件炭分,以便 ViewLayer 中的多個組件都能夠訂閱到這些事件桃焕,減少回調;

  12. 盡可能使用局部變量捧毛;

  13. 及時關閉流观堂;

  14. 盡量減少對變量的重復計算让网;

    如下面的操作:

    for (int i = 0; i < list.size(); i++) {
          ...
    }
    

    建議替換為:

    for (int i = 0, len = list.size(); i < len; i++) {
          ...
    }
    
  15. 盡量采用懶加載的策略,即在需要的時候才創(chuàng)建师痕;

    例如:

    String str = "aaa";
    if (i == 1) {
          list.add(str);
    }
    

    建議替換為:

    if (i == 1) {
          String str = "aaa";
          list.add(str);
    }
    
  16. 不要在循環(huán)中使用 try…catch…溃睹,應該把其放在最外層;

  17. 使用帶緩沖的輸入輸出流進行 IO 操作七兜;

  18. 盡量使用 HashMap丸凭、ArrayListStringBuilder腕铸,除非線程安全需要惜犀,否則不推薦使用 HashTableVector狠裹、StringBuffer虽界,后三者由于使用同步機制而導致了性能開銷;

  19. 盡量在合適的場合使用單例涛菠;

    使用單例可以減輕加載的負擔莉御、縮短加載的時間、提高加載的效率俗冻,但并不是所有地方都適用于單例礁叔,簡單來說,單例主要適用于以下三個方面:

    1. 控制資源的使用迄薄,通過線程同步來控制資源的并發(fā)訪問琅关。

    2. 控制實例的產生,以達到節(jié)約資源的目的讥蔽。

    3. 控制數(shù)據(jù)的共享涣易,在不建立直接關聯(lián)的條件下,讓多個不相關的進程或線程之間實現(xiàn)通信冶伞。

  20. 把一個基本數(shù)據(jù)類型轉為字符串新症,基本數(shù)據(jù)類型.toString() 是最快的方式,String.valueOf(數(shù)據(jù)) 次之响禽,數(shù)據(jù) + "" 最慢徒爹;

  21. 使用 AS 自帶的 Lint 來優(yōu)化代碼結構(什么,你不會金抡?右鍵 module瀑焦、目錄或者文件,選擇 Analyze -> Inspect Code)梗肝;

  22. 最后不要忘了內存泄漏的檢測榛瓮;


最后啰嗦幾句:

  • 好的命名規(guī)則能夠提高代碼質量,使得新人加入項目的時候降低理解代碼的難度巫击;
  • 規(guī)矩終究是死的禀晓,適合團隊的才是最好的精续;
  • 命名規(guī)范需要團隊一起齊心協(xié)力來維護執(zhí)行,在團隊生活里粹懒,誰都不可能獨善其身重付;
  • 一開始可能會有些不習慣,持之以恒凫乖,總會成功的确垫。

附錄

UI 控件縮寫表

名稱 縮寫
TextView tv
EditText et
ImageButton ib
Button btn
ImageView iv
ListView lv
GridView gv
ProgressBar pb
SeekBar sb
RadioButtion rb
CheckBox cb
ScrollView sv
LinearLayout ll
FrameLayout fl
RelativeLayout rl
RecyclerView rv
WebView wv
VideoView vv
Spinner spn
ToggleButton tb

常見的英文單詞縮寫表

名稱 縮寫
icon ic(主要用在 App 的圖標)
color cl(主要用于顏色值)
average avg
background bg(主要用于布局和子布局的背景)
selector sel(主要用于某一 view 多種狀態(tài),不僅包括 ListView 中的 selector帽芽,還包括按鈕的 selector)
buffer buf
control ctrl
default def
delete del
document doc
error err
escape esc
increment inc
infomation info
initial init
image img
Internationalization I18N
length len
library lib
message msg
password pwd
position pos
server srv
string str
temp tmp
window wnd

程序中使用單詞縮寫原則:不要用縮寫删掀,除非該縮寫是約定俗成的。

參考

Android 包命名規(guī)范

Android 開發(fā)最佳實踐

Android 編碼規(guī)范

阿里巴巴 Java 開發(fā)手冊

Project and code style guidelines

Google Java 編程風格指南

小細節(jié)导街,大用途披泪,35 個 Java 代碼性能優(yōu)化總結!

版本日志

  • 17/12/04: 完善按功能分包搬瑰,修復 typor款票,定該版為完結版;
  • 17/12/03: 完善代碼樣式規(guī)范和測試規(guī)范泽论;
  • 17/12/02: 新增代碼樣式規(guī)范艾少;
  • 17/12/01: 對資源文件規(guī)范進行重構;
  • 17/11/29: 格式化中英混排翼悴;
  • 17/03/14: 包名劃分為按功能劃分姆钉;
  • 17/03/13: 新增其他注釋;
  • 17/03/08: 規(guī)范排版抄瓦,修復 typor 及新增一些規(guī)范;
  • 17/03/07: 修訂目錄排版陶冷,完善某些細節(jié)钙姊;
  • 17/03/06: 發(fā)布初版;

——powered by Blankj

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末埂伦,一起剝皮案震驚了整個濱河市煞额,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌沾谜,老刑警劉巖膊毁,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異基跑,居然都是意外死亡婚温,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門媳否,熙熙樓的掌柜王于貴愁眉苦臉地迎上來栅螟,“玉大人荆秦,你說我怎么就攤上這事×ν迹” “怎么了步绸?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吃媒。 經常有香客問我瓤介,道長,這世上最難降的妖魔是什么赘那? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任刑桑,我火速辦了婚禮,結果婚禮上漓概,老公的妹妹穿的比我還像新娘漾月。我一直安慰自己,他們只是感情好胃珍,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布梁肿。 她就那樣靜靜地躺著,像睡著了一般觅彰。 火紅的嫁衣襯著肌膚如雪吩蔑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天填抬,我揣著相機與錄音烛芬,去河邊找鬼。 笑死飒责,一個胖子當著我的面吹牛赘娄,可吹牛的內容都是我干的。 我是一名探鬼主播宏蛉,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼遣臼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了拾并?” 一聲冷哼從身側響起揍堰,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嗅义,沒想到半個月后屏歹,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡之碗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年蝙眶,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片褪那。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡械馆,死狀恐怖胖眷,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情霹崎,我是刑警寧澤珊搀,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站尾菇,受9級特大地震影響境析,放射性物質發(fā)生泄漏。R本人自食惡果不足惜派诬,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一劳淆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧默赂,春花似錦沛鸵、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至奈辰,卻和暖如春栏妖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背奖恰。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工吊趾, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瑟啃。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓论泛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蛹屿。 傳聞我的和親對象是個殘疾皇子孵奶,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內容

  • title: Android開發(fā)規(guī)范 摘要 1 前言 2 命名規(guī)范 3 資源文件規(guī)范 4 版本統(tǒng)一規(guī)范 5 第三方...
    大白棧閱讀 1,187評論 0 16
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,509評論 25 707
  • 個人總結的 Android 開發(fā)規(guī)范,其中控件縮寫及 Android 資源文件命名部分不是很確定蜡峰,有待商榷。Jav...
    牙鍋子閱讀 1,565評論 0 6
  • 一:介紹 1:為什么需要編碼規(guī)范 編碼規(guī)范對于程序員而言尤為重要朗恳,有以下幾個原因: 一個軟件的生命周期中湿颅,80%的...
    huaerlala閱讀 418評論 0 0
  • Java類類名:大駝峰命名,所有單詞首寫字母大寫粥诫,并且類名最好為名詞.正確public class People{...
    WilsonMing閱讀 764評論 0 2