An additional layer of abstraction for creating repositories following the BLoC pattern architecture
Android | iOS | macOS | Web | Linux | Windows |
---|---|---|---|---|---|
✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
The existing BLoC libraries are amazing for handling state managment in Flutter projects. However, there are a few issues regarding Repository
s, which this package aims to fix.
- The boundaries for creating
Repositores
is are way too loose. Inpackage:flutter_bloc
, aRepository
can literally be any class. This package solves that problem by creating a class,Repository
, which all the repositories can inherit from. - Having all the repositories extend the same class makes it possible to create methods that all the classes have. For instance,
initialize
anddispose
methods. When all the repositories have these methods, its easier to initialize and dispose multiple repositories in bulk. - Repository-to-repository communication is hard to implement. A repository should be independent of other repositories and their implementations. However, sometimes a repository needs to call a method in another repository, or some method defined elsewhere outside the repository. To decouple repositories from each other, this package contains a
RepositoryChannel
which can be used to communicate back and forth to repositories.
-
Create a
RepositoryChannel
class MyRepositoryChannel extends RepositoryChannel{ // Add your custom repository events here MyRepositoryChannel({ required super.log, required this.myCustomCallback, }); final void Function() myCustomCallback; }
-
Create
Repository
and use the channelclass MyRepository extends Repository<MyRepositoryChannel>{ MyRepository({ required MyRepositoryChannel channel, }) super(channel); /// You can override the `initialize` and `dispose` methods, like so @override FutureOr<void> initialize(){ // Do own initialization super.initialize(); } Future<void> doSomething() async { channel.log('Starting to do something!'); // Do something channel.myCustomCallback(); channel.log('Finished doing something!'); } }
-
Use the repository
Widget build(BuildContext context){ return RepositoryProvider<MyRepository>( create: (_) => MyRepository( channel: MyRepositoryChannel( log: (value) => print(value), myCustomCallback: () {}, ); ); ); }
Creating mocks for the RepositoryChannel
function calls is easy with package:mocktail.
- For each function call you want to mock, create a mock class that extends
Mock
. The class should contain only a single method,call
. The method should not contain method body, and it should have the same return type and parameters as the method being mocked.class MockLog extends Mock { void call(String v); }
- Construct the class as you would normally, but instead of the actual function, pass
RepositoryChannel
the mocked function.final log = MockLog(); channel = MyRepositoryChannel( log: log, ); // Now you can do you basic mocktail stuff // Register calls when(() => log(any<String>())).thenAnswer((_) {}); // Check for calls verify(() => log('test')).called(1);