ListView: vad är det, enkla listor i Android-appar

Författare: IT Sectr Publicerad: 2026-02-23 Lästid: 8 min

ListView — grundläggande Android-komponent för att visa vertikala listor, tillgänglig från API 1 (Android 1.0). ListView skapar en lista av element med hjälp av ArrayAdapter och stöder anpassade cellayouter. Lär dig vad ListView är, hur du konfigurerar det och vilka fallgropar denna gamla men fortfarande använda komponent döljer. På IT Sectr stöter vi på ListView i legacy-projekt och upprätthåller bakåtkompatibilitet med Android 4.4. För jämförelse med det moderna alternativet läs artikeln om RecyclerView.

Huvudpunkter

  • ListView — inbyggd Android SDK-komponent för vertikala listor, introducerad i Android 1.0.
  • ArrayAdapter — standardadapter för att binda en datamatris till ListView via toString() eller anpassad layout.
  • SimpleAdapter — adapter för listor från Map-data, bekväm för enkla skärmar utan ViewModel.
  • onItemClickListener — inbyggd klickhanterare som inte kräver ytterligare implementering i adaptern.
  • convertView — mekanism för återanvändning av View i ListView som utvecklaren måste implementera manuellt (analogt med ViewHolder).

Vad är ListView i Android?

ListView — är en View-grupp från paketet android.widget, avsedd för att visa en rullningsbar lista av element. ListView implementerar AdapterView-mönstret: data skickas via en adapter (Adapter) som konverterar dataelement till View som visas på skärmen. ListView har funnits i Android SDK sedan första versionen (API 1) och kräver inga extra bibliotek.

Arkitektur för ListView är enklare än RecyclerView: LayoutManager är inbyggd (endast vertikal rullning), animering av ändringar saknas, avgränsare ställs in via XML-attributet android:divider. ListView lägger automatiskt till OverScrollView och markering vid fokus, vilket förenklar prototypframställning. Enligt Statista (2025) innehåller cirka 15% av Android-apparna i Play Store topp-100 fortfarande ListView — främst legacy-projekt med minimalt stöd.

Historia och aktualitet

ListView var den huvudsakliga listkomponenten i Android från 2008 till 2014, när RecyclerView presenterades på Google I/O 2014. Trots statusen som delvis föråldrad (soft-deprecated) förblir ListView tillgänglig i alla Android-versioner och är inte markerad som @Deprecated i SDK API 35. Om ditt projekt stöder Android 4.4 (API 19) och lägre är ListView det enda inbyggda valet, eftersom RecyclerView kräver AndroidX och gradle-beroenden.

Typer av adaptrar: ArrayAdapter och SimpleAdapter

ArrayAdapter — den mest populära adaptern för ListView. Den accepterar List<T> och en layout för varje element. Som standard anropar ArrayAdapter toString() för varje objekt och visar texten i simple_list_item_1 (en TextView). För anpassad visning måste getView() åsidosättas eller en anpassad layout skickas i konstruktorn.

kotlin
// ListView med ArrayAdapter (enkel text)
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private val countries = listOf(
        "Ryssland", "USA", "Tyskland",
        "Frankrike", "Japan", "Kina", "Brasilien"
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val adapter = ArrayAdapter<String>(
            this,
            android.R.layout.simple_list_item_1,
            countries
        )
        binding.listView.adapter = adapter

        // Klickhantering
        binding.listView.onItemClickListener =
            AdapterView.OnItemClickListener { _, _, position, _ ->
                Toast.makeText(this, countries[position], Toast.LENGTH_SHORT).show()
            }
    }
}

SimpleAdapter är avsedd för listor från Map-data. Den accepterar List<Map<String, Any>> och en from/to-matris för att binda Map-nycklar med ID:n för widgetar i layouten. SimpleAdapter är bekväm för snabba prototyper när ingen separat adapterklass behövs. Nackdel — brist på type-safe-typning och komplexitet med anpassad logik.

xml
<!-- Layout med ListView -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:divider="@color/divider"
        android:dividerHeight="1px"
        android:scrollbars="vertical" />
</LinearLayout>

Skapa en anpassad adapter med ViewHolder

Anpassad adapter för ListView åsidosätter metoden getView(), som RecyclerView delar upp i onCreateViewHolder + onBindViewHolder. I ListView är båda stegen kombinerade, så utvecklaren måste implementera ViewHolder-mönstret självständigt via convertView (återanvänd View) och tag setTag().

kotlin
// Datamodell
data class Product(
    name: String,
    price: String,
    imageResId: Int
)

// Anpassad adapter med ViewHolder
class ProductAdapter(
    context: Context,
    private val products: List<Product>
) : ArrayAdapter<Product>(context, 0, products) {

    // ViewHolder för cachning
    private class ViewHolder(view: View) {
        val nameText: TextView = view.findViewById(R.id.tvName)
        val priceText: TextView = view.findViewById(R.id.tvPrice)
        val imageView: ImageView = view.findViewById(R.id.ivProduct)
    }

    override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
        val view = convertView ?: LayoutInflater.from(context)
            .inflate(R.layout.item_product, parent, false)
            .also { it.tag = ViewHolder(it) }

        val holder = view.tag as ViewHolder
        val product = getItem(position)

        holder.nameText.text = product.name
        holder.priceText.text = product.price
        holder.imageView.setImageResource(product.imageResId)

        return view
    }
}

Viktig skillnad från RecyclerView: i ListView anropas metoden getView() för varje gång ett element visas på skärmen. Om convertView och ViewHolder inte används skapar varje rullning ett nytt View-objekt, vilket leder till minnesläckor och fördröjning på listor med 50+ element. ViewHolder med view.tag — obligatorisk optimering för ListView med anpassade layouter.

Begränsningar för ListView: varför Google rekommenderar RecyclerView

ListView har fyra arkitektoniska begränsningar som Google åtgärdade i RecyclerView: (1) endast vertikal orientering — inga rutnät, horisontella listor eller kaskader; (2) avsaknad av punktmeddelanden — varje dataändring orsakar fullständig omritning via notifyDataSetChanged(), vilket skapar ryckighet; (3) ingen inbyggd animering för tillägg/borttagning av element; (4) ingen separation av ansvarsområden — LayoutManager är inbyggd, ItemAnimator saknas.

xml
<!-- item_product.xml — layout för ListView-element -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="12dp">

    <ImageView
        android:id="@+id/ivProduct"
        android:layout_width="56dp"
        android:layout_height="56dp"
        android:scaleType="centerCrop" />

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical"
        android:paddingStart="12dp">

        <TextView
            android:id="@+id/tvName"
            android:textSize="16sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/tvPrice"
            android:textSize="14sp"
            android:textColor="@color/price" />
    </LinearLayout>
</LinearLayout>

Praktiska konsekvenser: på listor upp till 20 element fungerar ListView lika snabbt som RecyclerView. Vid 100+ element blir skillnaden märkbar: ListView börjar tappa FPS på grund av brist på differentiella beräkningar och tvingad ViewHolder. För listor med frekventa uppdateringar (chatt, feed, loggar) är ListView inte lämplig — använd RecyclerView med Paging 3. På IT Sectr migrerar vi ListView till RecyclerView vid varje arbete på legacy-skärmar med mer än 50 element.

Konfigurera ListView via XML-attribut

ListView tillhandahåller en uppsättning XML-attribut för snabb konfiguration utan kod: android:divider (färg/bild på avgränsare), android:dividerHeight (tjocklek), android:scrollbars (rullningslister), android:fastScrollEnabled (snabb rullning via handtag), android:choiceMode (markeringsläge: singleChoice, multipleChoice). Attributet android:entries gör det möjligt att fylla listan från en resursmatris (string-array) utan adapter.

AttributBeskrivningExempelvärde
android:dividerFärg eller drawable för avgränsare@color/gray_light
android:dividerHeightTjocklek på avgränsare i px/dp1dp
android:entriesMatris med strängar från resurser@array/countries
android:choiceModeMarkeringsläge för elementsingleChoice
android:fastScrollEnabledSnabb rullningtrue
android:overlapAnchorAnkare för popup-listor (API 21+)true

Markeringsläge: choiceMode="singleChoice" aktiverar RadioButton-stil, där det markerade elementet markeras. choiceMode="multipleChoice" — kryssrutor för flera element. Markeringsdata är tillgänglig via listView.checkedItemPosition eller listView.checkedItemIds. Viktigt: vid choiceMode använder ListView StateListDrawable för bakgrunden — ställ in en egen väljare om standardblått inte passar designen.

ListView vs RecyclerView: jämförelse av funktioner

Val mellan ListView och RecyclerView beror på projektets krav. RecyclerView är den moderna standarden, men ListView kan vara motiverad för enkla skärmar med minimala underhållskostnader för gammal kod. Jämförelse baserat på alla nyckelparametrar:

ParameterListViewRecyclerView
BiblioteksstorlekInbyggd i SDK (≈60 KB)AndroidX (≈300 KB med beroenden)
Minsta versionAPI 1API 14 (via AndroidX)
OrienteringEndast vertikalVertikal, horisontell, rutnät, kaskad
ViewHolderManuell implementeringObligatorisk enligt arkitektur
AnimeringEndast fade-övergångarDefaultItemAnimator (add, remove, move, change)
PunktuppdateringarNej (endast notifyDataSetChanged)notifyItemInserted/Removed/Changed
Click listeneronItemClickListener (inbyggd)Via ViewHolder (ingen inbyggd)
PrestandaTillräcklig för listor upp till 50 elementStabila 60 FPS för 1000+ element

Slutsats: för nya projekt använd RecyclerView. Lämna ListView endast i legacy-kod där migrering är orimligt dyr. Enligt riktlinjerna för Material Design 3 (2026) bör listor av vilken komplexitet som helst använda RecyclerView för att uppfylla moderna prestanda- och tillgänglighetsstandarder.

Vanliga frågor

Är ListView föråldrat eller inte?

ListView är inte markerat som @Deprecated i Android SDK API 35, men Google rekommenderar inte att det används i nya projekt (soft-deprecated). Komponenten förblir funktionell i alla Android-versioner. RecyclerView är den officiella ersättaren sedan 2014. Om du startar ett nytt projekt — välj RecyclerView. Om du underhåller ett befintligt — kommer ListView att fortsätta fungera utan ändringar.

Hur lägger man till header/footer i ListView?

ListView stöder metoderna addHeaderView(View, Object, boolean) och addFooterView(View, Object, boolean). Header och footer läggs till i den allmänna listan av element, men deltar inte i adaptern — de visas alltid i början och slutet av listan. Viktigt: lägg till header/footer innan du ställer in adaptern (setAdapter()), annars kommer de inte att beaktas. Efter att ha lagt till header förskjuts ID:n för elementpositioner med antalet headers.

Varför rullar inte ListView inuti ScrollView?

ListView och ScrollView hanterar båda vertikala gester, vilket skapar en konflikt: den yttre ScrollView fångar upp rullningen och ListView rullar inte. Lösning: (1) lägg inte ListView i ScrollView — använd RecyclerView med NestedScrollingChild, (2) ersätt ScrollView med NestedScrollView (API 21+), (3) använd ListView med fast höjd (android:layout_height="...dp") inuti ScrollView, men detta kommer att bryta anpassningsbarheten.

Hur rensar man ListView och uppdaterar data?

Rensning av data i ListView beror på adaptertypen. För ArrayAdapter: adapter.clear() och adapter.addAll(newList) följt av adapter.notifyDataSetChanged(). För anpassad adapter: uppdatera datalistan och anropa notifyDataSetChanged(). Observera: listView.invalidateViews() ritar bara om View, men uppdaterar inte data. Ändra alltid data via adaptern, inte direkt.

Hur ändrar man höjden på ett ListView-element?

Höjden på ett ListView-element ställs in i item-layouten. Om layouten använder layout_height="wrap_content" anpassar sig höjden efter innehållet. För fast höjd på alla element använder du en anpassad adapter som ställer in LayoutParams i getView(): view.layoutParams.height = resources.getDimensionPixelSize(R.dimen.itemHeight). För olika höjder använder du RecyclerView med olika vytyper.

Sammanfattning

  • ListView — grundläggande Android SDK-komponent för vertikala listor, tillgänglig sedan API 1.
  • ArrayAdapter — den enklaste adaptern för en lista av strängar; för anpassade layouter krävs åsidosatt getView().
  • ViewHolder i ListView implementeras manuellt via convertView och view.tag — obligatoriskt prestandakrav.
  • ListView stöder choiceMode (single/multiple), header/footer, fastScroll och android:entries utan adapter.
  • Begränsningar för ListView: endast vertikal orientering, ingen animering, fullständig omritning vid varje ändring.
  • ListView är inte markerat som föråldrat, men Google rekommenderar RecyclerView för alla nya projekt.
  • För listor upp till 50 element är ListView tillräckligt; för allt mer komplext — använd RecyclerView.

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också