6 個可以讓程式碼變得更整潔的 Android 庫

2017-01-12    分類:Android開發、程式設計開發、首頁精華0人評論發表於2017-01-12

本文由碼農網 – 小峰原創翻譯,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃

Android開發是有趣的——這毫無疑問。然而,還是有很多平臺迫使我們編寫重複的樣板程式碼。很多時候這都與需要你處理的UI元件相關。有一些確實是你需要的,當你希望你的應用程式架構能夠乾乾淨淨的時候。有很多操作在後臺非同步執行;事實上,最後很容易成為一堆義大利麵條似的程式碼,不可讀或者就是讓人感覺不正確。

今天,我們將看看6個可以幫助保持程式碼清晰和可讀性的Android庫,並且使用示例專案以方便你可以看到庫的作用。

專案

我們將使用之前我們在Retrofit指南中使用過的Retrofit 2 Sample應用程式。這是一個簡單的開源專案,可以在GitHub上找到。它需要一個公司名稱和一個Git儲存倉庫,並列出所有的貢獻者,貢獻者顯示為帶有頭像的一個列表。雖然它不是一個革命性的app,但是它展示瞭如何執行網路,使用影像,建立列表元件,以及處理使用者輸入。你可以隨意擺弄這個功能齊全的玩具專案。

讓我們將註釋庫應用到程式碼,來看看它們如何幫助維護Android app程式碼的整潔。

1.Butter Knife

每當你需要訪問程式碼中的檢視時,你需要獲取該檢視的物件例項。你可以通過編寫rootView.findViewById()方法來實現,然後將返回的物件轉換為正確的檢視型別。但是,你的程式碼很快就會建立起來,但是尤其是在onCreate和onCreateView方法中會有惱人的類似語句。想想看;在那些onCreate方法中,你初始化一切,繫結偵聽器,把整個UI綁在一起。你擁有的UI元素越多,那麼單個方法就會越長。

讓我們舉個簡單的例子:

此檢視將需要三個檢視:兩個EditTexts和一個Button,我們需要在片段中引用。一般我們會這樣做:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
  // Inflate the layout for this fragment
  View rootView = inflater.inflate(R.layout.fragment_search, container, false);
  companyEditText = (EditText) rootView.findViewById(R.id.company_edittext);
  repositoryEditText = (EditText) rootView.findViewById(R.id.repository_edittext);
  searchButton = (Button) rootView.findViewById(R.id.search_button);

  searchButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      searchContributors();
    }
  });
  return rootView;
}

在程式碼中除了從佈局中查詢檢視,將它們儲存在活動的欄位中,以及新增一個匿名內部類作為監聽器來處理搜尋命令之外,沒有太多事情發生。通過Butter Knife,我們可以使我們的工作和編碼更容易。檢視物件儲存在欄位中,因此我們可以簡單地向每個欄位新增Butter Knife @BindView註解,如下所示:

@BindView(R.id.company_edittext) EditText companyEditText;
@BindView(R.id.repository_edittext) EditText repositoryEditText;
@BindView(R.id.search_button) Button searchButton;

我們還需要使onCreateView方法知道Butter Knife的存在。現在,初始化程式碼將只包含以下簡短語句:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
  // Inflate the layout for this fragment
  View rootView = inflater.inflate(R.layout.fragment_search, container, false);
  ButterKnife.bind(this, rootView);
  return rootView;
}

我們還可以進一步,跳過繫結監聽器到searchButton方法,並改為註解onSearchButtonClicked方法,通過神奇地將之繫結到按鈕點選的@OnClick註解:

@OnClick(R.id.search_button)
public void onSearchButtonClicked(View searchButton) {
  searchContributors();
}

在官方的Butter Knife主頁還有其他的例子。不妨一一檢視一番!一般說來,如果你需要以程式設計方式訪問檢視元素,那麼Butter Knife會讓你的程式碼更簡潔和可讀。

2.Ice Pick

許多Android應用程式面臨的一個常見問題是活動和片段生命週期的不正確處理。是啊,我們知道,它不是Android框架最優雅的部分。但是,在AndroidManifest檔案中禁用橫向模式,這樣當使用者將裝置側向移動時,應用程式不會崩潰並非是一個正確的解決方案——首先,因為顯得有點傻,其次,程式碼不能正確處理的配置更改仍然會發生並破壞一切!因此,你必須正確處理應用程式元件的狀態和生命週期。

實現的目的是將活動中所有欄位的內容儲存到bundle中,然後由Android框架通過生命週期正確管理。這可能是相當無聊。

幸運的是,Ice Pick使我們的生活變得容易多了,因為你再不必一個個新增所有的變數到bundle去儲存。同樣從bundle中再次讀取資料,如果存在,那麼會很有挑戰性,但Ice Pick簡化了很多很多。因此,作為示例,假設我們需要記住最後一家公司和儲存庫搜尋的組合。

首先,我們對要儲存到bundle的欄位進行註解。

@State String lastSearchCombination;

現在我們需要在onSaveInstanceState()方法中呼叫Ice Pick:

@Override
public void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
  Icepick.saveInstanceState(this, outState);
}

也在onCreateView()方法中呼叫Ice Pick來恢復狀態:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                        Bundle savedInstanceState) {
  // Inflate the layout for this fragment
  View rootView = inflater.inflate(R.layout.fragment_search, container, false);
  ButterKnife.bind(this, rootView);
  Icepick.restoreInstanceState(this, savedInstanceState);
  return rootView;
}

記住:你可以儲存到bundle的內容的限制仍然存在。但是,沒有必要因為為bundle鍵新增常量或為savedInstanceState新增空檢查搞得一團亂。

3.Dart和Henson

與Ice Pick類似,Dart幫助我們避免為從一個活動傳遞到另一個活動的Intent Extras寫入所有鍵和檢查。它也適用於Fragments。這裡有一個小例子,展示了我是如何使用@InjectExtra註釋將搜尋關鍵字從搜尋螢幕傳遞到貢獻者列表,實際上將執行搜尋的地方。

所以我使用@InjectExtra註解定義了兩個類變數:

@InjectExtra String repositoryQuery;
@InjectExtra String companyQuery;

一旦Dart.inject(this, getActivity());被呼叫,那麼這些都將會被自動初始化。現在在Bundle中被新增到Intent的extras最終將如何。你可以手動進行,但這裡使用Henson是非常有道理的。為了使它工作,我新增以下程式碼到我的SearchFragment:

Intent intentContributorsFragment = 
  Henson.with(getActivity())
        .gotoContributorsFragment()
        .companyQuery(companySearchKeyword)
        .repositoryQuery(repositorySearchKeyword).build();
Intent intentContributorsActivity = 
  Henson.with(getActivity())
        .gotoContributorsActivity().build();
intentContributorsActivity.putExtras(intentContributorsFragment);
startActivity(intentContributorsActivity);

這簡化了程式碼中活動之間的通訊,而無需每次都手動指定每個txtra。

4. Parceler

Parceler幫助你進行物件序列化。它可以幫助你傳遞任何物件作為Intent extra,而不會讓你面對物件序列化的煩惱。

最好的事情是,Icepick,Henson和Dart也能很好地和Parceler一起玩。在我們的應用程式示例中,我使用@Parcel註釋了我的Contributor類。這允許我使用Dart傳遞Contributor作為Intent Extra,使我的程式碼簡潔和可讀。

5.Timber

當我寫程式碼的時候,過不了一會,我總有犯錯誤的傾向。通常情況下,這會導致應用程式的意外行為。我需要重現它,這樣我才能解決這個問題。當你知道重現的步驟時,偵錯程式會很方便,但是通常情況下,日誌也包含了真相!

在Android中開箱即用的Log類足夠好,因為可以提供不同的日誌記錄級別,等等。然而,每個Log.d()語句有兩個引數;首先是tag,第二是message。99%的時間裡,tag將是this.class.getName(),並且一次又一次地寫會很煩人。幸運的是,使用Timber庫,你只要這樣做:

Timber.d("Informative output that needs to be logged.");

…並且它將為你提供正確的預設tag!此外,請記住,你需要在使用之前初始化Timber。檢視我已新增呼叫的ContributorsApplication.onCreate()程式碼:

Timber.plant(new Timber.DebugTree());

這就是正確初始化Timber所有需要做的事情,所有沒有理由你的app不使用Timber。

6.Dagger和Dagger2

最後,但並非最不重要的,Dagger和Dagger2庫在app中管理依賴注入的表現真令人驚歎。為你處理依賴注入是編寫程式碼的超棒做法。你指定應用程式的元件以及它們應如何相互互動。你可以定義程式碼的哪些部分需要其他部件的工作,瞧,這個庫將為你初始化子部件,並根據需要注入它們。你可以檢查示例專案程式碼以檢視使用示例。

然而,Dagger和Dagger 2涉及面太廣泛了,所以在這篇文章中我們就不做詳細解釋了。如果你想從使用Dagger開始,那麼有一個很好的程式碼例子,coffee maker,它也得到了優秀的註釋支援。

結論

有很多有趣的Android庫,我在這裡只列出了一些。安裝起來相當容易,因為你只需要指定依賴關係就可以了。這些都是被積極維護的專案,所以它們有偉大的文件。

你要做的就是小心構建過程。當你開始結合多個庫與註解處理器時,確保使用provided()或annotationprocessor(),而不是在build.gradle中將它們結合起來。

譯文連結:http://www.codeceo.com/article/6-android-lib-make-code-clean.html
英文原文:6 Android Libraries That Can Clean Up Your Code
翻譯作者:碼農網 – 小峰
轉載必須在正文中標註並保留原文連結、譯文連結和譯者等資訊。]

相關文章