Skip to content

Architecture Overview

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:

Legacy Architecture

Traditional Android Activities with AsyncTasks. Used in most core features like Replenishment, Picking, and Quality Control.

MVP Architecture

Modern Model-View-Presenter pattern. Used in newer modules like Cycle Count and Load & Move.

Why Hybrid?

  • Legacy code maintains existing functionality
  • MVP modules demonstrate modern patterns
  • Both coexist in the same app
  • Gradual migration to MVP over time

The app is organized into four main layers:

Components: Activities, Fragments, Adapters, Views

Legacy Modules:

  • ReplenishmentActivity.java - Login and entry point
  • AppMenu.java - Main navigation menu
  • MyRep.java - Replenishment (4,133 lines)
  • PickActivity.java - Picking operations
  • QualityControl.java - Quality control
  • BinesActivity.java - Bins management

MVP Modules:

  • CycleCountActivity.java - Cycle count main view
  • CycleCountDetailFragment.java - Cycle count detail view
  • LoadAndMoveActivity.java - Load & move main view
  • Multiple fragments for different workflows

Responsibilities:

  • Display UI to users
  • Handle user interactions
  • Show data from business logic
  • Navigate between screens

Components: Presenters, Interactors, Services

Legacy Approach:

  • Business logic in Activities
  • AsyncTasks handle background operations
  • Direct API calls from Activities

MVP Approach:

  • CycleCountPresenter - Handles cycle count logic
  • CycleCountInteractor - Business logic for cycle count
  • LoadMoveBinPresenter - Handles load & move logic
  • LoadMoveBinInteractor - Business logic for load & move

Responsibilities:

  • Process user actions
  • Validate data
  • Coordinate between view and data layers
  • Handle business rules

Components: API Clients, Database Helpers, Services

API Services:

  • ConnectToDataBaseServer*.java - Multiple API connection classes
  • CycleCountAPI.java - Cycle count API client
  • LoadMoveBinAPI.java - Load & move API client
  • CycleCountService.java - Retrofit service interface
  • LoadMoveBinService.java - Retrofit service interface

Database:

  • SQLite local database
  • ProjectClockDB.java - Database helper
  • LoadMoveBinDB.java - Database helper for MVP module
  • Direct SQLiteDatabase usage in legacy modules

Responsibilities:

  • Connect to Shipedge server
  • Store data locally
  • Manage data synchronization
  • Handle data persistence

Components: Shipedge APIs, Bluetooth, Camera, System Services

Services:

  • Shipedge warehouse server APIs
  • Bluetooth scanner (Datasource.java, MySocket.java)
  • Camera for barcode scanning
  • Android system services

Responsibilities:

  • Communicate with external systems
  • Handle hardware integration
  • Manage device features
  • Process external data

User Action
Activity (UI)
AsyncTask (Background)
ConnectToDataBaseServer* (API)
Shipedge Server
Response Processing
Update UI (Handler/Runnable)
SQLite Database (Local Storage)

Example: Replenishment (MyRep.java)

  1. User scans barcode
  2. Activity receives input
  3. AsyncTask sends to server
  4. Server validates and responds
  5. Activity updates UI
  6. Data saved to SQLite

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)

  1. User selects bin to count
  2. Fragment calls presenter method
  3. Presenter calls interactor
  4. Interactor calls API service
  5. Server responds
  6. EventBus sends event
  7. Presenter receives event
  8. Presenter updates view
  9. Data saved via database helper

Activities: Self-contained with UI and business logic

Pattern:

  • Activity contains UI code
  • AsyncTasks handle network operations
  • Direct database access
  • Handlers update UI from background threads

Example Files:

  • MyRep.java - Replenishment Activity
  • PickActivity.java - Picking Activity
  • QualityControl.java - Quality Control Activity

Strengths:

  • Simple and straightforward
  • Easy to understand for Android beginners
  • Direct control over operations
  • Works well for small features

Limitations:

  • Business logic mixed with UI code
  • Hard to test
  • Code duplication
  • Difficult to maintain as features grow

View: Displays UI and handles user input

  • CycleCountActivity.java - Main view
  • CycleCountDetailFragment.java - Detail view
  • Implements view interface

Presenter: Handles business logic and coordinates

  • CycleCountPresenterClass.java - Main presenter
  • CycleCountDetailPresenterClass.java - Detail presenter
  • Receives events from EventBus
  • Updates view based on results

Interactor: Contains business logic

  • CycleCountInteractorClass.java - Main interactor
  • CycleCountDetailInteractorClass.java - Detail interactor
  • Calls API services
  • Processes data

API Service: Handles server communication

  • CycleCountAPI.java - API client
  • CycleCountService.java - Retrofit interface
  • Sends requests to server
  • Returns responses via EventBus

cycleCountActivity:

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.java

loadAndMoveActivity:

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.java

MVP modules use EventBus for communication:

How It Works:

  1. Interactor calls API service
  2. API service sends request
  3. Server responds
  4. API service posts EventBus event
  5. Presenter subscribes to events
  6. Presenter receives event
  7. Presenter updates view

Example:

// In Presenter
@Subscribe
public void onEvent(CycleCountEvent event) {
if (event == CycleCountEvent.getCycleCountListRef) {
mView.showZeroBins(event.getData());
}
}

Java

Primary programming language. Most code is Java with some Kotlin support.

Android SDK

Native Android development. Minimum API 21, target API 34.

SQLite

Local database for offline storage and caching.

Retrofit

HTTP client for API communication in MVP modules.

EventBus

Event-driven communication in MVP modules.

RxJava

Reactive programming support (limited use).

Networking:

  • Retrofit 2.6.2 - REST API client
  • RxJava Adapter 2.5.0 - Reactive extensions
  • Apache HttpClient Legacy - Legacy HTTP support

UI:

  • AndroidX AppCompat - UI components
  • Material Design Components 1.2.1
  • CardView 1.0.0
  • DragListView 1.7.1 - Draggable lists

Database:

  • SQLite (native Android)
  • Room 2.2.5 (limited use)

Utilities:

  • EventBus 3.1.1 - Event communication
  • Glide 4.12.0 - Image loading

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/

MVP Pattern

Model-View-Presenter in newer modules. Separates concerns and improves testability.

Singleton

Datasource uses singleton pattern for Bluetooth scanner management.

Adapter

45+ adapters for ListViews. Standard Android adapter pattern.

Observer

EventBus implements observer pattern for MVP modules.

Factory

Implicit factory patterns in API service creation.

Repository

Partial repository pattern in MVP modules with database helpers.


Legacy Modules:

  • AsyncTask: Background network operations
  • Thread + Handler: Bluetooth operations and UI updates
  • Runnable: UI updates from background threads

MVP Modules:

  • Retrofit Callbacks: Network operations
  • EventBus: Thread-safe event communication
  • RxJava: Limited reactive programming

Example Legacy:

// AsyncTask for network call
ConnectToDataBaseServerLoginAsync login =
new ConnectToDataBaseServerLoginAsync(...);
login.execute("");

Example MVP:

// Retrofit with EventBus
CycleCountAPI api = new CycleCountAPI(...);
api.getZeroBins(params, callback);
// Response sent via EventBus

SQLite Databases:

  • androidShipedge - Main database
  • Settings table - Warehouse configuration
  • LogProject table - Time tracking
  • LogError table - Sync status
  • Multiple feature-specific tables

Database Access:

  • Direct SQLiteDatabase in legacy modules
  • Database helpers in MVP modules (LoadMoveBinDB.java)
  • No ORM framework (direct SQL)

Storage Strategy:

  • Local cache for offline work
  • Sync to server when online
  • Data persists between app sessions

Legacy Approach:

  • Custom HTTP client classes
  • ConnectToDataBaseServer*.java classes
  • AsyncTask for async operations
  • JSON parsing in Activities

MVP Approach:

  • Retrofit for HTTP client
  • Service interfaces (CycleCountService.java)
  • API classes (CycleCountAPI.java)
  • EventBus for responses

Server Endpoints:

  • Base URL: https://[warehouse].shipedge.com/android/
  • API v2: https://[warehouse].shipedge.com/apiv2/
  • Endpoints vary by feature

Intent-Based Navigation:

  • Activities navigate using Intents
  • Intent extras pass data
  • Launch modes control behavior

Example:

Intent intent = new Intent(this, PickActivity.class);
intent.putExtra("warehouse", warehouse);
startActivity(intent);

Launch Modes:

  • singleTop - Prevents multiple instances (used in MyRep.java)
  • Standard - Default behavior
  • Portrait only - All activities locked to portrait

Entry Point:

  • ReplenishmentActivity.java - Login and authentication

Main Navigation:

  • AppMenu.java - Main menu with feature list

Core Features:

  • MyRep.java - Replenishment (largest file, 4,133 lines)
  • PickActivity.java - Picking operations
  • QualityControl.java - Quality control
  • BinesActivity.java - Bins management
  • ReturnActivity.java - Returns processing
  • TimeTrack.java - Time tracking

Cycle Count:

  • Complete MVP implementation
  • Main and detail modules
  • Full separation of concerns

Load & Move:

  • Complete MVP implementation
  • Multiple sub-modules
  • Blocked bins management

Bluetooth:

  • Datasource.java - Scanner management
  • MySocket.java - Bluetooth socket handling

Background:

  • NotificationService.java - Background notifications

  • Total Java Files: ~229 files
  • Activities: 22 activities
  • Adapters: 45+ adapters
  • Layouts: 171 XML layouts
  • API Services: 50+ connection classes
  • MVP Modules: 2 complete modules
  • MyRep.java - 4,133 lines (Replenishment)
  • PickActivity.java - Large picking implementation
  • QualityControl.java - Quality control features

Follow MVP Pattern

New features should use MVP architecture. Follow cycleCountActivity as example.

Use EventBus

MVP modules should use EventBus for communication. Keeps components decoupled.

Separate Concerns

Keep UI, business logic, and data access separate. MVP enforces this.

Use Retrofit

New API calls should use Retrofit. More maintainable than custom HTTP clients.

Database Helpers

Use database helpers in MVP modules. Avoid direct SQLiteDatabase access.

Consistent Naming

Follow existing naming conventions. Activities end with Activity, Presenters with Presenter.


When to Migrate:

  • Adding major new features
  • Refactoring large Activities
  • Improving testability
  • Reducing code complexity

Migration Steps:

  1. Create MVP Structure

    Set up module directories: view, presenter, model, common.

  2. Extract Business Logic

    Move business logic from Activity to Interactor.

  3. Create Presenter

    Create presenter to coordinate between view and interactor.

  4. Implement API Service

    Create Retrofit service and API class.

  5. Set Up EventBus

    Configure events for communication.

  6. Update View

    Update Activity/Fragment to use presenter.

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