Views, layouts and RecyclerView cheat sheet
The 8 Views, layouts and RecyclerView interview answers in 30 seconds each, plus quick facts. Printable, free.
One page per topic: print it or save it as PDF from your browser's print menu. Practise these questions
Rules of thumb
- invalidate for appearance, requestLayout for size.
- Never allocate in onDraw.
- ListAdapter + DiffUtil, and always submit a new list.
- dp for sizes, sp for text.
- Layout by window size class, not by 'is tablet'.
How a View is measured, laid out and drawn
Each frame that needs it runs three passes from the root. Measure: parents pass MeasureSpec constraints down and each view calls setMeasuredDimension. Layout: parents position children with layout(). Draw: each view draws itself in onDraw, then its children. requestLayout() reruns measure and layout; invalidate() only redraws.
ConstraintLayout
ConstraintLayout positions views with constraints to the parent, siblings, guidelines or barriers, so complex screens stay flat instead of nested. Chains distribute a group of views along an axis (spread, spread inside, packed), guidelines give fixed or percentage anchors, and barriers move with the largest of several views. A flat tree means fewer measure passes.
RecyclerView, ListAdapter and DiffUtil
RecyclerView creates only enough ViewHolders to fill the screen plus a few, and rebinds them with new data as you scroll. ListAdapter with a DiffUtil.ItemCallback compares the old and new list on a background thread and dispatches exact insert, remove, move and change events, so only affected rows rebind and animations work. notifyDataSetChanged() rebinds everything and kills animations.
data class Item(val id: Long, val title: String, val favourite: Boolean)
object ItemDiff : DiffUtil.ItemCallback<Item>() {
override fun areItemsTheSame(old: Item, new: Item) = old.id == new.id
override fun areContentsTheSame(old: Item, new: Item) = old == new
}
class ItemAdapter : ListAdapter<Item, ItemAdapter.Holder>(ItemDiff) {
class Holder(val text: TextView) : RecyclerView.ViewHolder(text)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = Holder(TextView(parent.context))
override fun onBindViewHolder(holder: Holder, position: Int) {
holder.text.text = getItem(position).title
}
}Writing a custom View
Extend View with the @JvmOverloads three-argument constructor, read custom attributes with context.withStyledAttributes, override onMeasure to honour the MeasureSpec, and draw in onDraw with Paint objects created once. Call invalidate() when appearance changes and requestLayout() only when size changes. Add accessibility info for anything interactive.
Resources and qualifiers
Resources live in folders with qualifiers like values-de, layout-w600dp or drawable-night. At runtime, Android picks the best match for the current configuration: language, screen width, density, night mode and more. Use dp for sizes, which scale with density, and sp for text, which also scales with the user's font size setting.
View Binding vs findViewById and Data Binding
View Binding generates a class per layout with a typed, non-null field for each view with an ID, so there's no casting and no wrong-ID crashes. It has no runtime cost beyond inflation. Data Binding adds expressions in XML and observation, at the price of build time and logic in layouts. For View-based screens, View Binding is the usual choice; new UI is mostly Compose.
Touch event dispatch
A touch goes down from the Activity through dispatchTouchEvent on each ViewGroup. A parent can steal the gesture by returning true from onInterceptTouchEvent, and then children get ACTION_CANCEL. If not intercepted, the target child's onTouchEvent handles it; if it returns false for ACTION_DOWN, the event bubbles back up to its parents and that view gets no more events in that gesture.
Large screens and window size classes
Design for the available window, not the device. Window size classes (compact, medium, expanded) from currentWindowAdaptiveInfo() drive layout choices such as a bottom bar on phones and a navigation rail or list-detail on wider windows. Handle resizing without losing state, support both orientations, and don't lock to portrait: Android 16 ignores orientation and resizability restrictions on large screens.
Quick facts
- dp
- 1 dp is one pixel on a 160 dpi screen; Android scales it for other densities.
- ViewStub
- ViewStub inflates its layout only when made visible or inflated, saving work for rarely shown views.
- ViewPager2
- ViewPager2 is built on RecyclerView and uses FragmentStateAdapter for Fragment pages.
- Touch target
- Material guidance asks for touch targets of at least 48 × 48 dp.