Mobile Application DevelopmentUnit 512 min read
Lists, Adapters, Fragments: Dynamic UI and Data Handling
Unit 5 of Mobile Application Development covers dynamic lists in Android (RecyclerView, ListView), adapter patterns for data binding, and fragment-based UI modularity, with real-world examples from eSewa’s transaction lists and Pathao’s ride queues.
TAKEAWAYS:
- Adapters bridge data sources (arrays, databases) to UI components (lists, grids) by converting data into views.
- RecyclerView is Android’s modern list/grid container, optimized for performance with view recycling.
- Fragments enable modular UI components (e.g., tabs, dialogs) that can be reused across activities.
- ViewHolder pattern caches views in RecyclerView to avoid costly
findViewById()calls during scrolling. - Adapter types (ArrayAdapter, CursorAdapter, RecyclerView.Adapter) differ in data source and efficiency.
- Fragment lifecycle must be managed carefully to avoid memory leaks or crashes.
Core Concepts: Lists and Adapters
1. Why Lists?
Lists are the backbone of mobile UIs for displaying dynamic data (e.g., chat messages, eSewa transactions, Daraz orders). They:
- Reduce layout complexity by reusing a single template (e.g., a
TextView+ImageViewfor each item). - Enable efficient scrolling via view recycling (only visible items are rendered).
- Support user interactions (clicks, swipes) via item decorators or gesture listeners.
Real-World Example: eSewa Transaction History
eSewa’s app shows a scrollable list of transactions. Each item is a TextView for amount + date, bound to a database via an adapter. When you scroll, only 5–10 items are rendered at once, not all 1000 transactions.
2. ListView vs. RecyclerView
| Feature | ListView | RecyclerView |
|---|---|---|
| View Recycling | Manual (via convertView) |
Automatic (via ViewHolder) |
| Layout Flexibility | Linear only | Linear, Grid, StaggeredGrid |
| Performance | Slower for large datasets | Optimized for smooth scrolling |
| API Level | Deprecated (use RecyclerView) | Modern (API 21+) |
| Use Case | Legacy apps | All new apps (e.g., WhatsApp messages) |
Key Idea: RecyclerView is the standard for modern Android apps. ListView is obsolete but may appear in legacy code.
3. How Adapters Work
An adapter acts as a bridge between:
- Data Source: Array, database cursor, or API response (e.g., Daraz’s product list).
- UI Component:
ListView,RecyclerView, orGridView.
Adapter Lifecycle
flowchart TD
A["Adapter Created"] --> B["onCreateViewHolder()\n(Inflate layout XML)"]
B --> C["onBindViewHolder()\n(Bind data to views)"]
C --> D["onViewRecycled()\n(Clean up views)"]
D -->|"Scroll"| CExample: Binding Data to a RecyclerView
// 1. Define a ViewHolder
public class ProductViewHolder extends RecyclerView.ViewHolder {
TextView txtName, txtPrice;
public ProductViewHolder(View itemView) {
super(itemView);
txtName = itemView.findViewById(R.id.product_name);
txtPrice = itemView.findViewById(R.id.product_price);
}
}
// 2. Create Adapter
public class ProductAdapter extends RecyclerView.Adapter<ProductViewHolder> {
List<Product> products;
@Override
public ProductViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_product, parent, false);
return new ProductViewHolder(view);
}
@Override
public void onBindViewHolder(ProductViewHolder holder, int position) {
Product p = products.get(position);
holder.txtName.setText(p.name);
holder.txtPrice.setText("Rs. " + p.price);
}
@Override
public int getItemCount() { return products.size(); }
}
Trace: Adapter in Action (Daraz Order List)
Assume products = [{"name": "iPhone", "price": 50000}, {"name": "Laptop", "price": 80000}].
| Step | onCreateViewHolder() |
onBindViewHolder() |
ViewHolder State |
|---|---|---|---|
| Scroll to top | Inflates item_product |
Binds "iPhone" | txtName="iPhone", txtPrice="50000" |
| Scroll down | Reuses recycled view | Binds "Laptop" | txtName="Laptop", txtPrice="80000" |
| Scroll back up | Reuses "iPhone" view | Rebinds "iPhone" | (No new inflation!) |
Visual: RecyclerView View Recycling
Advanced: Adapter Patterns
classDiagram
class ArrayAdapter {
+bindView()
-convertView()
}
class CursorAdapter {
+swapCursor()
+bindView()
}
class RecyclerView~Adapter~ {
+onCreateViewHolder()
+onBindViewHolder()
+onViewRecycled()
}
ArrayAdapter -->|Extends| Adapter
CursorAdapter -->|Extends| Adapter
RecyclerView~Adapter~ -->|Extends| Adapter
Adapter : +getView()
Adapter : +getItemCount()
Adapter : -dataSource
caption Adapter hierarchy in AndroidClass diagram of Android adapter patterns1. ArrayAdapter
- Simplest adapter for arrays/lists (e.g.,
ArrayList<String>). - Pros: Easy to use, built-in for basic lists.
- Cons: No view recycling (use
RecyclerView.Adapterinstead).
Example: WhatsApp Chat Messages
ArrayAdapter<String> adapter = new ArrayAdapter<>(
this, android.R.layout.simple_list_item_1, messages);
listView.setAdapter(adapter);
2. CursorAdapter
- Binds data from a SQLite database cursor (e.g., Ncell’s call logs).
- Pros: Efficient for large datasets (loads data on demand).
- Cons: Requires
Cursorobject management.
Example: Ncell Call Logs
CursorAdapter adapter = new SimpleCursorAdapter(
this, R.layout.item_call, cursor,
new String[]{"number", "date"}, new int[]{R.id.call_number, R.id.call_date});
listView.setAdapter(adapter);
3. RecyclerView.Adapter
- Modern standard for lists/grids.
- Key Features:
- ViewHolder: Caches views to avoid
findViewById()overhead. - DiffUtil: Computes minimal updates for dynamic data (e.g., live chat).
- ItemAnimator: Smooth animations for add/remove operations.
- ViewHolder: Caches views to avoid
Visual: ViewHolder in RecyclerView
Fragments: Modular UI Components
1. What Are Fragments?
- Reusable UI modules (e.g., a settings tab, a map fragment).
- Lifetime: Tied to an
Activitybut can be added/removed dynamically. - Use Cases:
- Multi-pane layouts (e.g., Gmail’s inbox + compose).
- Reusable components (e.g., a
ProfileFragmentin multiple activities).
2. Fragment Lifecycle
Critical Methods:
onCreateView(): Inflates the fragment’s layout.onActivityCreated(): Activity’sonCreate()completes.onDestroyView(): Clean up views (avoid memory leaks).
3. Real-World Example: Pathao Ride Queue
Pathao’s app uses fragments to switch between:
MapFragment: Shows real-time driver locations.OrderFragment: Displays pending ride requests.ProfileFragment: User details.
Code: Adding a Fragment
// In Activity
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, new MapFragment());
transaction.addToBackStack(null);
transaction.commit();
Visual: Fragment Transaction
Performance Optimization
1. ViewHolder Pattern
- Problem: Without
ViewHolder,findViewById()is called for every item during scrolling (slow!). - Solution: Cache views in a
ViewHolderclass.
Before (Slow)
// Inside onBindViewHolder (inefficient)
TextView txt = (TextView) convertView.findViewById(R.id.txt_name);
After (Optimized)
// ViewHolder caches views
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView txtName;
public MyViewHolder(View itemView) {
super(itemView);
txtName = itemView.findViewById(R.id.txt_name); // Called ONCE per item
}
}
2. DiffUtil for Dynamic Data
- Problem: If data changes (e.g., live chat messages), RecyclerView rebuilds all views.
- Solution: Use
DiffUtilto compute only changed items.
Example: WhatsApp Live Updates
DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() {
@Override public int getOldListSize() { return oldMessages.size(); }
@Override public int getNewListSize() { return newMessages.size(); }
@Override public boolean areItemsTheSame(int oldPos, int newPos) {
return oldMessages.get(oldPos).id == newMessages.get(newPos).id;
}
@Override public boolean areContentsTheSame(int oldPos, int newPos) {
return oldMessages.get(oldPos).text.equals(newMessages.get(newPos).text);
}
});
result.dispatchUpdatesTo(adapter);
In the Real World
eSewa Transaction Lists
- Idea Used:
RecyclerViewwithCursorAdapter. - How: Transactions are fetched from SQLite via a
Cursor, bound to aRecyclerViewwith a customViewHolder. Scrolling recycles views to handle 1000+ transactions efficiently.
- Idea Used:
Pathao Ride Queue
- Idea Used:
Fragment+RecyclerView.Adapter. - How: The "Upcoming Rides" screen is a
Fragmentcontaining aRecyclerViewof ride requests. Each request is aViewHolderwith driver details, status, and a "Cancel" button.
- Idea Used:
Daraz Product Grid
- Idea Used:
RecyclerViewwithStaggeredGridLayoutManager. - How: Products are displayed in a Pinterest-style grid (variable heights). The
StaggeredGridLayoutManagerhandles the dynamic layout, whileDiffUtilupdates the grid smoothly when new products are added.
- Idea Used:
Ncell Call Logs
- Idea Used:
ListViewwithCursorAdapter. - How: Call logs are stored in SQLite. The
CursorAdapterbinds each call (number, duration, date) to aListViewrow. Swiping left/right usesItemTouchHelper(built onRecyclerView).
- Idea Used:
Exam Tip
Adapter Questions:
- Expect code snippets where you must:
- Implement
onCreateViewHolder()andonBindViewHolder(). - Explain the role of
ViewHolder(avoidfindViewById()in loops).
- Implement
- Common Pitfall: Forgetting to recycle views in
onViewRecycled().
- Expect code snippets where you must:
Fragment Questions:
- Diagram-Based: Draw the lifecycle of a fragment (e.g.,
onCreateView→onActivityCreated). - Scenario-Based: Given a multi-pane layout (e.g., a news app with articles + details), explain how to use
FragmentManagerto switch between fragments.
- Diagram-Based: Draw the lifecycle of a fragment (e.g.,
Performance:
- Always mention view recycling and DiffUtil for dynamic lists.
- Compare
ListViewvs.RecyclerViewin terms of efficiency.
Real-World Mapping:
- Relate
RecyclerViewto eSewa transactions or Pathao rides. - For fragments, link to multi-tab apps (e.g., Facebook’s news feed + notifications).
- Relate
Pro Tip: For practicals, implement a RecyclerView with:
- A custom
ViewHolder. - Click listeners on items (e.g., "View Details").
- DiffUtil for updates (e.g., a live counter).
Based on the TU BIM syllabus for Mobile Application Development (IT272), unit 5.
Discussion
Loading…