Android 開発は楽しいものです – それは疑いの余地がありません。しかし、反復的な定型コードの記述を強いられるプラットフォームは依然として数多くあります。多くの場合、これは、作業が必要な UI コンポーネントに関係しています。アプリケーションのアーキテクチャをクリーンにしたい場合に、本当に必要なものがいくつかあります。バックグラウンドでは多くの操作が非同期に実行されているため、実際には、読めない、または正しく感じられないスパゲッティ コードが大量に生成されることがよくあります。
今日は、サンプル プロジェクトを使用してコードを明確で読みやすく保つのに役立つ 6 つの Android ライブラリを見て、ライブラリが何を行うかを確認します。
プロジェクト
以前 Retrofit ガイドで使用した Retrofit 2 サンプル アプリケーションを使用します。これは、GitHub にあるシンプルなオープン ソース プロジェクトです。会社名と Git リポジトリが必要で、すべての貢献者がアバター付きのリストとして表示されます。これは革新的なアプリではありませんが、ネットワークの実行方法、画像の操作方法、リスト コンポーネントの作成方法、およびユーザー入力の処理方法を示しています。この完全に機能するおもちゃのプロジェクトで遊んでみてください。
注釈ライブラリをコードに適用して、Android アプリ コードのクリーンさを維持するのにどのように役立つかを見てみましょう。
1. バターナイフ
コードでビューにアクセスする必要がある場合は、そのビューのオブジェクト インスタンスを取得する必要があります。これを行うには、 rootView.findViewById() メソッドを記述し、返されたオブジェクトを正しいビュー タイプに変換します。ただし、コードは、特に onCreate メソッドと onCreateView メソッドで、すぐに迷惑な同様のステートメントが増えてしまいます。考えてみてください。これらの onCreate メソッドでは、すべてを初期化し、リスナーをバインドし、UI 全体を結び付けます。 UI 要素が増えると、1 つのメソッドが長くなります。
簡単な例を見てみましょう:
このビューには 3 つのビューが必要です: 2 つの EditText と 1 つのボタンであり、フラグメント内で参照する必要があります。通常、これを実行します:
@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 @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(); }
バターナイフの公式ホームページには他の例もあります。一つ一つチェックしてみてはいかがでしょうか!一般に、ビュー要素にプログラムでアクセスする必要がある場合、バターナイフを使用するとコードがより簡潔で読みやすくなります。
2.アイスピック
多くの Android アプリが直面する一般的な問題は、アクティビティとフラグメントのライフサイクルの不適切な処理です。はい、それは Android フレームワークの最もエレガントな部分ではないことはわかっています。ただし、ユーザーがデバイスを横に動かしたときにアプリがクラッシュしないように AndroidManifest ファイルでランドスケープ モードを無効にすることは、正しい解決策ではありません。第一に、それは少しばかげているように思え、第二に、コードが構成を処理しないためです。正しく変更されますが、それでも発生し、すべてが台無しになります。したがって、アプリケーション コンポーネントの状態とライフサイクルを適切に処理する必要があります。
実装の目的は、アクティビティ内のすべてのフィールドの内容をバンドルに保存し、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 の使用を開始したい場合は、優れたコード例であるコーヒー メーカーがあり、これも優れた注釈によってサポートされています。
結論
Android ライブラリには興味深いものがたくさんありますが、ここではほんの一部を紹介します。インストールは依存関係を指定するだけなので非常に簡単です。これらはアクティブに保守されているプロジェクトであるため、優れたドキュメントが用意されています。
あなたがしなければならないのは、構築プロセスに注意することだけです。複数のライブラリとアノテーション プロセッサの組み合わせを開始するときは、build.gradle でそれらを組み合わせるのではなく、provided() または annotationprocessor() を必ず使用してください。
コードをよりクリーンにする 6 つの Android ライブラリをさらに詳しく知りたい場合は、PHP 中国語 Web サイトの関連記事に注目してください。