I’m working on an Android app that uses a RecyclerView with a custom Adapter and ViewHolder. The RecyclerView contains EditText views, and the properties of these views (such as text, color, padding, font size, etc.) are dynamically loaded via JNI from a native C++ layer.
The problem I’m encountering is the initial creation of the RecyclerView and how long it takes to populate and render the EditText views. The entire process takes around 100ms. I’m wondering if this is normal for a complex UI like this, or if there are ways to optimize the creation process.
Details:
RecyclerView Setup: The RecyclerView is populated with EditText items where each item’s properties are fetched from the native layer.
Performance Concern: The initial creation (setup, layout, and data population) takes ~100ms, and I'm wondering if there are optimizations I can apply to improve this time.
Code:
class MainActivity : AppCompatActivity() {
private lateinit var recyclerView: RecyclerView
private lateinit var adapter: EditTextAdapter
companion object {
init {
System.loadLibrary("recyclerviewtest")
}
external fun nativeGetItemCount(): Int
external fun nativeGetStringProperty(index: Int, propId: Int): String
external fun nativeGetIntProperty(index: Int, propId: Int): Int
external fun nativeGetFloatProperty(index: Int, propId: Int): Float
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val start = System.nanoTime()
recyclerView = RecyclerView(this).apply {
layoutManager = LinearLayoutManager(this@MainActivity)
}
adapter = EditTextAdapter(this)
recyclerView.adapter = adapter
val rootLayout = LinearLayout(this).apply {
orientation = LinearLayout.VERTICAL
addView(recyclerView, LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 1f))
}
setContentView(rootLayout)
// Initialize data and trigger first data fetch
adapter.setInitialData(nativeGetItemCount())
val durationMs = (System.nanoTime() - start) / 1_000_000.0
Log.d("Performance", "Create ALL duration (including layout): $durationMs ms")
}
}
class EditTextAdapter(private val context: Context) : RecyclerView.Adapter<EditTextViewHolder>() {
private val items = mutableListOf<ItemProps>()
fun setInitialData(count: Int) {
items.clear()
for (i in 0 until count) {
items.add(loadProps(i)) // Load data from JNI
}
notifyItemRangeInserted(0, items.size)
}
private fun loadProps(index: Int): ItemProps {
return ItemProps(
text = MainActivity.nativeGetStringProperty(index, 0),
textColor = MainActivity.nativeGetIntProperty(index, 1),
paddingTop = MainActivity.nativeGetIntProperty(index, 2),
paddingLeft = MainActivity.nativeGetIntProperty(index, 3),
fontSize = MainActivity.nativeGetFloatProperty(index, 4),
backgroundColor = MainActivity.nativeGetIntProperty(index, 5)
)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EditTextViewHolder {
return EditTextViewHolder(context)
}
override fun onBindViewHolder(holder: EditTextViewHolder, position: Int) {
holder.bind(items[position])
}
override fun getItemCount(): Int = items.size
}
Performance Observations:
- The initial creation of the RecyclerView (with all EditText views) takes around 100ms to complete.
- Data is fetched from JNI for each EditText item during the initial population of the RecyclerView.
Questions:
Is ~100ms for the initial creation and population of a RecyclerView with hundreds of EditText views considered normal?
What optimizations can be applied to speed up the initial setup?
Minimize marshalling of resources across the JNI layer