Skip to content

Android ListViews #14407

@m1ga

Description

@m1ga

Since some people complain about the ListView performance I thought it might be interesting to fire some agents on it to look at it 😄

Current Optimizations (Already Implemented)

  • DiffUtil for efficient adapter updates
  • View recycling using template-based view types
  • Stable IDs enabled via setHasStableIds(true)
  • Custom pre-caching during the first layout pass
  • List animations disabled to reduce unnecessary UI work
  • RecyclerView.setItemViewCacheSize(0) with a custom workaround

Identified Performance Issues & Recommended Improvements

1. Linear Search in getAdapterIndex() / getRowByIndex()

Location: TiListView.java:462–528
Issue: Both methods perform a linear scan through all items while comparing the index field.
Impact: Each lookup is O(n). This occurs during scrolling and marker operations, increasing overhead on large lists.
Recommendation: Introduce an index lookup cache:

HashMap<Integer, ListItemProxy>

The map should be updated whenever list items change, enabling O(1) lookups.

2. Expensive DiffUtil Content Comparison

Location: TiRecyclerViewAdapter.java:193–198
Issue: areContentsTheSame() recomputes hashes every comparison:

final long oldHash = oldProperties.hashCode() ^ Arrays.hashCode(oldView.getChildren());

This requires creating new arrays and computing hashes repeatedly.
Impact: Significant overhead during dataset updates and increased GC pressure.
Recommendation: Cache computed hashes inside ListItemProxy (property hash + children hash) and reuse them.

3. Inefficient Search / Filter Implementation (implemented)

Location: TiListView.java:681–719
Issue: toLowerCase() is called on every item's searchableText during filtering.
Impact: Repeated string allocations and increased CPU usage.
Recommendation: Cache the lowercase representation (lowercaseSearchableText) when the property is assigned.

4. Inefficient LinkedList.contains() in Recyclable Map

Location: ListViewAdapter.java:139
Issue: Uses recyclableItems.contains(item) which is O(n) for LinkedList.
Recommendation: Replace with HashSet for O(1) checks or remove the check if the item was already removed earlier.

5. Selection Tracker Heavy Iteration

Location: TiListView.java:313–337
Issue: A new KrollDict is created for each selected item and the full selection is iterated on every change.
Impact: Excessive allocations and processing overhead.
Recommendation: Batch selection updates, reuse KrollDict objects, or defer processing.

6. Missing RecyclerView Optimizations

setHasFixedSize(true) Not Enabled by Default
Issue: Only enabled when explicitly configured.
Impact: RecyclerView cannot fully optimize layout calculations when item sizes are constant.
Recommendation: Enable automatically when list dimensions are known.

Missing RecycledViewPool Optimization
Issue: No custom configuration for RecyclerView.RecycledViewPool.
Recommendation: Preconfigure the pool with expected view type counts to reduce view inflation and improve recycling.

7. View Binding Inefficiencies

Location: ListViewHolder.java

Full Reset on Every Bind
Issue: reset() removes all views and re-adds them even when the template is unchanged.
Impact: Unnecessary view operations and layout work.
Recommendation: Skip reset() when the recycled view uses the same template.

Repeated Theme Attribute Resolution
Location: ListViewHolder.java:370–394
Issue: Theme attributes are resolved during every bind operation.
Impact: Repeated theme lookups and avoidable overhead.
Recommendation: Cache resolved theme attributes and reuse them during view binding.

Summary

Key improvements should focus on:

  • Eliminating O(n) lookups
  • Reducing object allocations
  • Avoiding repeated hash/string calculations
  • Improving RecyclerView recycling behavior

These changes should significantly improve scroll performance, update efficiency, and memory usage, especially for large datasets.


I'll do some tests and see if some of them work and are easy to test and verify.

Platforms

Android

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions