Android recyclerview with gridlayoutmanager is lagging, when using the debug buildType
Android recyclerview with gridlayoutmanager is lagging, when using the debug buildType
I have an unexplained issue with my recyclerview or its adapter. The problem is an annoying lag as a result of the FIRST scroll/swip only.
So far, this is only happening on Galaxy S8 phone (tested on 2 different phones). It is completely smooth on Galaxy S6, which I have also tested on. This is the most confusing fact. The S6 runs Android 7.0 and the S8 runs 8.0.
I have reduced the number of viewtype to use only 1 (1 layout). Here is the adapter part:
class TestAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>
private var mItems: ArrayList<ListItem> = ArrayList()
private var viewPool: RecyclerView.RecycledViewPool = RecyclerView.RecycledViewPool()
constructor(items: ArrayList<ListItem> = ArrayList())
mItems = items
viewPool?.setMaxRecycledViews(ItemType.TEST_VIEWTYPE.index, 100)
override fun getItemViewType(position: Int): Int
return mItems.get(position).getItemType().index
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder
var layoutView = LayoutInflater.from(parent?.context)?.inflate(R.layout.list_item_empty, parent, false)
var viewholder: RecyclerView.ViewHolder = EmptyViewHolder(layoutView)
when (viewType)
ItemType.TEST_VIEWTYPE.index ->
layoutView = LayoutInflater.from(parent?.context)?.inflate(R.layout.list_item_test, parent, false)
viewholder = TestViewholder(layoutView)
return viewholder
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int)
val item = mItems.get(position)
if (holder is TestViewholder && item is ListItemTest)
holder.bind(item)
override fun getItemCount(): Int
return mItems.size
And the view holder "TestViewholder":
class TestViewholder: RecyclerView.ViewHolder
private var mContext: Context? = null
private var mTitlteView: MTTextView? = null
private var mItem: ListItemTest? = null
private var mData: Customer? = null
constructor(view: View?) : super(view)
this.mContext = view?.context
this.mTitlteView = view?.findViewById(R.id.title)
fun bind(item: ListItemTest)
mItem = item
mData = item?.data
mTitlteView?.text = mData?.name
(As shown above, the constructor and bind method are not doing that much)
Here is the xml layout for the viewholder:
<FrameLayout
android:id="@+id/test"
android:layout_width="@dimen/customer_logo_size_medium"
android:layout_height="@dimen/customer_logo_size_medium"
android:orientation="vertical">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/customerLogoImageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/favorite_customer_logo_placeholder"/>
<TextView
android:id="@+id/notificationBubble"
android:layout_width="@dimen/notification_bubble_small"
android:layout_height="@dimen/notification_bubble_small"
android:textColor="@color/white"
android:gravity="center"
android:textSize="@dimen/customer_notification_bubble_text"
android:background="@drawable/notification_bubble_view"
android:textAlignment="center"
android:visibility="visible"/>
</FrameLayout>
<TextView
android:id="@+id/testItemTitle"
android:layout_width="match_parent"
android:layout_height="@dimen/customers_customer_item_title_height"
android:paddingLeft="@dimen/list_item_padding_horizontal_default"
android:paddingRight="@dimen/list_item_padding_horizontal_default"
android:gravity="center"
android:textSize="@dimen/titletext_size"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="25dp"
android:background="@drawable/button_favorite_customer"
android:paddingTop="2dp"
android:paddingBottom="2dp"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:orientation="horizontal">
<TextView
android:id="@+id/customerFavoriteButtonIcon"
style="@style/icon_default"
android:clickable="false"
android:textSize="@dimen/icon_size"
android:textColor="@color/grey"
android:text="@string/icon_favorite"/>
<TextView
android:id="@+id/customerFavoriteButtonText"
style="@style/text_secondary"
android:clickable="false"
android:layout_height="match_parent"
android:layout_marginRight="4dp"
android:textSize="@dimen/favorites_icon_text"
android:textColor="@color/grey"
android:text="@string/pages_customers_favorite_button_text"/>
</LinearLayout>
And here is how I initiliaze it:
if (!adapterInitialized) {
adapterInitialized = true
var columns = if (isBigScreen() && isLandscape()) 6
else if (isLandscape() || isBigScreen()) 4
else 3
val gridLayoutManager = GridLayoutManager(context, columns, GridLayoutManager.VERTICAL, false)
mCustomersRecyclerview?.layoutManager = gridLayoutManager
mCustomersAdapter = TestAdapter(gridLayoutManager, columns)
mCustomersRecyclerview?.adapter = mCustomersAdapter
I have tried to inspect the GPU usage and so on using the tool on the device
(https://developer.android.com/studio/profile/inspect-gpu-rendering).
The results were not what I expected. At the time where the recyclerview was lagging, the dominating color of the bars were the ones with these meanings (taken from link above).
Input Handling: Represents the time that the app spent executing code inside of an input event callback. If this segment is large it indicates that the app is spending too much time processing the user input. Consider offloading such processing to a different thread.
[Misc Time / VSync Delay]: Represents the time that the app spends
executing operations in between two consecutive frames. It might be an
indicator of too much processing happening in the UI thread that could
be offloaded to a different thread.
Apparently, switching to my release build instead of the debug build, solved it.
However, I am quite curious about, why and how this can affect the performance like this. Here is the 2 buildTypes from my gradle:
debug
minifyEnabled false
shrinkResources false
debuggable true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard.cfg'
signingConfig signingConfigs.debugConfig
applicationIdSuffix ".debug"
versionNameSuffix "-debug"
resValue "string", "app_name", "myapp$versionNameSuffix"
release
minifyEnabled true
shrinkResources true
debuggable false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard.cfg'
signingConfig signingConfigs.releaseConfig
resValue "string", "app_name", "myapp"
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Note we prefer a technical style of writing here. We gently discourage greetings, hope-you-can-helps, thanks, advance thanks, notes of appreciation, regards, kind regards, signatures, please-can-you-helps, chatty material and abbreviated txtspk, pleading, how long you've been stuck, voting advice, meta commentary, etc. Just explain your problem, and show what you've tried, what you expected, and what actually happened.
– halfer
Aug 23 at 23:55