Kapsamlı Anlatım ile Android RecyclerView Kullanımı

Kapsamlı Anlatım ile Android RecyclerView Kullanımı
REKLAM Makale içi AdSense alanı

RecyclerView, Android'de liste veya grid gibi tekrarlayan verileri performanslı bir şekilde göstermek için kullanılan en güçlü bileşenlerden biridir. Modern Android uygulamalarında, eski ListView bileşeninin yerini tamamen almıştır. Bu makalede RecyclerView’un ne olduğunu, nasıl kullanıldığını ve en iyi kullanım pratiklerini adım adım öğreneceksiniz.


RecyclerView Nedir?

RecyclerView, Android Jetpack kütüphanelerinin bir parçasıdır ve büyük veri setlerinin verimli bir şekilde kullanıcıya sunulmasını sağlar. Adından da anlaşılacağı gibi, görünüm hücrelerini geri dönüştürerek (recycle) belleği ve işlemciyi optimize eder.

Özellikleri:

  • Scroll edilebilir liste ve grid oluşturma
  • Farklı ViewType desteği
  • Animasyonlarla geçişler
  • Swipe, drag & drop desteği
  • ViewBinding, DiffUtil, ListAdapter ile uyumluluk

Gerekli Bağımlılıklar

build.gradle (app):

dependencies {
    implementation 'androidx.recyclerview:recyclerview:1.3.1'
}

Jetpack Compose kullanmıyorsanız RecyclerView için bu bağımlılık yeterlidir. Ek olarak ViewBinding aktif olmalıdır:

android {
    buildFeatures {
        viewBinding true
    }
}

RecyclerView Kullanım Adımları

RecyclerView kullanımı için temel bileşenler şunlardır:

  1. RecyclerView bileşeni (layout içinde)
  2. ViewHolder (her bir satırı temsil eden sınıf)
  3. Adapter (veriyi bağlayan sınıf)
  4. LayoutManager (liste düzeni)

1. XML Tasarımı

activity_main.xml

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    tools:listitem="@layout/item_user" />

item_user.xml

<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="8dp"
    android:elevation="4dp"
    android:padding="12dp">

    <TextView
        android:id="@+id/textViewName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Kullanıcı Adı"
        android:textSize="18sp"
        android:textStyle="bold" />

</androidx.cardview.widget.CardView>

Model Sınıfı

data class User(val id: Int, val name: String)

ViewHolder ve Adapter

class UserAdapter(private val userList: List<User>) :
    RecyclerView.Adapter<UserAdapter.UserViewHolder>() {

    inner class UserViewHolder(val binding: ItemUserBinding) :
        RecyclerView.ViewHolder(binding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
        val binding = ItemUserBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return UserViewHolder(binding)
    }

    override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
        val user = userList[position]
        holder.binding.textViewName.text = user.name
    }

    override fun getItemCount(): Int = userList.size
}

RecyclerView Tanımlama – MainActivity.kt

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

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

        val sampleList = listOf(
            User(1, "Ahmet Yılmaz"),
            User(2, "Zeynep Demir"),
            User(3, "Mehmet Kara")
        )

        val adapter = UserAdapter(sampleList)

        binding.recyclerView.layoutManager = LinearLayoutManager(this)
        binding.recyclerView.adapter = adapter
    }
}

ListAdapter ve DiffUtil ile Gelişmiş Kullanım (Önerilir)

RecyclerView içinde büyük veri setleriyle çalışırken notifyDataSetChanged() yerine DiffUtil kullanmak performansı ciddi oranda artırır.

class UserDiffCallback : DiffUtil.ItemCallback<User>() {
    override fun areItemsTheSame(oldItem: User, newItem: User) = oldItem.id == newItem.id
    override fun areContentsTheSame(oldItem: User, newItem: User) = oldItem == newItem
}

class UserListAdapter : ListAdapter<User, UserListAdapter.UserViewHolder>(UserDiffCallback()) {

    inner class UserViewHolder(val binding: ItemUserBinding) :
        RecyclerView.ViewHolder(binding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
        val binding = ItemUserBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return UserViewHolder(binding)
    }

    override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
        val user = getItem(position)
        holder.binding.textViewName.text = user.name
    }
}

En İyi Kullanım Tavsiyeleri

  • ViewBinding kullanın: XML şişkinliğini azaltır, hataları önler.
  • ListAdapter + DiffUtil: Büyük veri setlerinde notifyDataSetChanged() yerine tercih edilmelidir.
  • ViewType desteği ekleyin: Farklı satır görünümleri gerekiyorsa getItemViewType() ile destekleyin.
  • Lifecycle-aware yaklaşım: LiveData veya StateFlow ile birlikte kullanın.
  • RecyclerView optimizasyonları: setHasFixedSize(true) kullanımı performansı artırır.

RecyclerView ile Kullanılabilecek Diğer Olaylar ve Özellikler


1. Sonsuz Liste / Sayfalama (Pagination)

Büyük veri setlerinde verilerin hepsini aynı anda yüklemek hem kullanıcı deneyimini bozar hem de performans sorunlarına neden olur. Bunun yerine, verileri sayfa sayfa yüklemek (infinite scroll) tercih edilir.

Kullanım Mantığı:

recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
        val layoutManager = recyclerView.layoutManager as LinearLayoutManager
        val lastVisibleItem = layoutManager.findLastVisibleItemPosition()
        val totalItemCount = layoutManager.itemCount

        if (!isLoading && lastVisibleItem >= totalItemCount - 3) {
            loadNextPage() // API'den sonraki verileri çek
            isLoading = true
        }
    }
})

2. Swipe ile Silme (Swipe to Delete)

RecyclerView’de bir öğeyi sağa veya sola kaydırarak silmek için ItemTouchHelper kullanılır.

val itemTouchHelperCallback = object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
    override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder) = false

    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
        val position = viewHolder.adapterPosition
        myList.removeAt(position)
        adapter.notifyItemRemoved(position)
    }
}
ItemTouchHelper(itemTouchHelperCallback).attachToRecyclerView(recyclerView)

3. Drag & Drop

Öğelerin sürüklenerek yer değiştirmesini sağlamak için yine ItemTouchHelper kullanılabilir. Bu sayede kullanıcılar liste sırasını değiştirebilir.

4. Çoklu ViewType Kullanımı (Multiple View Types)

Bazı listelerde farklı tipte öğeler aynı RecyclerView içinde gösterilir. Örneğin, başlık, içerik ve footer gibi. Bunun için getItemViewType() metodu kullanılır.

override fun getItemViewType(position: Int): Int {
    return when (items[position]) {
        is Header -> VIEW_TYPE_HEADER
        is Content -> VIEW_TYPE_CONTENT
        is Footer -> VIEW_TYPE_FOOTER
        else -> throw IllegalArgumentException("Bilinmeyen tip")
    }
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    return when (viewType) {
        VIEW_TYPE_HEADER -> {
            val binding = ItemHeaderBinding.inflate(LayoutInflater.from(parent.context), parent, false)
            HeaderViewHolder(binding)
        }
        VIEW_TYPE_CONTENT -> {
            val binding = ItemContentBinding.inflate(LayoutInflater.from(parent.context), parent, false)
            ContentViewHolder(binding)
        }
        VIEW_TYPE_FOOTER -> {
            val binding = ItemFooterBinding.inflate(LayoutInflater.from(parent.context), parent, false)
            FooterViewHolder(binding)
        }
        else -> throw IllegalArgumentException("Bilinmeyen viewType")
    }
}

5. Item Seçimi & Vurgulama (Selection State)

RecyclerView öğelerinin seçilmesi ve seçili öğelerin vurgulanması için item'ların durumunu yönetmeniz gerekir. Basitçe adapter içinde seçili pozisyonu tutabilir ve seçimi değiştirdiğinizde ilgili itemların arayüzünü güncelleyebilirsiniz.

class UserAdapter(private val userList: List<User>) :
    RecyclerView.Adapter<UserAdapter.UserViewHolder>() {

    private var selectedPosition = RecyclerView.NO_POSITION

    inner class UserViewHolder(val binding: ItemUserBinding) :
        RecyclerView.ViewHolder(binding.root) {
        init {
            binding.root.setOnClickListener {
                notifyItemChanged(selectedPosition)
                selectedPosition = adapterPosition
                notifyItemChanged(selectedPosition)
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
        val binding = ItemUserBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return UserViewHolder(binding)
    }

    override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
        val user = userList[position]
        holder.binding.textViewName.text = user.name
        holder.itemView.isSelected = (selectedPosition == position)
        // Veya farklı bir vurgulama: background renk değiştirme gibi
        holder.itemView.setBackgroundColor(
            if (selectedPosition == position) Color.LTGRAY else Color.WHITE
        )
    }

    override fun getItemCount(): Int = userList.size
}

Eğer RecyclerView ile ilgili daha spesifik bir kullanım veya kod örneği istersen, ya da başka Android konularında destek lazım olursa bana sorabilirsin.

Şerif Güngör

Yazar: Şerif Güngör

Android Dersleri 2025, Raspberry Pi Dersleri, PHP Dersleri - Şerif Güngör Blog

Yorumlar