Skip to main content

Overview

The App Category module is a core pillar of the application’s organization logic. It identifies every installed app on the user’s device and assigns it a category (e.g., “Social”, “Games”, “Productivity”). To the user, this manifests as a clean, grouped list of apps where they can search, view categorization status, and manually override classifications if the automated system misses the mark.

Architecture & Data Flow

The module follows a strict pattern, leveraging to bridge the gap between persistent storage and the Compose UI.

Key Components

1. UI Layer (AppCategoryScreen)

A high-performance interface featuring:
  • Scroll-Aware Search: The search bar collapses/expands based on events to maximize screen real estate.
  • Expandable Grouping: Apps are grouped into “Cards” by category. These cards use AnimatedVisibility for smooth expansion and show a “cluster” of app icons when collapsed.
  • Manual Override: A CategorizeAppBottomSheet allows users to manually pick a category from a predefined list if the automated sync fails.

2. Logic Layer (AppCategoryViewModel)

The “Brain” of the module. It uses the combine operator to merge multiple sources:
  • Source 1: Categorized apps from the database.
  • Source 2: Raw app metadata (names, icons) from the system.
  • Source 3: User search queries and filter selections.

3. Data Layer (AppCategoryRepository)

The manages the complexity of synchronization. It coordinates between the local database and the remote REST API.

Operational Logic

Initialization & Sync

When the module starts, it doesn’t just wait for the user. It employs a multi-stage sync strategy:
  1. Metadata Scan: The AppMetadataRepository scans the device for installed apps and caches their icons to internal storage.
  2. Observer Pattern: A background observer watches for new app installations. When a new app is detected, it triggers an immediate “Targeted Sync”.
  3. Background Workers: The module uses to perform batch API requests (up to 100 apps at a time) to fetch categories without draining the battery or blocking the UI.

State Management

The UI handles four distinct states:
  • Loading: A shimmer/loading screen while the initial DB query completes.
  • Synced: The standard view showing categorized apps.
  • Pending: A banner appears if apps are currently in the “Pending” queue (waiting for API response).
  • Uncategorized: A specific “Error” section for apps that the API couldn’t identify, prompting user action.

Data Engineering & Transformation

Source Tables

  • app_metadata: Stores the “Source of Truth” for what is installed (Package Name, App Name, Version).
  • app_categories: Stores the classification data (Category Name, Sync Status, User Override Flag).

Transformation Pipeline

The ViewModel performs heavy lifting to ensure the UI remains responsive:
  1. Filtering: Removes apps that are marked as “Hidden” or “System Apps” (unless they have a launcher intent).
  2. Formatting: Uses CategoryUtil to normalize raw API strings (e.g., GAME_ACTION becomes “Games”, HEALTH_AND_FITNESS becomes “Health”).
  3. Grouping: Transforms a flat list of apps into a Map<String, List<App>> sorted alphabetically by category name.

Performance Optimization

  • Icon Caching: Icons are extracted once and saved as .png files in the app’s internal directory. This prevents the PackageManager from being a bottleneck during list scrolling.
  • Computation Offloading: All grouping and filtering logic is shifted to Dispatchers.Default using the flowOn operator to keep the Main Thread free for UI rendering.

Dependencies

  • Hilt: For of repositories into ViewModels.
  • Coil: For asynchronous loading of cached app icons.
  • Retrofit: For communicating with the Category API.
  • Timber: For structured logging of sync events and failures.
Last modified on January 22, 2026