Search code examples
flutterdartarchitectureblocflutter-cubit

How to organise architecture using main.dart in huge projects?


I'm preparing to create proper architecture in dart. I make tutorials in flutter about bloc, cubit, providers etc.

How do you provide well organise main.dart to have it well written?

i.e. I use models, repositories, services, cubit, screens itd., but... everthing goes to main.dart.

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:pagination_app/data/repositories/post_repository.dart';
import 'package:pagination_app/presentation/post_screen.dart';

import 'bloc/posts/posts_cubit.dart';
import 'data/services/post_service.dart';

void main() {
  runApp(PaginationApp(repository: PostsRepository(PostsService()),));
}

class PaginationApp extends StatelessWidget {
  const PaginationApp({Key? key, required this.repository}) : super(key: key);

  final PostsRepository repository;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BlocProvider(
        create: (context) => PostsCubit(repository),
        child: PostsView(),
      ),
    );
  }
}

It is okay if I use it like this for small projects. How to you achieve clean code, maybe somekind of global providers where I handle all repositories then launch to main.dart? What is your proposition?


Solution

  • There are multiple ways of how you can achieve it. One of those is the one you just mentioned - injecting repositories/services inside main.dart. Even better - not to clutter this file, you could create some kind of bootstrap function in a separate file that wraps your app and injects the dependencies as well. This way, you keep the main.dart clean by also having a single place of where you are keeping and managing dependencies. Here you could find an example of such bootstrap function.

    Another way of doing this is using a Dependency Injection (DI) package or service locator where you define all your dependencies that could be later accessed across the app. For instance, when using get_it, you could create a dedicated file where you initiate the service locator by registering all your app dependencies in a single file. This way, you do not need to wrap your app in any way, since the service locator is basically a globally accessible singleton object that allows you to resolve dependencies.