Theory
Forty events, one screen
FestConnect Mobile (your BCA305-02 app) showed a handful of events in a LinearLayout, one TextView each: fine for 5, absurd for this year's 40. Hard-coding 40 TextViews is not an option, and next year's list will differ anyway.
What the screen needs is a widget that takes a data list and manufactures rows on demand, scrolling included. Android's classic answer, and the syllabus's, is the ListView, and the interesting part is the middleman it employs.
Theory
The thali server
A ListView is a canteen counter with a fixed number of thalis (row views): only as many as fit on screen.
The adapter is the server standing between the kitchen (your data array) and the counter: for each position, it takes a thali, fills it with that item's food, and hands it over. Scroll, and the thali that slid off the top is wiped and REFILLED for the row entering below: nobody cooks 10000 plates for 10000 items.
Theory
Simple ListView, formally
Three pieces wire the plain version:
- the ListView in your layout XML
- your data: a String array or ArrayList
- an ArrayAdapter connecting them, given a built-in row layout:
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, events);
listView.setAdapter(adapter);
simple_list_item_1 is Android's stock one-TextView row. Taps arrive by position: setOnItemClickListener((parent, view, position, id) -> ...): position indexes your data array directly.
Practical
The event list, simple form
public class EventListActivity extends AppCompatActivity {
String[] events = { "Garba Night", "Coding Contest", "Robo Race" };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event_list);
ListView list = findViewById(R.id.eventList);
ArrayAdapter<String> adapter = new ArrayAdapter<>(
this, android.R.layout.simple_list_item_1, events);
list.setAdapter(adapter);
list.setOnItemClickListener((parent, view, position, id) ->
Toast.makeText(this, events[position] + " selected",
Toast.LENGTH_SHORT).show());
}
}
Theory
Custom ListView: your own row
The committee wants each row to show name, venue AND seats left: the stock one-liner row cannot. A custom ListView = 2 additions:
- a row layout XML you design (event_row.xml: two TextViews and an ImageView)
- a custom adapter: extend ArrayAdapter and override getView(position, convertView, parent): inflate your row layout, findViewById its pieces, fill them from the data at
position, return the row.
getView is the thali-filling moment: it runs once per VISIBLE row, and again each time a row scrolls into view.
Practical
The custom adapter's heart: getView with recycling
public class EventAdapter extends ArrayAdapter<Event> {
public EventAdapter(Context c, ArrayList<Event> events) {
super(c, 0, events);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) { // no recycled thali?
convertView = LayoutInflater.from(getContext())
.inflate(R.layout.event_row, parent, false);
}
Event e = getItem(position); // this row's data
TextView name = convertView.findViewById(R.id.rowName);
TextView seats = convertView.findViewById(R.id.rowSeats);
name.setText(e.name);
seats.setText(e.seatsLeft + " seats");
return convertView; // the filled row
}
}
Quiz
In getView, what is the convertView parameter, and why does Android pass it to you?
- The row the user last tapped, for highlighting
- A recycled row view scrolled off screen, offered for REUSE so you inflate only when it is null
- The parent ListView itself
- A copy of the layout XML as a View, freshly inflated every call
Show the answer
A recycled row view scrolled off screen, offered for REUSE so you inflate only when it is null
convertView is the wiped thali: a row object that slid off screen, handed back so you can refill it instead of inflating a new one: inflation (parsing XML into views) is expensive, and recycling is why a 10000-row list scrolls smoothly with only a dozen row objects alive. The canonical pattern is exactly the listing's: inflate if null, else reuse. Option D describes what your code would wastefully do WITHOUT the check: the classic laggy-list bug. Options A and C mislabel the parameter entirely: taps arrive via the click listener, and parent is a separate argument.
Think first
Simple or custom? Rule on 3 lists
Three FestConnect screens: (a) a plain list of department names for a filter, (b) the events list with name + venue + seats + a photo, (c) a list of rules, one sentence each. Decide simple ArrayAdapter or custom adapter for each, before tapping.
Show the answer
(a) and (c): simple ArrayAdapter with simple_list_item_1: one string per row is exactly its shape, and writing a custom adapter for it is ceremony without benefit. (b): custom adapter: multiple fields and an image per row need your own row layout and getView. The decision rule: one string per row = stock; anything richer = custom. Saying WHY (the row layout's shape drives the adapter choice) is what upgrades the answer from correct to full-marks.
Watch out
ListView traps
Inflating every call: skipping the convertView null-check works, then stutters on real data: THE performance bug examiners describe and ask you to spot.
Forgetting setAdapter: a ListView without an adapter is silently blank: no error, no rows.
notifyDataSetChanged: after changing the data list, call adapter.notifyDataSetChanged() or the screen keeps showing stale rows: the adapter does not watch your ArrayList; you must ring it.
Theory
The adapter idea outlives ListView
Hold the shape: data + row template + a function filling one row by position. Android's modern RecyclerView is this same idea with recycling made compulsory, and Unit 5's Flutter ListView.builder(itemCount, itemBuilder) is it again in Dart: itemBuilder IS getView with nicer clothes. Learn the middleman once and every list framework you ever meet is a dialect. Next lesson: the widgets that pick dates and show progress: DatePicker, TimePicker, ProgressBar.
Summary
Key takeaways
- ListView renders scrollable rows; an ADAPTER bridges data to rows.
- Simple form: ArrayAdapter with android.R.layout.simple_list_item_1 for one string per row.
- Custom form: your own row XML + an adapter overriding getView(position, convertView, parent).
- Recycle: inflate only when convertView is null, else refill it: the smooth-scroll secret.
- Row taps arrive with position via setOnItemClickListener; position indexes your data.
- Data changed? adapter.notifyDataSetChanged() or the screen stays stale.
- Memory hook: few thalis, one server, endless queue.