flutter_ddi 0.4.0 copy "flutter_ddi: ^0.4.0" to clipboard
flutter_ddi: ^0.4.0 copied to clipboard

A Flutter package for easy and clean dependency injection management, enhancing code organization and flexibility.

Flutter DDI Library #

pub package Last Commits Issues Pull Requests Code size License

The flutter_ddi library is a Flutter package that integrates with the dart_ddi dependency injection manager, simplifying the dependency injection process in Flutter applications. It enhances code organization, flexibility, and maintainability, making the codebase more structured and scalable.

Features #

The flutter_ddi offers a range of features that can be easily integrated into your Flutter application. You can choose to use or not the route management provided by the package. If preferred, you can integrate flutter_ddi solely for dependency injection, maintaining your own route logic.

  • Integration during navigation: While navigating between screens, you can utilize flutter_ddi without the need to create routes. The package simplifies passing dependencies to new screens.

  • Enhanced route building: By using flutter_ddi to construct your routes, you improve code organization by separating navigation logic from object creation logic.

  • Improved code organization: By separating navigation and dependency structures from screen and business logics, your code becomes more organized and easier to maintain, especially in large and complex projects.

  • Flexibility and scalability: This package is designed to be flexible and scalable, allowing you to add and change dependencies as needed without impact on other parts of the code.

Using flutter_ddi #

Defining Modules and Routes #

FlutterDDIModule #

The FlutterDDIModule class is an abstraction that allows defining a module to organize and encapsulate specific dependencies.

Example Usage:

class HomeModule extends FlutterDDIModule {

  @override
  FutureOr<void> onPostConstruct() {
    registerApplication<HomeRepository>(() => HomeRepositoryImpl());
    registerApplication<HomeService>(() => HomeServiceImpl(homeRepository: ddi()));
    registerApplication<HomeController>(() => HomeControllerHomeServiceImpl(homeService: ddi<HomeService>()));
  }

  @override
  WidgetBuilder get page => (_) => const HomePage();

  @override
  String get path => '/home';
}

FlutterDDIModuleRouter #

The FlutterDDIModuleRouter class is used to define routes that contain modules. With it, you can organize the application navigation in a modular way, facilitating code maintenance and expansion.

Example Usage:

class SplashModule extends FlutterDDIModuleRouter {

  @override
  WidgetBuilder get page => (_) => const SplashPage();

  @override
  String get path => '/';

  @override
  List<FlutterDDIModuleDefine> get modules => [
    FlutterDDIPage.from(path: '/signup', page: (_) => const SignupPage()),
    LoginModule(),
    HomeModule(),
  ];
}

You can also use the DDIModule mixin in a class that extends FlutterDDIModuleRouter. This allows creating a structure of modules with submodules.

Example Usage:

class SplashModule extends FlutterDDIModuleRouter with DDIModule {

  @override
  FutureOr<void> onPostConstruct() {
    registerSingleton<DioForNative>(() => RestClient('http://my-url'));
  }

  @override
  WidgetBuilder get page => (_) => const SplashPage();

  @override
  String get path => '/';

  @override
  List<FlutterDDIModuleDefine> get modules => [
    FlutterDDIPage.from(path: 'signup', page: (_) => const SignupPage()),
    LoginModule(),
    HomeModule(),
  ];
}

FlutterDDIFutureModuleRouter #

The FlutterDDIFutureModuleRouter class is used to create modules that have Future loading. Making it possible to await for initialization before accessing the route

Example Usage:

class SplashModule extends FlutterDDIFutureModuleRouter {

  @override
  Future<void> onPostConstruct() async{
    await registerSingleton<Databaseconnection>(() async => Databaseconnection());
  }

  @override
  WidgetBuilder get page => (_) => const SplashPage();

  @override
  String get path => '/';

  @override
  List<FlutterDDIModuleDefine> get modules => [
    FlutterDDIPage.from(path: 'signup', page: (_) => const SignupPage()),
    LoginModule(),
    HomeModule(),
  ];

  @override
  Widget get error => const SizedBox.shrink();

  @override
  Widget get loading => const Center(child: CircularProgressIndicator());

}

FlutterDDIPage #

The FlutterDDIPage class allows defining pages that do not have any dependencies.

Example Usage:

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home Page'),
      ),
      body: Center(
        child: Text('Home Page Content'),
      ),
    );
  }
}

class HomeModule extends FlutterDDIPage {
  @override
  WidgetBuilder get page => (_) => const HomePage();

  @override
  String get path => '/home';
}

Using the FlutterDDIRouter #

The FlutterDDIRouter class is a utility that allows building application routes from the defined modules and pages. With it, you can get a map of routes ready to be used with the Flutter Navigator.

Example Usage:

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'My App',
      initialRoute: '/',
      routes: FlutterDDIRouter.getRoutes(
        modules: [
            SplashModule(),
        ],
      ),
    );
  }
}

Simplified State Management #

Managing state in Flutter applications, especially for medium or smaller projects, doesn't always require complex state management solutions. For apps where simplicity and efficiency are key, using these mixins and classes for state management can be a straightforward and effective approach. But for larger and complex projects, it's recommended to use a proper state management solutions.

How It Works #

Under the hood, these mixins utilize the setState method to update the widget's state. They handle registering an event or stream in the initState and cleaning up in the dispose method.

Example Usage:

    class HomePage extends StatefulWidget {
        const HomePage({super.key});

        @override
        State<HomePage> createState() => _HomePageState();
    }

    /// You can extend `StreamListenerState` or `EventListenerState` or use the mixin `StreamListener` or `EventListener`
    class _HomePageState extends StreamListenerState<HomePage, HomePageModel> {
    // class _HomePageState extends EventListenerState<HomePage, HomePageModel> {
    // class _HomePageState extends State<HomePage> with StreamListener<HomePage, HomePageModel> {
    // class _HomePageState extends State<HomePage> with EventListener<HomePage, HomePageModel> {

      Widget build(BuildContext context) {
          return Text('Welcome ${state.name} ${state.surname}');
      } 
    }

    class HomePageModel {
      final String name;
      final String surname;

      HomePageModel(this.name, this.surname);
    }

    class HomePageControler with DDIEventSender<HomePageModel> {
    //class HomePageControler with DDIStreamSender<HomePageModel>{

      String name = 'John'; 
      String surname = 'Wick';

      void update() {
        fire(HomePageModel(name, surname));
      }
    }

FlutterDDIBuilder #

The Widget FlutterDDIBuilder handles dependency injection by wrapping a builder and registering its module asynchronously.

Example Usage:

    class HomePage extends StatelessWidget {
        const HomePage({super.key});

        @override
        Widget build(BuildContext context) {
            return Column(
                children: [
                    FlutterDDIBuilder<BeanT>(
                      module: AsyncWidgetModule.new,
                      child: (context) => const MyWidget(),
                      moduleName: 'AsyncWidgetModule',
                      loading: const CircularProgressIndicator(),
                      error: const ErrorWidget(),
                    ),
                ],
            );
        } 
    }

Extension FlutterDDIContext #

The FlutterDDIContext extension provides a get and arguments method on the BuildContext class. The get method allows getting a dependency from the context. The arguments method allows getting the arguments passed in the route.

Example Usage:

    class HomePage extends StatelessWidget {
        const HomePage({super.key});

        @override
        Widget build(BuildContext context) {
            final HomePageController controller = context.get<HomePageController>();

            final RouteArguments routeData = context.arguments<RouteArguments>();

            return Container();
        }
    }

Known Limitation #

Circular Routes: At present, the package does not fully support circular route structures. Defining circular dependencies between routes will lead to errors during the module registration process.

Any help, suggestions, corrections are welcome.

0
likes
160
pub points
42%
popularity

Publisher

unverified uploader

A Flutter package for easy and clean dependency injection management, enhancing code organization and flexibility.

Repository (GitHub)
View/report issues

Topics

#dependency-injection #di #inject #java #routes

Documentation

API reference

License

Apache-2.0 (license)

Dependencies

dart_ddi, flutter

More

Packages that depend on flutter_ddi