I'm currently using DataBinding with a RecyclerView, and I'm getting pretty severe lag when a list first loads. However, after I scroll past a page and it stops creating new viewholders, everything is fine.
During creation, the only thing I'm doing is inflating a layout using DataBindingUtils, so I'm wondering if there are parts that can be improved.
Attached below are relevant code snippets. I'm currently using a library, FastAdapter, so the signatures will not match exactly
When creating a viewholder, I do the following:
override fun createView(ctx: Context, parent: ViewGroup?): View {
val start = System.nanoTime()
val binding: ViewDataBinding = DataBindingUtil.inflate(
LayoutInflater.from(ctx),
layoutRes, parent,
false,
null
)
L.d { "Create view ${(System.nanoTime() - start) / 1000000}" }
return binding.root
}
It appears that for my more complex layout, viewholders take around 30-60 ms each, resulting in notable lag.
Binding and unbinding are like so:
final override fun bindView(holder: ViewHolder, payloads: MutableList<Any>) {
super.bindView(holder, payloads)
val binding = DataBindingUtil.getBinding<Binding>(holder.itemView) ?: return
binding.bindView(holder, payloads)
binding.executePendingBindings()
}
open fun Binding.bindView(holder: ViewHolder, payloads: MutableList<Any>) {
setVariable(BR.model, data)
}
final override fun unbindView(holder: ViewHolder) {
super.unbindView(holder)
val binding = DataBindingUtil.getBinding<Binding>(holder.itemView) ?: return
binding.unbindView(holder)
binding.unbind()
}
open fun Binding.unbindView(holder: ViewHolder) {}
final override fun getViewHolder(v: View): ViewHolder = ViewHolder(v, layoutRes)
Basically, I usually have a single data model that I set, and I implement unbinding myself per viewholder. There doesn't seem to be a problem there.
Reading other articles, it appears that most developers have the same viewholder creation method as I do. Is DataUtilBinding not meant to be done upon creation, or is there something I'm missing?
As an addition, here is my relevant layout xml:
<?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>
<variable
name="model"
type="github.fragment.ShortRepoRowItem" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:windowBackground"
android:foreground="?selectableItemBackground"
android:paddingStart="@dimen/kau_activity_horizontal_margin"
android:paddingTop="@dimen/kau_padding_small"
android:paddingEnd="@dimen/kau_activity_horizontal_margin"
android:paddingBottom="@dimen/kau_padding_small"
tools:context=".activity.MainActivity">
<TextView
android:id="@+id/repo_name"
style="@style/TextAppearance.AppCompat.Medium"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@{model.name}"
android:textColor="?android:textColorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="@tools:sample/full_names" />
<TextView
android:id="@+id/repo_desc"
style="@style/TextAppearance.AppCompat.Caption"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:text="@{model.description}"
android:textColor="?android:textColorSecondary"
app:goneFlag="@{model.description}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/repo_name"
tools:text="@tools:sample/lorem/random" />
<com.google.android.material.chip.Chip
android:id="@+id/repo_stars"
style="@style/RepoChips"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:chipIcon="@drawable/ic_star_border"
app:compactNumberText="@{model.stargazers.totalCount}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/repo_desc"
app:layout_constraintWidth_percent="0.12"
tools:text="123" />
<com.google.android.material.chip.Chip
android:id="@+id/repo_forks"
style="@style/RepoChips"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:chipIcon="@drawable/ic_fork"
app:compactNumberText="@{model.forkCount}"
app:layout_constraintStart_toEndOf="@id/repo_stars"
app:layout_constraintTop_toBottomOf="@id/repo_desc"
app:layout_constraintWidth_percent="0.12"
tools:text="123" />
<com.google.android.material.chip.Chip
android:id="@+id/repo_issues"
style="@style/RepoChips"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:chipIcon="@drawable/ic_issues"
app:compactNumberText="@{model.issues.totalCount}"
app:layout_constraintStart_toEndOf="@id/repo_forks"
app:layout_constraintTop_toBottomOf="@id/repo_desc"
app:layout_constraintWidth_percent="0.12"
tools:text="1.5k" />
<com.google.android.material.chip.Chip
android:id="@+id/repo_prs"
style="@style/RepoChips"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:chipIcon="@drawable/ic_pull_requests"
app:compactNumberText="@{model.pullRequests.totalCount}"
app:layout_constraintStart_toEndOf="@id/repo_issues"
app:layout_constraintTop_toBottomOf="@id/repo_desc"
app:layout_constraintWidth_percent="0.12"
tools:text="123" />
<com.google.android.material.chip.Chip
android:id="@+id/repo_language"
style="@style/RepoChips"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@{model.primaryLanguage.name}"
app:chipIcon="@drawable/ic_language"
app:languageColor="@{model.primaryLanguage.color}"
app:layout_constraintEnd_toStartOf="@id/repo_date"
app:layout_constraintStart_toEndOf="@id/repo_prs"
app:layout_constraintTop_toBottomOf="@id/repo_desc"
app:layout_constraintWidth_percent="0.25"
tools:text="JavaScript" />
<com.google.android.material.chip.Chip
android:id="@+id/repo_date"
style="@style/RepoChips"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:chipIcon="@drawable/ic_time"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/repo_language"
app:layout_constraintTop_toBottomOf="@id/repo_desc"
app:relativeDateText="@{model.pushedAt}"
app:textStartPadding="4dp"
tools:text="@tools:sample/date/mmddyy" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
I've tried doing the same thing with two linear layouts instead of ConstraintLayout, but it doesn't seem to make much of a difference.
Code snapshot: https://github.com/AllanWang/GitDroid/tree/f802c991580d70470b422186fc43f46b9cfe2465