Android User Login with MVVM, Ktor Client & RESTful APIs

Hi all! Welcome to a brand new post. Today, I have something really helpful for you — a flexible and foolproof Android User Login template that you can plug into your next project easily. With …

android user login

Hi all! Welcome to a brand new post. Today, I have something really helpful for you — a flexible and foolproof Android User Login template that you can plug into your next project easily.

With Android development evolving so much in recent years, it’s important to stay updated — and that’s exactly why I’m sharing this with you. This login template is built using the Ktor Android Client, making it clean, modern, and easy to customize.

Android User Login Demo

Before moving ahead, it’s better to take a look at the app first. Below, you can see the app in action that we’re going to build.

android user login

The above android user login app uses

  • Jetpack Compose – Modern UI toolkit for building beautiful and reactive UI.
  • Ktor Client – Lightweight and efficient networking for API calls.
  • Jetpack Compose Navigation – Manages screen transitions seamlessly.
  • Kotlin Serialization – Simplifies JSON parsing for API responses.
  • Hilt (Dependency Injection) – Ensures modularity and easy testing.
  • ViewModel + StateFlow – Manages UI state efficiently.
  • DataStore – Stores authentication tokens securely.

Android User Login API

I’m utilizing dummyjson.com for login API in this project.
You can just clone the repo and run it immediately.

If you would like to include your own API, you may need to modify the code a bit to accommodate your API’s response structure.

The base URL is defined in the app level build.config file.

You can visit dummyjson.com to check the login request and response it is pretty simple.

App Architecture

The core of this setup is MVVM (Model-View-ViewModel). On top of that, I’ve added a few extra layers to make everything more maintainable and scalable:

  • Repository Layer – Handles all data operations, whether local or from a remote API.
  • Use Case Layer – Wraps business logic in reusable, testable actions.
  • Composable View Layer – Builds UI using Jetpack Compose in a clean and modular way.
  • State/Event-driven ViewModels – Manages UI logic with better structure and flexibility.

File Structure Pattern per Screen

To keep things clean and consistent, every screen in the app follows the same simple 3-file structure. This makes the code easier to navigate, maintain, and scale as the app grows. Let’s take the Login screen as an example:

1. LoginView.kt – The Composable Root

This is the entry point for the screen. It contains only one public composable: LoginView(). This function connects everything together—it takes in the LoginViewModel and any necessary callbacks or arguments.

Inside LoginView, we collect state from the ViewModel and pass it down to the internal UI components. The actual UI is rendered by a private composable function called Login(). That’s where the layout and visuals are handled.

You can also define smaller private composables here if needed, like inputs, buttons, etc., but everything apart from the root function stays private. These UI components are stateless, and they simply receive the state from LoginView and sends the UI Events back to LoginView.

This separation helps keep logic out of the UI and keeps the rendering functions focused on just that—rendering.

2. LoginViewModel.kt – The ViewModel

This is where all the logic lives.

The LoginViewModel extends a custom base class called EventStateViewModel<S, E>, where S is the state and E is the event.

This setup lets us keep UI state and user-triggered events in separate, well-defined buckets. The ViewModel listens for events (like button clicks), handles them using use cases, and then updates the state accordingly. It’s clean, testable, and flexible enough for any screen.

3. LoginViewModelData.kt – State & Event Definitions

This file holds the definitions for the screen’s state and events. Typically, these are represented using data classes and sealed classes.

  • LoginViewState: Holds UI-related data like email, password, loading flags, etc.
  • LoginViewEvent: A sealed class that defines user actions—like OnEmailChanged, OnLoginClicked, etc.

Keeping state and events in a separate file makes everything easier to manage and helps avoid clutter in the ViewModel itself.

This 3-file pattern helps strike a good balance between clarity, testability, and scalability. The UI stays dumb and clean, the logic stays in the ViewModel, and the state/event definitions stay organized in their own space.

Why EventStateViewModel?

This base ViewModel class helps simplify things by abstracting state and events. That means:

  • You can reuse logic across multiple screens.
  • It’s easier to test and debug.
  • It scales well as the app grows.

All you have to do is define the ViewState and ViewEvent for each screen, and the rest plugs in smoothly.

It should not be the parent for all your ViewModels — only for those where you want to use the Event-State pattern.

Benefits of This Architecture

  • Separation of Concerns
    Each layer has one job, making the codebase clean and organized.
  • Composable & Modular
    Screens are easy to build, update, and test individually.
  • Test-Friendly
    ViewModels and Use Cases are simple to write unit tests for.
  • Scalable
    Whether you’re working solo or with a team, this structure can grow with your app.

Download the Android User Login Project

If you’d rather dive in and explore the project hands-on, you can grab the full Android User Login source code right here.

Android User Login Project Source Code

It’s a great way to understand how everything fits together — from the architecture and UI to how the login logic is handled behind the scenes.

Whether you’re looking to build your own login system or just curious about how modern Android apps manage authentication, this project can be a solid reference.

Got a question, ran into a bug, or just want to share your thoughts? Drop a comment below — I read every one and I’m happy to help however I can.

Hi, my name is Belal Khan and I am a Google Developers Expert (GDE) for Android. The passion of teaching made me create this blog. If you are an Android Developer, or you are learning about Android Development, then I can help you a lot with Simplified Coding.

Expand Your Knowledge: Next Tutorial Picks

0 0 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x