Launcher3 Modularization-Componentization
Source: Dev.to
Table of Contents
- 1. Background
- 2. Development Environment
- 3. Launcher3 Review
- 4. Structural Decomposition
- 5. What Can Be Done
- 6. How to Use
- 7. Features to be Improved
- 8. Others
1. Background
Smart cockpit desktop systems are typically customized based on the Android AOSP Launcher3 source code. However, Launcher3’s codebase is overly complex, leading to high customization costs. To reduce these costs, this project splits Launcher3 into several independent modules that can be customized individually.
In the context of the thriving Vibe Coding trend, this customization project might seem redundant—or even foolish. I share that sentiment. After importing Launcher3 into Cursor and providing specific requirements, Cursor couldn’t effectively reduce development difficulty or understand the overall project context or the logical context of specific functional points.
Thus, with the assistance of the programming tool TRAE, the initial version of this project was completed.
2. Development Environment
Hardware
- Allwinner H618 development board
- 2 GB DDR3 memory
- 16 GB eMMC storage
Software
- Android 12.0
Development Tools
- Android Studio Otter 2 Feature Drop | 2025.2.2
- Mac Pro Tahoe
- Gradle 8.13
- JVM‑openjdk version “17.0.17” (2025‑10‑21 LTS)
PaginationScrollViewDemo on GitHub
3. Launcher3 Review
3.1 UI Architecture


All desktop elements are aggregated in a single view, which makes tracking issues with a specific view type typically require excluding other types, including both UI and logic.
3.2 Data Architecture

Under the MVP architecture, the Model loads basic item‑element data and also obtains auxiliary data such as the icon cache. All data is ultimately passed back to the Launcher class or widget‑related views for processing.
4. Structural Decomposition
The initial idea was to split Launcher3 into several modules, each responsible for a specific function (e.g., application icons, widgets). However, during the actual splitting process, it became clear that Launcher3’s code structure is highly inter‑dependent. For example, both desktop icons and widgets rely on the DragLayer class. Placing them in a single module does not reduce overall complexity.
Consequently, the project was divided into the following modules:
| Module | Responsibility |
|---|---|
| item_foundation | Core data structures and logic for item elements (icons, text, etc.). Includes DragLayer, the basic view for dragging icons and widgets. |
| PaginationScrollView | Implementation of paginated scrolling views, handling page switching, position prediction, and related behaviors. |
| pop_exchange | Widget view generation, bottom widget list implementation, and related functions. |
| data_persistence | Storage and retrieval of application icons, widgets, and other persistent data. |
| router | Cross‑module method invocation. |
| utils | Common utility classes (logging, thread pools, etc.). |
Overall Logical Architecture

(If the image appears broken, verify the URL or replace it with the correct one.)
4.1 Functional Transformation
4.1.1 Data Persistence
In the original Launcher3, ContentProvider is relied upon for data processing. This remains unchanged here, but the original logic is discarded and reorganized. The data‑CRUD logic is abstracted and placed in a centralized location to avoid perceptual confusion.
4.1.2 Widget Trimming
Widgets involve data reading, preview view generation, drag exclusion, deletion, and other functions. Here, the core functions are extracted and are no longer processed together with desktop icons. For general cockpit desktop development, custom widgets are not of much concern, so they are removed.
4.1.3 Folders
The folder function is rarely used in the cockpit projects I’ve encountered so far, so it is not implemented for now.
4.1.4 Shortcuts
For shortcuts, application icons are used directly, specifying the application startup Activity.
4.1.5 Application Status
In the projects I’ve seen, systems have their own app stores and generally don’t interface with the native installer to distribute application status (installation, updates, uninstallation, etc.). This is discarded here; addition, update, and deletion can be achieved directly through the provided data‑operation classes.
4.1.6 Application Icons
In the original Launcher3, icons are cached through the IconCache DB. Here, they are stored in a single table for processing.
5. What Can Be Done
- Paginated scrolling view
- Widget list
These two functions cover ~80 % of the use‑case scenarios for cockpit desktops. They can be used as separate application lists (implementing left‑right pagination and drag‑to‑page‑switch) or as widget lists (implementing widget editing or drag‑to‑add/delete widgets).
With the current project, developers only need to focus on data assembly and UI implementation, without worrying about the data layer.
6. How to Use
In the home page, you can set it up as follows:
// Define the number of rows and columns for icons
final int row = 3;
final int column = 5;
// Get screen resolution
DisplayMetrics displayMetrics = new DisplayMetrics();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
getWindowManager().getDefaultDisplay().getRealMetrics(displayMetrics);
} else {
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
}
// Get screen width and height, then divide by rows and columns respectively
int screenWidth = displayMetrics.widthPixels;
int screenHeight = displayMetrics.heightPixels;
LogUtils.d(TAG, "device screen size: " + screenWidth + "x" + screenHeight);
PaginationProfile paginationProfile = new PaginationProfile.Builder()
.setHeightPx(screenHeight) // view height = screen height
.setWidthPx(screenWidth) // view width = screen width
.setCellHeightPx(360) // icon height = 360 px (view height / rows)
.setCellWidthPx(384) // icon width = 384 px (view width / columns)
.setNumColumns(column) // number of columns = 5
.setNumRows(row) // number of rows = 3
.setIconDrawablePaddingPx(2) // padding between icon and text
.setDefaultPageSpacingPx(2) // default page spacing
.setEdgeMarginPx(2) // edge margin
.setIconSizePx(108) // icon size
.setIconTextSizePx(16) // text size
.setCellTextColor(getColor(R.color.black)) // text color
.setWorkspacePadding(new Rect(0, 0, 0, 0)) // workspace padding
.setSaveDataInDb(true) // persist data in DB
.build();
setContentView(R.layout.activity_main);
// Get the paginated scroll view instance
PaginationScrollView paginationScrollView = findViewById(R.id.pagination_scroll_view);
// Initialize the widget‑list popup view (comment out if not needed)
PopUpExchangeView.getInstance().init(this);
// Determine whether data has been saved to DB
SharedPreferences sp = getSharedPreferences("PaginationScrollView", MODE_PRIVATE);
boolean dataSaved = sp.getBoolean("data_saved", false);
if (dataSaved) {
paginationScrollView.bindItems(); // load from DB
} else {
paginationScrollView.bindItems(fruits); // bind sample data
sp.edit().putBoolean("data_saved", true).apply(); // remember that we saved it
}
// Set click listener for the widget‑list popup button
FloatingActionButton popupButton = findViewById(R.id.show_pop_window);
popupButton.setOnClickListener(v -> {
PopUpExchangeView.getInstance().showOrClosePopWindow();
});
Enter fullscreen mode
Exit fullscreen mode
7. Features to be Improved
- Deletion and update of item and widget data
8. Others
- Add data tracking based on item operation records for analyzing user behavior.
- Add AI recommendation features based on behavior data.
- Add AI smart recommendation features based on geofencing.
- Ensure data compliance.
