Hallo allerseits! Meine Beiträge sind ein Wunsch, mit einigen Android-Elementen zu helfen. Wenn Sie ein Entwickler sind, der noch keinen Algorithmus zum Erstellen von Listen entwickelt hat, ist es möglicherweise hilfreich, dieses Material zu lesen. Grundsätzlich möchte ich vorgefertigte Lösungen für die Entwicklung anbieten und im Verlauf der Geschichte einige Gedanken darüber enthüllen, wie ich zu
ihnen gekommen bin.
In diesem Artikel:- Wir bilden mehrere Basisklassen und Schnittstellen für die Arbeit mit RecyclerView und RecyclerView.Adapter
- Verbinden Sie eine Bibliothek von Android Jetpack (optional, zuerst ohne)
- für noch schnellere entwicklung - die vorlagenoption am ende des artikels;)
Eintrag
Na dann! Jeder hat ListView bereits vergessen und schreibt sicher auf RecyclerView (
Rv ). Die Zeiten, in denen wir das
ViewHolder- Muster
selbst implementiert haben, sind in Vergessenheit geraten.
Rv bietet uns eine Reihe vorgefertigter Klassen zum Implementieren von Listen und eine ziemlich große Auswahl an
LayoutManagern zum Anzeigen dieser Listen.
Wenn Sie sich viele Bildschirme
ansehen , können Sie sich die meisten als Liste vorstellen - gerade weil jedes Element seinen eigenen
ViewHolder implementieren
kann .
Die Entwicklungsgeschichte wurde
uns in Google I / O ausführlicher
erzählt.Es gibt jedoch immer ein paar „Aber!“. Standardantworten auf Stackoverflow schlagen allgemeine Lösungen vor, die zum Kopieren und Einfügen führen, insbesondere an der Stelle, an der der Adapter implementiert ist.
Im Moment ist
Rv bereits drei Jahre alt. Es gibt viele Informationen und viele Bibliotheken mit vorgefertigten Lösungen, aber was ist, wenn Sie nicht alle Funktionen benötigen oder wenn Sie sich den Code eines anderen ansehen - und Sie sehen, dass der
Ancient Horror nicht das
ist , was Sie sehen möchten oder nicht vorgestellt? In diesen drei Jahren hat Android Kotlin offiziell akzeptiert = die Lesbarkeit des Codes hat sich verbessert. Viele interessante Artikel wurden auf
Rv veröffentlicht , die seine Fähigkeiten voll und ganz offenbaren.
Ziel ist es, die Grundlage für die Best Practices
Ihres Fahrrads zu ermitteln , ein Framework für die Arbeit mit Listen für neue Anwendungen. Dieses Framework kann durch Logik von Anwendung zu Anwendung ergänzt werden, wobei das verwendet wird, was Sie benötigen, und unnötiges Verwerfen. Ich denke, dieser Ansatz ist viel besser als die Bibliothek eines anderen. In Ihren Klassen haben Sie die Möglichkeit, zu verstehen, wie alles funktioniert, und die Fälle zu kontrollieren, die Sie benötigen, ohne an die Entscheidung eines anderen gebunden zu sein.
Denken wir von Anfang an logisch und logisch
Was die Komponente tun soll, wird von der
Schnittstelle entschieden, nicht von der Klasse , aber am Ende werden wir die konkrete Implementierungslogik für die Klasse schließen, die diese Schnittstelle implementiert und implementiert. Wenn sich jedoch herausstellt, dass mit der Implementierung der Schnittstelle ein Copy-Paste gebildet wird, können wir es hinter einer abstrakten Klasse und danach hinter einer Klasse verstecken, die von der Zusammenfassung erbt. Ich werde meine Implementierung der grundlegenden Schnittstellen zeigen, aber mein Ziel ist es, dass der Entwickler nur versucht, in die gleiche Richtung zu denken. Noch einmal - der Plan lautet wie folgt:
Eine Reihe von Schnittstellen -> eine abstrakte Klasse , die (falls erforderlich) kopiert und eingefügt wird -> und bereits eine bestimmte Klasse mit einem eindeutigen Code . Sie können Schnittstellen unterschiedlich implementieren.
Was kann ein Adapter mit einer Liste tun? Die Antwort auf diese Frage ist am einfachsten zu finden, wenn Sie sich ein Beispiel ansehen. Sie können sich den RecyclerView.Adapter ansehen, in dem Sie einige Tipps finden. Wenn Sie ein wenig nachdenken, können Sie sich so etwas wie diese Methoden vorstellen:
IBaseListAdapterinterface IBaseListAdapter<T> { fun add(newItem: T) fun add(newItems: ArrayList<T>?) fun addAtPosition(pos : Int, newItem : T) fun remove(position: Int) fun clearAll() }
* Beim Durchgehen der Projekte habe ich einige andere Methoden gefunden, die ich hier weglassen werde, zum Beispiel getItemByPos (Position: Int) oder sogar Unterliste (startIndex: Int, endIndex: Int). Ich wiederhole: Sie müssen selbst beobachten, was Sie vom Projekt benötigen, und Funktionen in die Benutzeroberfläche aufnehmen. Es ist nicht schwierig, wenn Sie wissen, dass alles in einer Klasse passiert. Die Askese in dieser Angelegenheit ermöglicht es Ihnen, unnötige Logik zu beseitigen, was die Lesbarkeit des Codes beeinträchtigt, da eine bestimmte Implementierung mehr Zeilen benötigt. Achten Sie auf das generische
T. Im Allgemeinen funktioniert der Adapter mit jedem Objekt der Liste (Element), daher gibt es hier keine Klarstellung - wir haben unseren Ansatz noch nicht gewählt. Und in diesem Artikel wird es mindestens zwei davon geben, die erste Oberfläche sieht so aus:
interface IBaseListItem { fun getLayoutId(): Int }
Ja, es scheint logisch - wir sprechen von einem Listenelement, daher muss jedes Element eine Art Layout haben, und Sie können mit layoutId darauf verweisen. Höchstwahrscheinlich wird ein unerfahrener Entwickler wahrscheinlich nichts brauchen, es sei denn, wir verfolgen natürlich
fortgeschrittenere Ansätze . Wenn Sie genug Erfahrung in der Entwicklung haben, können Sie sicherlich einen Delegierten oder einen Wrapper machen, aber lohnt es sich mit einem kleinen Projekt - und noch weniger Entwicklungserfahrung? Alle meine Links irgendwo auf YouTube sind sehr nützlich, wenn Sie gerade keine Zeit haben - erinnern Sie sich einfach an sie und lesen Sie weiter, da der Ansatz hier einfacher ist. Ich denke, dass bei der Standardarbeit mit
Rv nach der offiziellen Dokumentation das , was oben angeboten wird, nicht der Fall ist impliziert.
Es ist Zeit, unseren
IBaseListAdapter mit Schnittstellen zu kombinieren, und die folgende Klasse wird abstrakt sein:
SimpleListAdapter abstract class SimpleListAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>(), IBaseListAdapter<IBaseListItem> { protected val items: ArrayList<IBaseListItem> = ArrayList() override fun getItemCount() = items.size override fun getItemViewType(position: Int) = items[position].layoutId protected fun inflateByViewType(context: Context?, viewType: Int, parent: ViewGroup) = LayoutInflater.from(context).inflate(viewType, parent, false) override fun add(newItem: IBaseListItem) { items.add(newItem) notifyDataSetChanged() } override fun add(newItems: ArrayList<IBaseListItem>?) { for (newItem in newItems ?: return) { items.add(newItem) notifyDataSetChanged() } } override fun addAtPosition(pos: Int, newItem: IBaseListItem) { items.add(pos, newItem) notifyDataSetChanged() } override fun clearAll() { items.clear() notifyDataSetChanged() } override fun remove(position: Int) { items.removeAt(position) notifyDataSetChanged() } }
* Hinweis: Beachten Sie die überschriebene Funktion
getItemViewType (Position: Int) . Wir benötigen eine Art int-Schlüssel, anhand dessen Rv versteht, welcher ViewHolder zu uns passt.
Val layoutId für unseren
Artikel ist hierfür sehr nützlich, da Android macht die ID der Layouts jedes Mal hilfreich eindeutig und alle Werte sind größer als Null. Wir werden dies später verwenden,
um itemView für unsere Betrachter in der
inflateByViewType () -Methode (nächste Zeile) zu „
aufblasen “.
Erstellen Sie eine Liste
Nehmen Sie zum Beispiel den Einstellungsbildschirm. Android bietet uns
eine eigene Version an, aber was ist, wenn das Design etwas Anspruchsvolleres benötigt? Ich fülle diesen Bildschirm lieber als Liste aus. Hier wird ein solcher Fall gegeben:

Wir sehen zwei verschiedene Listenelemente, daher sind
SimpleListAdapter und
Rv hier perfekt!
Fangen wir an! Sie können mit Layout-Layouts für item'ov beginnen:
item_info.xml; item_switch.xml <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="56dp"> <TextView android:id="@+id/tv_info_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginStart="28dp" android:textColor="@color/black" android:textSize="20sp" tools:text="Balance" /> <TextView android:id="@+id/tv_info_value" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical|end" android:layout_marginEnd="48dp" tools:text="1000 $" /> </FrameLayout> <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="56dp"> <TextView android:id="@+id/tv_switch_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginStart="28dp" android:textColor="@color/black" android:textSize="20sp" tools:text="Send notifications" /> <Switch android:id="@+id/tv_switch_value" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical|end" android:layout_marginEnd="48dp" tools:checked="true" /> </FrameLayout>
Dann definieren wir die Klassen selbst, innerhalb derer wir die Werte übergeben möchten, die mit der Liste interagieren: Der erste ist der Header und ein Wert, der von außen kam (wir haben einen Stub, über Anfragen ein anderes Mal), der zweite ist der Header und die boolesche Variable durch die wir eine Aktion ausführen müssen. Zur Unterscheidung zwischen Switch-Elementen ist die ID der Entitäten vom Server geeignet. Wenn sie nicht vorhanden sind, können wir sie während der Initialisierung selbst erstellen.
InfoItem.kt, SwitchItem.kt class InfoItem(val title: String, val value: String): IBaseListItem { override val layoutId = R.layout.item_info } class SwitchItem( val id: Int, val title: String, val actionOnReceive: (itemId: Int, userChoice: Boolean) -> Unit ) : IBaseListItem { override val layoutId = R.layout.item_switch }
In einer einfachen Implementierung benötigt jedes Element auch einen ViewHolder:
InfoViewHolder.kt, SwitchViewHolder.kt class InfoViewHolder.kt(view: View) : RecyclerView.ViewHolder(view) { val tvTitle = view.tv_info_title val tvValue = view.tv_info_value } class SwitchViewHolder.kt(view: View) : RecyclerView.ViewHolder(view) { val tvTitle = view.tv_switch_title val tvValue = view.tv_switch_value }
Der interessanteste Teil ist die konkrete Implementierung von SimpleListAdapter'a:
SettingsListAdapter.kt class SettingsListAdapter : SimpleListAdapter() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { val context = parent.context return when (viewType) { R.layout.item_info -> InfoHolder(inflateByViewType(context, viewType, parent)) R.layout.item_switch -> SwitchHolder(inflateByViewType(context, viewType, parent)) else -> throw IllegalStateException("There is no match with current layoutId") } } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { when (holder) { is InfoHolder -> { val infoItem = items[position] as InfoItem holder.tvTitle.text = infoItem.title holder.tvValue.text = infoItem.value } is SwitchHolder -> { val switchItem = items[position] as SwitchItem holder.tvTitle.text = switchItem.title holder.tvValue.setOnCheckedChangeListener { _, isChecked -> switchItem.actionOnReceive.invoke(switchItem.id, isChecked) } } else -> throw IllegalStateException("There is no match with current holder instance") } } }
* Hinweis: Vergessen Sie nicht, dass unter der Haube der
inflateByViewType- Methode
(context, viewType, parent): viewType = layoutId.Alle Komponenten sind fertig! Jetzt bleibt der Aktivitätscode erhalten und Sie können das Programm ausführen:
activity_settings.xml <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/rView" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout>
SettingsActivity.kt class SettingsActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_settings) val adapter = SettingsListAdapter() rView.layoutManager = LinearLayoutManager(this) rView.adapter = adapter adapter.add(InfoItem("User Name", "Leo Allford")) adapter.add(InfoItem("Balance", "350 $")) adapter.add(InfoItem("Tariff", "Business")) adapter.add(SwitchItem(1, "Send Notifications") { itemId, userChoice -> onCheck(itemId, userChoice) }) adapter.add(SwitchItem(2, "Send News on Email") { itemId, userChoice -> onCheck(itemId, userChoice) }) } private fun onCheck(itemId: Int, userChoice: Boolean) { when (itemId) { 1 -> Toast.makeText(this, "Notification now set as $userChoice", Toast.LENGTH_SHORT).show() 2 -> Toast.makeText(this, "Send news now set as $userChoice", Toast.LENGTH_SHORT).show() } } }
Beim Erstellen der Liste läuft die gesamte Arbeit daher auf Folgendes hinaus:
1. Berechnung der
Anzahl verschiedener Layouts für Artikel
2. Wählen Sie ihre
Namen . Ich benutze die Regel:
Etwas Item.kt, item_
etwas .xml,
Etwas ViewHolder.kt
3. Wir schreiben einen
Adapter für diese Klassen. Wenn Sie nicht vorgeben, zu optimieren, reicht im Prinzip ein gemeinsamer Adapter aus. Aber in großen Projekten würde ich immer noch ein paar auf den Bildschirmen machen, da im ersten Fall die
onBindViewHolder () -Methode in Ihrem Adapter unweigerlich wächst (die Lesbarkeit des Codes leidet) (in unserem Fall ist es
SettingsListAdapter ) + das Programm muss jedes Mal für jedes Element gestartet werden, Führen Sie diese Methode + die Methode
onCreateViewHolder () aus4. Führen Sie den Code aus und genießen Sie!
Jetpack
Bis zu diesem Moment haben wir den Standardansatz für die Datenbindung von
Item.kt zu unserer
item_layout.xml verwendet . Wir können jedoch die
onBindViewHolder () -Methode vereinheitlichen, minimal lassen und die Logik auf Item und Layout übertragen.
Gehen wir zur offiziellen Android JetPack-Seite:

Achten wir auf die erste Registerkarte im Abschnitt Architektur.
Android Databinding ist ein sehr umfangreiches Thema, ich möchte in anderen Artikeln ausführlicher darauf eingehen, aber im
Moment werden wir es nur als Teil des aktuellen verwenden - wir werden unsere
Item.kt -
Variable für
item.xml machen (oder Sie können es ein Ansichtsmodell für das Layout nennen).
Zum Zeitpunkt des Schreibens konnte die
Datenbindung folgendermaßen verbunden werden:
android { compileSdkVersion 27 defaultConfig {...} buildTypes {...} dataBinding { enabled = true } dependencies { kapt "com.android.databinding:compiler:3.1.3"
Lassen Sie uns noch einmal die Basisklassen durchgehen. Die Schnittstelle für den Artikel ergänzt die vorherige:
interface IBaseItemVm: IBaseListItem { val brVariableId: Int }
Außerdem werden wir unseren ViewHolder erweitern, daher werden wir mit Databyding kontaktiert. Wir werden
ViewDataBinding daran übergeben, danach werden wir sicher vergessen, ein Layout und eine Datenbindung zu erstellen
class VmViewHolder(val binding: ViewDataBinding) : RecyclerView.ViewHolder(binding.root)
Der gleiche Ansatz wird
hier verwendet , aber auf Kotlin sieht es viel kürzer aus, nicht wahr? =)
VmListAdapter class VmListAdapter : RecyclerView.Adapter<VmViewHolder>(), IBaseListAdapter<IBaseItemVm> { private var mItems = ArrayList<IBaseItemVm>() override fun getItemCount() = mItems.size override fun getItemViewType(position: Int) = mItems[position].layoutId override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VmViewHolder { val inflater = LayoutInflater.from(parent.context) val viewDataBinding = DataBindingUtil.inflate<ViewDataBinding>(inflater!!, viewType, parent, false) return VmViewHolder(viewDataBinding) } override fun onBindViewHolder(holder: VmViewHolder, position: Int) { holder.binding.setVariable(mItems[position].brVariableId, mItems[position]) holder.binding.executePendingBindings() } override fun add(newItem: IBaseItemVm) { mItems.add(newItem) notifyItemInserted(mItems.lastIndex) } override fun add(newItems: ArrayList<IBaseItemVm>?) { val oldSize = mItems.size mItems.addAll(newItems!!) notifyItemRangeInserted(oldSize, newItems.size) } override fun clearAll() { mItems.clear() notifyDataSetChanged() } override fun getItemId(position: Int): Long { val pos = mItems.size - position return super.getItemId(pos) } override fun addAtPosition(pos: Int, newItem: IBaseItemVm) { mItems.add(pos, newItem) notifyItemInserted(pos) } override fun remove(position: Int) { mItems.removeAt(position) notifyItemRemoved(position) } }
Beachten Sie generell die Methoden
onCreateViewHolder () ,
onBindViewHolder () . Die Idee ist, dass sie nicht mehr wachsen. Insgesamt erhalten Sie einen Adapter für jeden Bildschirm mit beliebigen Listenelementen.
Unsere Artikel:
InfoItem.kt, SwitchItem.kt class InfoItem(val title: String, val value: String) : IBaseItemVm { override val brVariableId = BR.vmInfo override val layoutId = R.layout.item_info } // class SwitchItem( val id: Int, val title: String, private val actionOnReceive: (itemId: Int, userChoice: Boolean) -> Unit ) : IBaseItemVm { override val brVariableId = BR.vmSwitch override val layoutId = R.layout.item_switch val listener = CompoundButton.OnCheckedChangeListener { _, isChecked -> actionOnReceive.invoke(id, isChecked) } }
Hier können Sie sehen, wohin die Logik der
onBindViewHolder () -Methode
gegangen ist . Die Android-Datenbindung hat es auf sich genommen - jetzt wird jedes unserer Layouts durch sein Ansichtsmodell gesichert und verarbeitet die gesamte Logik von Klicks, Animationen, Abfragen und anderen Dingen in aller Ruhe. Was hast du dir ausgedacht?
Bindungsadapter leisten gute Arbeit, sodass Sie die Ansicht mit Daten jeglicher Art verbinden können. Außerdem kann die Kommunikation dank
bidirektionaler Datenerfassung verbessert werden. Wahrscheinlich wird er in einem der folgenden Artikel blinken, in diesem Beispiel kann alles einfacher gemacht werden. Ein Adapter Adapter reicht uns:
@BindingAdapter("switchListener") fun setSwitchListener(sw: Switch, listener: CompoundButton.OnCheckedChangeListener) { sw.setOnCheckedChangeListener(listener) }
Danach binden wir unsere Variablenwerte mit unserem
Item in xml:
item_info.xml; item_switch.xml <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <data> <import type="com.lfkekpoint.adapters.adapters.presentation.modules.bindableItemsSettings.InfoItem" /> <variable name="vmInfo" type="InfoItem" /> </data> <FrameLayout android:layout_width="match_parent" android:layout_height="56dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginStart="28dp" android:text="@{vmInfo.title}" android:textColor="@color/black" android:textSize="20sp" tools:text="Balance" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical|end" android:layout_marginEnd="48dp" android:text="@{vmInfo.value}" tools:text="1000 $" /> </FrameLayout> </layout> <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> <data> <import type="com.lfkekpoint.adapters.adapters.presentation.modules.bindableItemsSettings.SwitchItem" /> <variable name="vmSwitch" type="SwitchItem" /> </data> <FrameLayout android:layout_width="match_parent" android:layout_height="56dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginStart="28dp" android:text="@{vmSwitch.title}" android:textColor="@color/black" android:textSize="20sp" tools:text="Send notifications" /> <Switch android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical|end" android:layout_marginEnd="48dp" app:switchListener="@{vmSwitch.listener}" tools:checked="true" /> </FrameLayout> </layout>
app: switchListener = "@ {vmSwitch.listener}" - in dieser Zeile haben wir unseren
BindingAdapter verwendet * Hinweis: Aus fairen Gründen scheint es einigen, dass wir viel mehr Code in XML schreiben - dies ist jedoch eine Frage der Kenntnis der Android-Datenbindungsbibliothek. Es ergänzt das Layout, liest schnell und entfernt im Prinzip zum größten Teil genau die Kesselplatte. Ich denke, Google wird diese Bibliothek gut entwickeln, da es die erste auf der Registerkarte Architektur in Android Jetpack ist. Versuchen Sie, MVP in einigen Projekten auf MVVM umzustellen - und viele werden möglicherweise angenehm überrascht sein.
Na dann! .. Ah, der Code in SettingsActivity:
SettingsActivity.kt... hat sich nicht geändert, es sei denn, der Adapter hat sich geändert! =) Aber um nicht über den Artikel zu springen:
class SettingsActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_settings) val adapter = BaseVmListAdapter() rView.layoutManager = LinearLayoutManager(this) rView.adapter = adapter adapter.add(InfoItem("User Name", "Leo Allford")) adapter.add(InfoItem("Balance", "350 $")) adapter.add(InfoItem("Tariff", "Business")) adapter.add(SwitchItem(1, "Send Notifications") { itemId, userChoice -> onCheck(itemId, userChoice) }) adapter.add(SwitchItem(2, "Send News on Email") { itemId, userChoice -> onCheck(itemId, userChoice) }) } private fun onCheck(itemId: Int, userChoice: Boolean) { when (itemId) { 1 -> Toast.makeText(this, "Notification now set as $userChoice", Toast.LENGTH_SHORT).show() 2 -> Toast.makeText(this, "Send news now set as $userChoice", Toast.LENGTH_SHORT).show() } } }
Zusammenfassung
Wir haben einen Algorithmus zum Erstellen von Listen und Tools für die Arbeit mit ihnen. In meinem Fall (ich verwende fast immer die
Datenbindung ) besteht die gesamte Vorbereitung darin, die Basisklassen in Ordnern zu initialisieren, die Elemente in XML zu verteilen und dann an Variablen in .kt zu binden.
Beschleunigung der EntwicklungFür eine schnellere Arbeit habe ich die
Vorlagen von Apache für Android Studio verwendet - und
meine Vorlagen mit einer kleinen
Demonstration der Funktionsweise geschrieben. Ich hoffe wirklich, dass jemand nützlich sein wird. Bitte beachten Sie, dass Sie bei der Arbeit die Vorlage aus dem Projektstammordner aufrufen müssen. Dies geschieht, weil der Parameter
applicationId des Projekts Sie belügen kann, wenn Sie ihn in Gradle geändert haben. Aber
packageName lässt sich nicht so einfach
täuschen , was ich verwendet habe. Die verfügbare Sprache zur Vorlage kann unter den folgenden Links gelesen werden
Referenzen / Medien
1.
Moderne Android-Entwicklung: Android Jetpack, Kotlin und mehr (Google I / O 2018, 40 m.) - eine kurze Anleitung zu dem, was heute in Mode ist. Von hier aus wird auch allgemein klar, wie sich RecyclerView entwickelt hat.
2.
Droidcon NYC 2016 - Radical RecyclerView, 36 m. - Ein ausführlicher Bericht über RecyclerView von
Lisa Wray ;
3.
Erstellen Sie eine Liste mit RecyclerView - offizielle Dokumentation
4.
Schnittstellen vs. Klassen5.
Android IDE-Vorlagenformat ,
Gesamtvorlagen ,
FreeMarker-Handbuch - ein praktischer Ansatz, mit dem im Rahmen dieses Artikels schnell die erforderlichen Dateien für die Arbeit mit Listen erstellt werden können
6.
Code für den Artikel (es gibt leicht unterschiedliche Klassennamen, seien Sie vorsichtig),
Vorlagen für Arbeit und
Video, wie man mit Vorlagen arbeitet7.
Englische Version des Artikels