Implementing Themes in Flutter with Cubit: Best Practices

Flutter allows developers to create visually stunning apps, and implementing themes is crucial to enhance the user experience. By using the Cubit state management approach, you can efficiently switch between light and dark themes or even customize your app’s appearance dynamically.

This tutorial will guide you through the best practices for implementing themes in a Flutter app using Cubit.


Why Use Cubit for Theme Management?

Cubit (a lightweight version of Bloc) separates business logic from the UI, making your code clean, testable, and maintainable. For theme management:

  • Centralized Control: Manage themes across the app from a single point.
  • Dynamic Switching: Enable runtime switching of themes based on user preferences.
  • Scalability: Easily expand to include multiple themes in the future.

Step 1: Set Up Your Flutter Project

  1. Create a new Flutter project:
    flutter create theme_cubit_demo cd theme_cubit_demo
  2. Add the required dependencies in pubspec.yaml:
dependencies:
  flutter:
    sdk: flutter
  flutter_bloc: ^8.1.0

Step 2: Define the Theme Cubit and States

Create a directory structure for Cubit:

lib/
  |- cubit/
      |- theme_cubit.dart
      |- theme_state.dart

Define Theme States

Create theme_state.dart to define the available theme states:

import 'package:flutter/material.dart';

abstract class ThemeState {
  ThemeData get themeData;
}

class LightThemeState extends ThemeState {
  @override
  ThemeData get themeData => ThemeData.light().copyWith(
        primaryColor: Colors.blue,
        appBarTheme: AppBarTheme(color: Colors.blue),
      );
}

class DarkThemeState extends ThemeState {
  @override
  ThemeData get themeData => ThemeData.dark().copyWith(
        primaryColor: Colors.black,
        appBarTheme: AppBarTheme(color: Colors.black),
      );
}

Define the Theme Cubit

Create theme_cubit.dart to handle theme logic:

import 'package:bloc/bloc.dart';
import 'theme_state.dart';

class ThemeCubit extends Cubit<ThemeState> {
  ThemeCubit() : super(LightThemeState());

  void toggleTheme() {
    if (state is LightThemeState) {
      emit(DarkThemeState());
    } else {
      emit(LightThemeState());
    }
  }
}

Step 3: Implement Theme Switching in the App

Update main.dart to integrate the theme Cubit:

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'cubit/theme_cubit.dart';
import 'cubit/theme_state.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => ThemeCubit(),
      child: BlocBuilder<ThemeCubit, ThemeState>(
        builder: (context, themeState) {
          return MaterialApp(
            title: 'Theme Cubit Demo',
            theme: themeState.themeData,
            home: HomeScreen(),
          );
        },
      ),
    );
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Theme Cubit Demo'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            context.read<ThemeCubit>().toggleTheme();
          },
          child: Text('Toggle Theme'),
        ),
      ),
    );
  }
}

Step 4: Run the App

  1. Start the app using: flutter run
  2. Tap the “Toggle Theme” button to switch between light and dark themes.

Best Practices

  • Use Constants: Define commonly used colors or styles as constants to ensure consistency.
  • Custom Themes: Extend the ThemeData class to include custom attributes for specific app requirements.
  • Persist Theme Preferences: Use a package like shared_preferences to save the user’s theme choice across sessions.

Source Code

The complete source code for this tutorial can be found on GitHub. Feel free to explore and build upon it to suit your app’s needs.

Conclusion

With Cubit, managing themes in Flutter becomes structured and scalable. Whether it’s switching between light and dark modes or implementing custom themes, the Cubit architecture ensures your code is maintainable and clean. Start experimenting with themes in your Flutter app today! 🚀