dependencies

dependencies is a library for managing dependencies in Flutter applications. It provides a convenient way to initialize and access services or repositories via an InheritedWidget.


Why it Rocks πŸš€

  • Initialize dependencies before launching the app
  • Access dependencies from anywhere in the widget tree
  • Log initialization times for each dependency
  • Clean and extensible way to manage dependencies
  • Easy to use and integrate with existing codebases

Installation

Add the package to your pubspec.yaml:

dependencies:
  depend: ^0.0.1

Then run:

$ flutter pub get

Example Usage

Example 1: Define Dependencies

Step 1: Create a List of Dependencies

Start by creating a list of dependencies that will be initialized when your app starts. Each dependency can rely on another through DependenciesProgress:

List<DependenciesProgress> progress = [
  (progress) => ApiService(), // Example of an independent dependency
  (progress) {
    return AuthRepository(
      dataSource: AuthDataSource(
        apiService: progress.dependencies.get<ApiService>(),
      ),
    );
  },
];

Step 2: Initialize Dependencies

Use DependenciesInit to initialize your dependencies before launching the app:

void main() {
  final init = DependenciesInit(progress: progress);

  runApp(
    MyApp(
      dependencies: init.dependencies,
    ),
  );
}

Step 3: Access Dependencies with InheritedWidget

Once initialized, dependencies can be accessed from anywhere in the widget tree using Dependencies.of(context).get<T>():

class MyApp extends StatelessWidget {
  final DependenciesLibrary dependencies;

  const MyApp({super.key, required this.dependencies});

  @override
  Widget build(BuildContext context) {
    return Dependencies(
      dependencies: dependencies,
      child: MaterialApp(
        title: 'Flutter Demo',
        home: MyHomePage(),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool isLogin = false;

  void _login() {
    try {
      Dependencies.of(context).get<AuthRepository>().login();
      setState(() {
        isLogin = true;
      });
    } catch (err) {
      print(err);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Column(
          children: [
            Text('Login: $isLogin'),
            ElevatedButton(
              onPressed: _login,
              child: const Text('Login'),
            ),
          ],
        ),
      ),
    );
  }
}

Example 2: Example Usage with Bloc

You can also use dependencies with Bloc for state management. Here’s an example where the AuthRepository is injected into an AuthBloc:

/// Authentication BLoC
class AuthBloc extends Bloc<AuthEvent, AuthState> {
  final AuthRepository authRepository;

  AuthBloc({required this.authRepository}) : super(AuthInitial()) {
    on<LoginRequested>(_login);
  }
}
BlocProvider(
    create: (context) => AuthBloc(
      authRepository: Dependencies.of(context).get<AuthRepository>(),
    ),
),

In this example:

  • We create an AuthBloc that depends on AuthRepository (which is initialized through the dependencies library).
  • The AuthBloc is provided using BlocProvider, and we inject the AuthRepository from the dependencies into the BLoC.
  • The UI responds to authentication events and displays different states like AuthSuccess or AuthFailure.

Logging and Debugging

During initialization, each dependency logs the time it took to initialize:

πŸ’‘ ApiService: initialized successfully for 500 ms
πŸ’‘ AuthRepository: initialized successfully for 10 ms

This is useful for tracking performance and initialization times.

Conclusion

The dependencies library provides a clean and extensible way to manage dependencies in your Flutter app, including integration with Bloc for state management.

Libraries

depend