Skip to main content
back to blogs

The Cleanest Way to Do Dark/Light Mode in Flutter

November 22, 2025 8 min read

A simple and effective approach to implement dark and light themes in your Flutter app using ValueNotifier.

Hey, I'm Ekaksh.

In this post I'm going to walk you through how I set up dark mode and light mode in Flutter using nothing besides ValueNotifier and ValueListenableBuilder.

This is exactly the same setup I showed in my YouTube video.

I use this pattern in basically every Flutter app I build because it's clean, simple, and works everywhere in the app without dragging in state-management packages just for toggling a theme.

Let's jump into it.


Step 1: Create a new project and install dependencies (optional)

Create a new Flutter project:

snippet.bash

Add shared_preferences if you want to persist the theme choice:

snippet.bash

Now, just remove the boilerplate from main.dart, create your usual app.dart and home.dart, and get a basic MaterialApp running.

Setp 2: Create the Theme Notifier (this is the core)

We need something to tell the entire app:
"Theme mode changed — rebuild yourself."

Flutter already gives us ValueNotifier, so we'll just use that.
So, let's create a theme_notifier.dart file and write the following code:

snippet.dart

Why a singleton? Because I want to access this from anywhere in the app without passing BuildContext around like it’s hot potato.

Step 3: Persisting the theme with SharedPreferences (optional)

If someone switches to dark mode, closes the app, opens it again — the app should stay in dark mode.

For this, we can use the shared_preferences package we added earlier.
Let's create a class called LocalStorage in a file called local_storage.dart to handle saving and retrieving things from local storage:

snippet.dart

Step 4: Complete the theme notifier with persistence

Now let's complete the theme notifier by implementing the loadThemeMode, saveThemeMode, and toggleTheme methods:

snippet.dart

Step 5: Setup the material app to listen to theme changes

In your app.dart, wrap your MaterialApp with a ValueListenableBuilder that listens to the themeModeNotifier:

snippet.dart

Finally in your main.dart, initialize the LocalStorage and loadThemeMode before running the app:

snippet.dart

Step 6: Setup your home.dart

snippet.dart

Great! Now we have a working dark mode and light mode toggle, with persistence using local storage and zero external state-management packages. Just simple ValueNotifiers doing their job.

Here is the full source code:
Theme Notifier Tutorial

Thanks for reading, hope this helps you keep your theming clean.