Elenchi: il vecchio modo vs il nuovo modo con Android Compose

Feb 17 2023
Per quasi 20 anni (dal 2008) quando abbiamo dovuto aggiungere un elenco alla nostra app per Android, abbiamo utilizzato un ListView, che è stato successivamente aggiornato a RecyclerView (nel 2014) come parte di Material Design nelle librerie di supporto Android e successivamente aggiunto come parte di AndroidX (nel 2018). Quindi, nel 2019 è stato annunciato un nuovo modo di lavorare con l'interfaccia utente in Google IO e 2 anni dopo, nel 2021, Google ha rilasciato la prima versione stabile di Jetpack Compose.

Per quasi 20 anni (dal 2008) quando abbiamo dovuto aggiungere un elenco alla nostra app per Android, abbiamo utilizzato un ListView , che è stato successivamente aggiornato a RecyclerView (nel 2014) come parte di Material Design nelle librerie di supporto Android e successivamente aggiunto come parte di AndroidX (nel 2018).

Quindi, nel 2019 è stato annunciato un nuovo modo di lavorare con l'interfaccia utente in Google IO e 2 anni dopo, nel 2021, Google ha rilasciato la prima versione stabile di Jetpack Compose .
Non entrerò in tutta la differenza tra lavorare con compose e i vecchi modi usando xml, oltre a menzionare i 3 vantaggi chiave:

  • meno codifica
  • una fonte di verità (come vedrai nell'esempio qui sotto)
  • ottenere nuove funzionalità/correzioni di bug

Il vecchio modo

  1. Aggiungere all'xml che rappresenta il layout dello schermo un elemento riciclatoView
  2. <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:listitem="@layout/series_item" />
    

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout 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"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        tools:context=".MainActivity"
        android:gravity="center">
    
        <ImageView
            android:id="@+id/imageview"
            android:layout_width="150dp"
            android:layout_height="150dp" />
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent" >
    
            <TextView
                android:id="@+id/title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="10dp"
                android:layout_marginLeft="15dp"
                android:text="Item"
                android:textColor="@color/white"
                android:textSize="20sp"
                android:textStyle="bold" />
    
            <TextView
                android:id="@+id/description"
                android:layout_below="@+id/title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="10dp"
                android:layout_marginLeft="15dp"
                android:text="Item"
                android:textColor="@color/white"
                android:textSize="14sp"
                 />
        </RelativeLayout>
    
    
    
    </LinearLayout>
    

    class SeriesItemAdapter(private val list: List<Series>) : RecyclerView.Adapter<SeriesItemAdapter.SeriesDataHolder>() {
    
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SeriesDataHolder {
            val view = LayoutInflater.from(parent.context)
                .inflate(R.layout.series_item, parent, false)
    
            return SeriesDataHolder(view)
        }
    
        override fun onBindViewHolder(holder: SeriesDataHolder, position: Int) {
            val series = list[position]
    
            holder.imageView.setImageResource(series.imageId)
            holder.titleView.text = series.title
            holder.descriptionView.text = series.description
        }
    
        override fun getItemCount(): Int {
            return list.size
        }
    
        class SeriesDataHolder(ItemView: View) : RecyclerView.ViewHolder(ItemView) {
            val imageView: ImageView = itemView.findViewById(R.id.imageview)
            val titleView: TextView = itemView.findViewById(R.id.title)
            val descriptionView: TextView = itemView.findViewById(R.id.description)
        }
    
    }
    

    val seriesList = findViewById<RecyclerView>(R.id.recyclerview)
            seriesList.layoutManager = LinearLayoutManager(this)
            val adapter = SeriesItemAdapter(SeriesDataProvider.seriesList)
            seriesList.adapter = adapter
    

  3. 2 xml da configurare per l'elenco.
  4. Il posto nel codice da cui colleghi quegli xml.
  5. Una classe adattatore che rappresenta il titolare dei dati e il raccoglitore.
  6. Il nuovo modo

    1. Utilizzare un componibile LazyColumn per l'elenco
    2. @Composable
          fun SeriesList() {
              LazyColumn(
                  modifier = Modifier.background(Color.Black)
              ) {
                  items(
                      items = SeriesDataProvider.seriesList,
                      itemContent = {
                          Series(series = it)
                      }
                  )
              }
          }
      

      Row() {
                  Image(
                      modifier =  Modifier.size(150.dp).align(Alignment.CenterVertically),
                      painter =  painterResource(id = series.imageId),
                      contentDescription = "")
                  Column(
                      modifier = Modifier
                      .padding(16.dp)
                      .align(Alignment.CenterVertically)
                  ) {
                      Text(color = Color.White, text = series.title, style = typography.h6)
                      Text(color = Color.White,text = series.description, style = typography.caption)
                  }
              }