Sparround

RecyclerView, ViewBinding, ConstraintLayout — performans

RecyclerView böyük siyahıların standartıdır — mahiyyəti view recycling: ekrandan çıxan item-in view-u hovuza qayıdır, yeni item üçün yenidən istifadə olunur (onBindViewHolder yalnız datanı bağlayır, inflate olunmur).

Açar hissələr:

  • ViewHolder — view istinadlarını saxlayır, findViewById təkrarının qarşısını alır
  • DiffUtil / ListAdapter — köhnə/yeni siyahını müqayisə edib yalnız dəyişən item-ləri yeniləyir; notifyDataSetChanged()-in bahalı alternativisiz istifadəsi antipatterndir
  • ItemDecoration / ItemAnimator — ayırıcılar və animasiyalar

ViewBinding — hər layout üçün type-safe binding class generasiya edir: findViewById yoxdur, null-safety var, DataBinding-dən fərqli olaraq layout-da məntiq yazılmır (DataBinding expression-ları müasir kodda tövsiyə olunmur).

ConstraintLayout — düz (flat) iyerarxiya ilə mürəkkəb layout: iç-içə LinearLayout-ların (xüsusilə layout_weight ilə) yaratdığı ikiqat measure pass-lardan qaçır. Dərin view iyerarxiyası = yavaş measure/layout = frame drop.

kotlin
class TransactionAdapter :
    ListAdapter<TransactionUi, TransactionAdapter.VH>(Diff) {

    object Diff : DiffUtil.ItemCallback<TransactionUi>() {
        override fun areItemsTheSame(a: TransactionUi, b: TransactionUi) = a.id == b.id
        override fun areContentsTheSame(a: TransactionUi, b: TransactionUi) = a == b
    }

    class VH(val binding: ItemTransactionBinding) : RecyclerView.ViewHolder(binding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = VH(
        ItemTransactionBinding.inflate(LayoutInflater.from(parent.context), parent, false)
    )

    override fun onBindViewHolder(holder: VH, position: Int) {
        val item = getItem(position)
        holder.binding.title.text = item.title
        holder.binding.amount.text = item.formattedAmount
    }
}

// İstifadə: adapter.submitList(newList) — diff arxa planda hesablanır

ListAdapter + DiffUtil — müasir siyahı adapteri

Performans sualının cavab çərçivəsi: (1) siyahı — ListAdapter/DiffUtil, setHasFixedSize(true), item layout-larının sadələşdirilməsi, şəkillər üçün Coil/Glide (placeholder + ölçü); (2) iyerarxiya — Layout Inspector ilə dərinliyi yoxla, ConstraintLayout-a keç, merge/ViewStub; (3) ölçmə — Profiler + Choreographer frame metrikaları. "OnBindViewHolder-də nə etmək olmaz?" — obyekt yaratmaq, şəkil sinxron yükləmək, listener-i hər bind-də yenidən qurmaq.

🛠 Tapşırıq

50+ elementli siyahı qur və üç dəyişikliyi ölç:

  • Əvvəl notifyDataSetChanged() ilə yenilə, sonra ListAdapter + DiffUtil (submitList) ilə — animasiya və hamarlıq fərqini gör.
  • onBindViewHolder içində qəsdən obyekt yarat və Profiler-də allocation-lara bax; sonra təmizlə.
  • Layout Inspector ilə item layout-un dərinliyini yoxla, iç-içə LinearLayout-u ConstraintLayout-a çevir.

Bitdi sayılır: "siyahı ləng işləyir" sualına ölç → düzəlt → ölç axını ilə cavab verirsənsə.

📚 Mənbələr və sənədlər