IT272 Mobile Application Development

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 + ImageView for each item).
  • Enable efficient scrolling via view recycling (only visible items are rendered).
  • Support user interactions (clicks, swipes) via item decorators or gesture listeners.
Transaction 1: Rs. 5000Transaction 2: Rs. 12001Transaction 3: Rs. 3002Transaction 4: Rs. 8003
eSewa transaction list (only 4 of 1000 items rendered at once via RecyclerView)
Transaction 1: Rs. 5000Transaction 2: Rs. 12001Transaction 3: Rs. 3002Transaction 4: Rs. 8003
eSewa transaction list as an array (only 4 of 1000 items rendered at once)

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)
Manual recycling (no ViewHolder)Automatic recyclingModern bindingEfficient (paginated)Legacy (full load)ListViewRecyclerViewViewHolderAdapterDatabase
Data flow comparison: ListView (legacy) vs. RecyclerView (modern) with ViewHolder optimization

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:

  1. Data Source: Array, database cursor, or API response (e.g., Daraz’s product list).
  2. UI Component: ListView, RecyclerView, or GridView.
View 3 (Laptop)View 2 (iPhone)View 1 (Recycled)TOP (Visible)
RecyclerView view recycling: View 1 (off-screen) is reused for View 3 (new position) to save memory

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"| C

Example: 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 Android
Class diagram of Android adapter patterns

1. 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.Adapter instead).

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 Cursor object 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.

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 Activity but can be added/removed dynamically.
  • Use Cases:
    • Multi-pane layouts (e.g., Gmail’s inbox + compose).
    • Reusable components (e.g., a ProfileFragment in multiple activities).

2. Fragment Lifecycle

Critical Methods:

  • onCreateView(): Inflates the fragment’s layout.
  • onActivityCreated(): Activity’s onCreate() 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.
Rider 3 (Active)Rider 2 (Waiting)Rider 1 (Completed)TOP (Visible)
Fragment back stack: Rider 1’s UI is destroyed when replaced by Rider 3’s fragment

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 ViewHolder class.

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 DiffUtil to 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

  1. eSewa Transaction Lists

    • Idea Used: RecyclerView with CursorAdapter.
    • How: Transactions are fetched from SQLite via a Cursor, bound to a RecyclerView with a custom ViewHolder. Scrolling recycles views to handle 1000+ transactions efficiently.
  2. Pathao Ride Queue

    • Idea Used: Fragment + RecyclerView.Adapter.
    • How: The "Upcoming Rides" screen is a Fragment containing a RecyclerView of ride requests. Each request is a ViewHolder with driver details, status, and a "Cancel" button.
  3. Daraz Product Grid

    • Idea Used: RecyclerView with StaggeredGridLayoutManager.
    • How: Products are displayed in a Pinterest-style grid (variable heights). The StaggeredGridLayoutManager handles the dynamic layout, while DiffUtil updates the grid smoothly when new products are added.
  4. Ncell Call Logs

    • Idea Used: ListView with CursorAdapter.
    • How: Call logs are stored in SQLite. The CursorAdapter binds each call (number, duration, date) to a ListView row. Swiping left/right uses ItemTouchHelper (built on RecyclerView).

Exam Tip

  1. Adapter Questions:

    • Expect code snippets where you must:
      • Implement onCreateViewHolder() and onBindViewHolder().
      • Explain the role of ViewHolder (avoid findViewById() in loops).
    • Common Pitfall: Forgetting to recycle views in onViewRecycled().
  2. 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 FragmentManager to switch between fragments.
  3. Performance:

    • Always mention view recycling and DiffUtil for dynamic lists.
    • Compare ListView vs. RecyclerView in terms of efficiency.
  4. Real-World Mapping:

    • Relate RecyclerView to eSewa transactions or Pathao rides.
    • For fragments, link to multi-tab apps (e.g., Facebook’s news feed + notifications).

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…