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,我們需要在片段中引用。一般我們會這樣做:
@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中文網!