Legacy Architecture
Traditional Android Activities with AsyncTasks. Used in most core features like Replenishment, Picking, and Quality Control.
Shipedge Warehouse Pro uses a hybrid architecture that combines traditional Android patterns with modern MVP (Model-View-Presenter) architecture. Understanding the architecture helps developers navigate the codebase, understand data flow, and contribute effectively.
The app has evolved over time, resulting in a mix of legacy Activities and newer MVP modules. This overview explains both approaches and how they work together.
The app uses two architectural patterns:
Traditional Android Activities with AsyncTasks. Used in most core features like Replenishment, Picking, and Quality Control.
Modern Model-View-Presenter pattern. Used in newer modules like Cycle Count and Load & Move.
Why Hybrid?
The app is organized into four main layers:
Components: Activities, Fragments, Adapters, Views
Legacy Modules:
ReplenishmentActivity.java - Login and entry pointAppMenu.java - Main navigation menuMyRep.java - Replenishment (4,133 lines)PickActivity.java - Picking operationsQualityControl.java - Quality controlBinesActivity.java - Bins managementMVP Modules:
CycleCountActivity.java - Cycle count main viewCycleCountDetailFragment.java - Cycle count detail viewLoadAndMoveActivity.java - Load & move main viewResponsibilities:
Components: Presenters, Interactors, Services
Legacy Approach:
MVP Approach:
CycleCountPresenter - Handles cycle count logicCycleCountInteractor - Business logic for cycle countLoadMoveBinPresenter - Handles load & move logicLoadMoveBinInteractor - Business logic for load & moveResponsibilities:
Components: API Clients, Database Helpers, Services
API Services:
ConnectToDataBaseServer*.java - Multiple API connection classesCycleCountAPI.java - Cycle count API clientLoadMoveBinAPI.java - Load & move API clientCycleCountService.java - Retrofit service interfaceLoadMoveBinService.java - Retrofit service interfaceDatabase:
ProjectClockDB.java - Database helperLoadMoveBinDB.java - Database helper for MVP moduleResponsibilities:
Components: Shipedge APIs, Bluetooth, Camera, System Services
Services:
Datasource.java, MySocket.java)Responsibilities:
User Action ↓Activity (UI) ↓AsyncTask (Background) ↓ConnectToDataBaseServer* (API) ↓Shipedge Server ↓Response Processing ↓Update UI (Handler/Runnable) ↓SQLite Database (Local Storage)Example: Replenishment (MyRep.java)
User Action ↓View (Fragment/Activity) ↓Presenter ↓Interactor ↓API Service (Retrofit) ↓Shipedge Server ↓EventBus (Response) ↓Presenter Updates View ↓Database Helper (Local Storage)Example: Cycle Count (cycleCountActivity)
Activities: Self-contained with UI and business logic
Pattern:
Example Files:
MyRep.java - Replenishment ActivityPickActivity.java - Picking ActivityQualityControl.java - Quality Control ActivityStrengths:
Limitations:
View: Displays UI and handles user input
CycleCountActivity.java - Main viewCycleCountDetailFragment.java - Detail viewPresenter: Handles business logic and coordinates
CycleCountPresenterClass.java - Main presenterCycleCountDetailPresenterClass.java - Detail presenterInteractor: Contains business logic
CycleCountInteractorClass.java - Main interactorCycleCountDetailInteractorClass.java - Detail interactorAPI Service: Handles server communication
CycleCountAPI.java - API clientCycleCountService.java - Retrofit interfacecycleCountActivity:
cycleCountActivity/├── mainModule/│ ├── view/│ │ ├── CycleCountActivity.java│ │ └── CycleCountView.java (interface)│ ├── CycleCountPresenter.java (interface)│ ├── CycleCountPresenterClass.java│ ├── model/│ │ ├── CycleCountInteractor.java (interface)│ │ └── CycleCountInteractorClass.java│ └── events/│ └── CycleCountEvent.java├── detailModule/│ └── [Similar structure]├── common/│ ├── dataAccess/│ │ ├── CycleCountAPI.java│ │ └── CycleCountService.java│ └── params/│ └── GetCycleCountParams.java└── pojo/ └── CycleCountPojo.javaloadAndMoveActivity:
loadAndMoveActivity/├── mainModule/│ └── view/│ └── LoadAndMoveActivity.java├── blockedBinModule/│ ├── LoadMoveBinPresenter.java│ ├── LoadMoveBinPresenterClass.java│ ├── model/│ │ └── LoadMoveBinInteractorClass.java│ └── view/│ └── LoadMoveBlockedBinFragment.java├── putAwayModule/│ └── [Similar structure]└── common/ ├── dataAccess/ │ ├── LoadMoveBinAPI.java │ ├── LoadMoveBinService.java │ └── LoadMoveBinDB.java └── params/ └── BinBlockedParams.javaMVP modules use EventBus for communication:
How It Works:
Example:
// In Presenter@Subscribepublic void onEvent(CycleCountEvent event) { if (event == CycleCountEvent.getCycleCountListRef) { mView.showZeroBins(event.getData()); }}Primary programming language. Most code is Java with some Kotlin support.
Native Android development. Minimum API 21, target API 34.
Local database for offline storage and caching.
HTTP client for API communication in MVP modules.
Event-driven communication in MVP modules.
Reactive programming support (limited use).
Networking:
UI:
Database:
Utilities:
pro/src/shipedge/rep/├── [Legacy Activities]│ ├── ReplenishmentActivity.java│ ├── AppMenu.java│ ├── MyRep.java│ ├── PickActivity.java│ └── [Other Activities...]│├── [MVP Modules]│ ├── cycleCountActivity/│ │ ├── mainModule/│ │ ├── detailModule/│ │ ├── common/│ │ └── pojo/│ └── loadAndMoveActivity/│ ├── mainModule/│ ├── blockedBinModule/│ ├── putAwayModule/│ └── common/│├── [API Services]│ ├── ConnectToDataBaseServer*.java│ ├── ConnecToDataBaServer*.java│ └── newConnectToDataBaseServer.java│├── [Data Models]│ ├── Order.java│ ├── Product.java│ ├── Bin.java│ ├── Users.java│ └── [Other models...]│├── [Adapters]│ ├── MyAdapter*.java (45+ adapters)│ └── ItemAdapter.java│└── [Services & Utilities] ├── Datasource.java (Bluetooth) ├── MySocket.java (Bluetooth) ├── NotificationService.java └── utils/Model-View-Presenter in newer modules. Separates concerns and improves testability.
Datasource uses singleton pattern for Bluetooth scanner management.
45+ adapters for ListViews. Standard Android adapter pattern.
EventBus implements observer pattern for MVP modules.
Implicit factory patterns in API service creation.
Partial repository pattern in MVP modules with database helpers.
Legacy Modules:
MVP Modules:
Example Legacy:
// AsyncTask for network callConnectToDataBaseServerLoginAsync login = new ConnectToDataBaseServerLoginAsync(...);login.execute("");Example MVP:
// Retrofit with EventBusCycleCountAPI api = new CycleCountAPI(...);api.getZeroBins(params, callback);// Response sent via EventBusSQLite Databases:
androidShipedge - Main databaseDatabase Access:
LoadMoveBinDB.java)Storage Strategy:
Legacy Approach:
ConnectToDataBaseServer*.java classesMVP Approach:
CycleCountService.java)CycleCountAPI.java)Server Endpoints:
https://[warehouse].shipedge.com/android/https://[warehouse].shipedge.com/apiv2/Intent-Based Navigation:
Example:
Intent intent = new Intent(this, PickActivity.class);intent.putExtra("warehouse", warehouse);startActivity(intent);Launch Modes:
singleTop - Prevents multiple instances (used in MyRep.java)Entry Point:
ReplenishmentActivity.java - Login and authenticationMain Navigation:
AppMenu.java - Main menu with feature listCore Features:
MyRep.java - Replenishment (largest file, 4,133 lines)PickActivity.java - Picking operationsQualityControl.java - Quality controlBinesActivity.java - Bins managementReturnActivity.java - Returns processingTimeTrack.java - Time trackingCycle Count:
Load & Move:
Bluetooth:
Datasource.java - Scanner managementMySocket.java - Bluetooth socket handlingBackground:
NotificationService.java - Background notificationsMyRep.java - 4,133 lines (Replenishment)PickActivity.java - Large picking implementationQualityControl.java - Quality control featuresNew features should use MVP architecture. Follow cycleCountActivity as example.
MVP modules should use EventBus for communication. Keeps components decoupled.
Keep UI, business logic, and data access separate. MVP enforces this.
New API calls should use Retrofit. More maintainable than custom HTTP clients.
Use database helpers in MVP modules. Avoid direct SQLiteDatabase access.
Follow existing naming conventions. Activities end with Activity, Presenters with Presenter.
When to Migrate:
Migration Steps:
Create MVP Structure
Set up module directories: view, presenter, model, common.
Extract Business Logic
Move business logic from Activity to Interactor.
Create Presenter
Create presenter to coordinate between view and interactor.
Implement API Service
Create Retrofit service and API class.
Set Up EventBus
Configure events for communication.
Update View
Update Activity/Fragment to use presenter.
Test Thoroughly
Test all functionality before removing legacy code.
Next Steps:
Understanding Features:
Shipedge Warehouse Pro uses a hybrid architecture:
✅ Legacy Architecture - Traditional Activities with AsyncTasks for most features
✅ MVP Architecture - Modern Model-View-Presenter for newer modules
✅ Four Layers - Presentation, Business Logic, Data Access, External Services
✅ EventBus - Event-driven communication in MVP modules
✅ Retrofit - Modern HTTP client for MVP modules
✅ SQLite - Local database for offline storage
✅ Gradual Migration - Moving from legacy to MVP over time
Understanding both architectures helps navigate the codebase effectively. New features should follow MVP patterns, while maintaining compatibility with legacy code.