Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

edvardFH/FormulaFan

Repository files navigation

FormulaFan Android

Android Java Retrofit Gradle

Android Java app for F1 fans: MVVM architecture, JWT authentication, post CRUD, admin moderation panel, geolocation, and race data from an external XML API.

Mobile front-end of the FormulaFan project. See also FormulaFan Backend for the Spring Boot REST API that powers this app.


Architecture Overview

flowchart TD
 subgraph PRESENTATION["PRESENTATION"]
 style PRESENTATION fill:#dbeafe,stroke:#3b82f6
 A["Activities\n(Login · Profile · CreatePost · EditPost)"]
 F["Fragments\n(Home · Feed · UserPosts · Race · Location)"]
 VM["ViewModels\n(RaceViewModel · CameraViewModel · LocationViewModel)"]
 end
 subgraph DATA["DATA"]
 style DATA fill:#dcfce7,stroke:#22c55e
 REPO["UserRepository\n(SharedPreferences + Gson)"]
 AC["ApiClient\n(Retrofit + AuthorizationInterceptor)"]
 SVC["Services\n(Auth · Post · Moderation · Profile · GrandPrix)"]
 end
 subgraph REMOTE["REMOTE / PERSISTENCE"]
 style REMOTE fill:#fef9c3,stroke:#eab308
 DB["SQLite + SharedPreferences"]
 BE["FormulaFan Backend :8080"]
 F1["F1 XML API"]
 end
 A & F --> VM
 A & F --> REPO
 REPO --> DB
 VM --> AC
 A & F --> AC
 AC --> SVC
 SVC --> BE
 VM --> F1
Loading

Layers

Layer Package Responsibilities
PRESENTATION ui/ Activities, Fragments, ViewModels, Adapters. View Binding throughout.
DATA / NETWORK data/api/ Retrofit service interfaces per domain, ApiClient, OkHttp interceptor
REPOSITORY data/repository/ UserRepository: single source of truth for auth state (token + User)
MODELS data/ DTOs: PostRequest/Response, Auth, ModerationRequest/Response, ProfileStat

Navigation: 5-tab bottom nav via NavController / mobile_navigation.xml. Screens requiring full Activity lifecycle (login, post creation/editing, profile) are launched via Intent.


Architecture Decisions

JWT injected via OkHttp Interceptor

Context. Every request to the FormulaFan backend requires a Bearer token. Repeating the injection manually across 5 Retrofit service interfaces would be fragile and duplicated.

Decision. ApiClient.AuthorizationInterceptor reads the token from UserRepository and automatically injects it into every request through the OkHttp chain.

Consequence. Zero Bearer header duplication across Services. Any change to the authentication strategy is isolated to ApiClient.


Dual data sources: REST backend + external F1 XML API

Context. F1 race data (schedule, results) comes from a third-party XML API, not from the FormulaFan backend.

Decision. HttpConnectAPI + F1ApiXmlParser consume the XML API independently from the Retrofit REST interfaces.

Consequence. RaceViewModel orchestrates two heterogeneous sources. The FormulaFan backend stays focused on social logic (posts, users, moderation).


Role-based UI in HomeFragment

Context. Admins need access to a moderation panel. Regular users see a different home screen.

Decision. HomeFragment checks user.role == "ADMIN" and renders either the hidden-posts list via ModerationService, or the default view.

Consequence. A single Fragment handles two distinct user experiences. Adding a new role requires a targeted change in HomeFragment.isAdminUser().


Hybrid local persistence

Context. Two types of local data with distinct needs: authentication state (small, structured, must survive restarts) and photo file paths (a list that benefits from SQL queries).

Decision. UserRepository uses SharedPreferences + Gson for the token and User object. FormulaFanDatabaseHelper (SQLite) stores camera photo paths.

Consequence. Each mechanism is sized for its use case. No oversized ORM for straightforward mobile persistence.


Mixed ViewModel strategy: LiveData vs. direct Retrofit callbacks

Context. Some Fragments (RaceFragment, LocationFragment) manage rich UI state and complex lifecycles. Others (FeedFragment, HomeFragment) make simple one-shot Retrofit calls.

Decision. Fragments with complex state use ViewModel + LiveData. Simpler Fragments call Retrofit directly via Callback.

Consequence. Less boilerplate for simple cases. New code should prefer ViewModel + LiveData to ensure long-term consistency.


Getting Started

Prerequisites:

  • Android Studio Hedgehog+ (AGP 8.x)
  • JDK 17+
  • Android emulator API 30+ or a physical device

Backend required: start FormulaFan Backend on localhost:8080 before launching the app. The emulator reaches the host via 10.0.2.2 (configured in BuildConfig.BASE_URL).

git clone <repo>
cd FormulaFan

Open in Android Studio and hit Run (Shift+F10), or from the command line:

./gradlew assembleDebug
adb install app/build/outputs/apk/debug/app-debug.apk

Tech Stack

Concern Technology
Language Java (Android source/target compat: 1.8)
Platform Android min SDK 30 / compile SDK 34
Build Gradle (Kotlin DSL)
HTTP Retrofit 2.9.0 + OkHttp
Serialization Gson
Image loading Glide 4.16.0
UI Material 3 · ConstraintLayout · View Binding
Navigation AndroidX Navigation 2.7.7
State management AndroidX ViewModel + LiveData 2.7.0
Maps / Location Google Maps SDK 18.2.0 + Location Services 21.2.0
Local persistence SQLite (photos) + SharedPreferences (auth)
Testing JUnit 4.13.2 + Espresso 3.5.1

Testing

./gradlew test # Unit tests
./gradlew connectedAndroidTest # Instrumented tests (emulator required)
./gradlew build # Full build (assemble + test)

About

Android front for an F1 social platform. Java · MVVM · Retrofit · JWT · Material 3 · fullstack mobile

Topics

Resources

Stars

Watchers

Forks

Contributors

Languages

AltStyle によって変換されたページ (->オリジナル) /