Android-Entwicklung macht Spaß – daran besteht kein Zweifel. Allerdings gibt es immer noch viele Plattformen, die uns dazu zwingen, sich wiederholenden Boilerplate-Code zu schreiben. Dies hängt oft mit UI-Komponenten zusammen, an denen Sie arbeiten müssen. Es gibt einige, die Sie wirklich benötigen, wenn Ihre Anwendungsarchitektur sauber sein soll. Im Hintergrund laufen viele Vorgänge asynchron ab; tatsächlich kann es leicht passieren, dass am Ende ein Haufen Spaghetti-Code entsteht, der nicht lesbar ist oder sich einfach nicht richtig anfühlt.
Heute schauen wir uns 6 Android-Bibliotheken an, die dabei helfen können, Ihren Code klar und lesbar zu halten, und verwenden dazu Beispielprojekte, damit Sie sehen können, was die Bibliotheken bewirken.
Projekt
Wir werden die Retrofit 2-Beispielanwendung verwenden, die wir zuvor im Retrofit-Leitfaden verwendet haben. Dies ist ein einfaches Open-Source-Projekt, das auf GitHub zu finden ist. Es erfordert einen Firmennamen und ein Git-Repository und listet alle Mitwirkenden auf. Die Mitwirkenden werden als Liste mit Avataren angezeigt. Obwohl es sich nicht um eine revolutionäre App handelt, zeigt sie, wie man Netzwerke betreibt, mit Bildern arbeitet, Listenkomponenten erstellt und Benutzereingaben verarbeitet. Sie können mit diesem voll funktionsfähigen Spielzeugprojekt herumspielen.
Lassen Sie uns die Annotationsbibliothek auf den Code anwenden und sehen, wie sie dazu beitragen kann, die Sauberkeit des Android-App-Codes aufrechtzuerhalten.
1.Buttermesser
Immer wenn Sie auf eine Ansicht im Code zugreifen müssen, müssen Sie eine Objektinstanz dieser Ansicht abrufen. Sie können dies tun, indem Sie die Methode rootView.findViewById() schreiben und dann das zurückgegebene Objekt in den richtigen Ansichtstyp konvertieren. Allerdings wird Ihr Code schnell zu lästigen ähnlichen Anweisungen führen, insbesondere in den Methoden onCreate und onCreateView. Denken Sie darüber nach: In diesen onCreate-Methoden initialisieren Sie alles, binden Listener und binden die gesamte Benutzeroberfläche zusammen. Je mehr UI-Elemente Sie haben, desto länger dauert eine einzelne Methode.
Nehmen wir ein einfaches Beispiel:
Diese Ansicht erfordert drei Ansichten: zwei EditTexts und einen Button, auf den wir im Fragment verweisen müssen. Im Allgemeinen würden wir Folgendes tun:
@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; }
Zusätzlich dazu, Ansichten aus dem Layout zu finden, sie in den Feldern der Aktivität zu speichern und eine anonyme innere Klasse als Listener hinzuzufügen, um den Suchbefehl zu verarbeiten, passiert nicht viel. Mit Butter Knife können wir unsere Arbeit und das Codieren erleichtern. Ansichtsobjekte werden in Feldern gespeichert, daher können wir jedem Feld einfach die Annotation „Butter Knife @BindView“ wie folgt hinzufügen:
@BindView(R.id.company_edittext) EditText companyEditText; @BindView(R.id.repository_edittext) EditText repositoryEditText; @BindView(R.id.search_button) Button searchButton;
Wir müssen auch die onCreateView-Methode auf die Existenz von Butter Knife aufmerksam machen. Jetzt enthält der Initialisierungscode nur noch die folgende kurze Anweisung:
@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; }
Wir können einen Schritt weiter gehen und die Bindung des Listeners an die searchButton-Methode überspringen und stattdessen die onSearchButtonClicked-Methode mit Anmerkungen versehen, indem wir sie auf magische Weise an binden @OnClick-Anmerkung für Schaltflächenklicks:
@OnClick(R.id.search_button) public void onSearchButtonClicked(View searchButton) { searchContributors(); }
Weitere Beispiele finden Sie auf der offiziellen Butter Knife-Homepage. Warum schauen Sie sie sich nicht einzeln an? Wenn Sie programmgesteuert auf Ansichtselemente zugreifen müssen, sorgt Butter Knife im Allgemeinen dafür, dass Ihr Code prägnanter und lesbarer wird.
2.Ice Pick
Ein häufiges Problem, mit dem viele Android-Anwendungen konfrontiert sind, ist die falsche Handhabung von Aktivitäts- und Fragment-Lebenszyklen. Ja, wir wissen, es ist nicht der eleganteste Teil des Android-Frameworks. Das Deaktivieren des Querformatmodus in der AndroidManifest-Datei, damit die App nicht abstürzt, wenn der Benutzer das Gerät seitwärts bewegt, ist jedoch nicht die richtige Lösung – erstens, weil es etwas albern aussieht, und zweitens, weil der Code die Konfiguration nicht übernimmt ändert sich korrekt. Passiert immer noch und macht alles kaputt! Daher müssen Sie den Status und den Lebenszyklus von Anwendungskomponenten ordnungsgemäß verwalten.
Der Zweck der Implementierung besteht darin, den Inhalt aller Felder in der Aktivität im Bundle zu speichern und ihn dann während des Lebenszyklus durch das Android-Framework korrekt zu verwalten. Das kann ziemlich langweilig sein.
幸运的是,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中管理依赖注入的表现真令人惊叹。为你处理依赖注入是编写代码的超棒做法。你指定应用程序的组件以及它们应如何相互交互。你可以定义代码的哪些部分需要其他部件的工作,瞧,这个库将为你初始化子部件,并根据需要注入它们。你可以检查示例项目代码以查看使用示例。
Dolch und Dagger 2 sind jedoch zu weit gefasst, sodass wir sie in diesem Artikel nicht im Detail erklären werden. Wenn Sie Dagger verwenden möchten, gibt es ein großartiges Codebeispiel, Kaffeemaschine, das auch durch hervorragende Anmerkungen unterstützt wird.
Fazit
Es gibt viele interessante Android-Bibliotheken, ich habe hier nur einige aufgelistet. Die Installation ist recht einfach, da Sie nur die Abhängigkeiten angeben müssen. Da es sich um aktiv gepflegte Projekte handelt, verfügen sie über eine hervorragende Dokumentation.
Alles, was Sie tun müssen, ist beim Build-Prozess vorsichtig zu sein. Wenn Sie beginnen, mehrere Bibliotheken mit Annotationsprozessoren zu kombinieren, stellen Sie sicher, dass Sie „proved()“ oder „annotationprocessor()“ verwenden, anstatt sie in build.gradle zu kombinieren.
Weitere 6 Android-Bibliotheken, die den Code sauberer machen können, finden Sie auf der chinesischen PHP-Website für verwandte Artikel!