首頁  >  文章  >  Java  >  6 個可以讓程式碼變得更整齊的 Android 函式庫

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

高洛峰
高洛峰原創
2017-02-08 10:26:031279瀏覽

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

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

項目

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

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

1.Butter Knife

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

讓我們舉個簡單的例子:

6 个可以让代码变得更整洁的 Android 库

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

@Overridepublic 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的存在。現在,初始化程式碼將只包含以下簡短語句:

@Overridepublic 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:

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

也在onCreateView()方法中调用Ice Pick来恢复状态:

@Overridepublic 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中將它們結合。

更多6 個可以讓程式碼變得更整潔的 Android 庫相關文章請關注PHP中文網!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn