mirror of
https://github.com/pese-git/cherrypick.git
synced 2026-01-23 21:13:35 +00:00
Compare commits
6 Commits
c483d8c9e2
...
cherrypick
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90732a39e3 | ||
|
|
1298f7dba1 | ||
|
|
9f4288b93f | ||
|
|
5737c89cc9 | ||
|
|
000208e37e | ||
|
|
fe6fc213a7 |
28
CHANGELOG.md
28
CHANGELOG.md
@@ -3,6 +3,34 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## 2025-05-13
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Packages with breaking changes:
|
||||||
|
|
||||||
|
- There are no breaking changes in this release.
|
||||||
|
|
||||||
|
Packages with other changes:
|
||||||
|
|
||||||
|
- [`cherrypick` - `v2.1.0-dev.0`](#cherrypick---v210-dev0)
|
||||||
|
- [`cherrypick_flutter` - `v1.1.1-dev.0`](#cherrypick_flutter---v111-dev0)
|
||||||
|
|
||||||
|
Packages with dependency updates only:
|
||||||
|
|
||||||
|
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
|
||||||
|
|
||||||
|
- `cherrypick_flutter` - `v1.1.1-dev.0`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `cherrypick` - `v2.1.0-dev.0`
|
||||||
|
|
||||||
|
- **FEAT**: Add async dependency resolution and enhance example.
|
||||||
|
|
||||||
|
|
||||||
## 2025-05-03
|
## 2025-05-03
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
|
|||||||
3
cherrypick/.gitignore
vendored
3
cherrypick/.gitignore
vendored
@@ -19,3 +19,6 @@ doc/api/
|
|||||||
*.js_
|
*.js_
|
||||||
*.js.deps
|
*.js.deps
|
||||||
*.js.map
|
*.js.map
|
||||||
|
|
||||||
|
# FVM Version Cache
|
||||||
|
.fvm/
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
## 2.1.0-dev.0
|
||||||
|
|
||||||
|
- **FEAT**: Add async dependency resolution and enhance example.
|
||||||
|
|
||||||
## 2.0.1
|
## 2.0.1
|
||||||
|
|
||||||
- **FIX**: fix warning.
|
- **FIX**: fix warning.
|
||||||
|
|||||||
@@ -1,31 +1,43 @@
|
|||||||
# CherryPick Flutter
|
# CherryPick Flutter
|
||||||
|
|
||||||
`cherrypick_flutter` is a powerful Flutter library for managing and accessing dependencies within your application through a root scope context using `CherryPickProvider`. It offers simplified dependency injection, making your application more modular and test-friendly.
|
`cherrypick_flutter` is a robust Flutter library designed for managing and accessing dependencies using a scope context provided by `CherryPickProvider`. It enhances your application's modularity and testability by simplifying dependency injection.
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
### Main Components in Dependency Injection (DI)
|
### Core Components of Dependency Injection (DI)
|
||||||
|
|
||||||
#### Binding
|
#### Binding
|
||||||
|
|
||||||
A Binding is a custom instance configurator, essential for setting up dependencies. It offers the following key methods:
|
A Binding is a custom instance configurator crucial for setting up dependencies. It offers the following key methods:
|
||||||
|
|
||||||
- `toInstance()`: Directly provides an initialized instance.
|
- `toInstance()`: Directly provides an initialized instance.
|
||||||
- `toProvide()`: Accepts a provider function or constructor for lazy initialization.
|
- `toProvide()`: Accepts a provider function for lazy initialization.
|
||||||
- `withName()`: Assigns a name to an instance, allowing for retrieval by name.
|
- `toProvideAsync()`: Accepts an asynchronous provider for lazy initialization.
|
||||||
- `singleton()`: Marks the instance as a singleton, ensuring only one instance exists in the scope.
|
- `toProvideWithParams()`: Accepts a provider function requiring dynamic parameters.
|
||||||
|
- `toProvideAsyncWithParams()`: Accepts an asynchronous provider requiring dynamic parameters.
|
||||||
|
- `withName()`: Assigns a name for instance retrieval by name.
|
||||||
|
- `singleton()`: Marks the instance as a singleton, ensuring only one instance exists within the scope.
|
||||||
|
|
||||||
##### Example:
|
##### Example:
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
// Direct instance initialization with toInstance()
|
// Direct instance initialization using toInstance()
|
||||||
Binding<String>().toInstance("hello world");
|
Binding<String>().toInstance("hello world");
|
||||||
|
|
||||||
// Or use a provider for lazy initialization
|
// Lazy initialization via provider
|
||||||
Binding<String>().toProvide(() => "hello world");
|
Binding<String>().toProvide(() => "hello world");
|
||||||
|
|
||||||
// Named instance
|
// Asynchronous lazy initialization
|
||||||
Binding<String>().withName("my_string").toInstance("hello world");
|
Binding<String>().toProvideAsync(() async => "hello async world");
|
||||||
|
|
||||||
|
/ Asynchronous lazy initialization with dynamic parameters
|
||||||
|
Binding<String>().toProvideAsyncWithParams((params) async => "hello $params");
|
||||||
|
|
||||||
|
// Initialization with dynamic parameters
|
||||||
|
Binding<String>().toProvideWithParams((params) => "hello $params");
|
||||||
|
|
||||||
|
// Named instance for resolution
|
||||||
|
Binding<String>().toProvide(() => "hello world").withName("my_string").toInstance("hello world");
|
||||||
|
|
||||||
// Singleton instance
|
// Singleton instance
|
||||||
Binding<String>().toProvide(() => "hello world").singleton();
|
Binding<String>().toProvide(() => "hello world").singleton();
|
||||||
@@ -33,7 +45,7 @@ Binding<String>().toProvide(() => "hello world").singleton();
|
|||||||
|
|
||||||
#### Module
|
#### Module
|
||||||
|
|
||||||
A Module encapsulates bindings, allowing you to organize dependencies logically. To create a custom module, implement the `void builder(Scope currentScope)` method.
|
A Module encapsulates bindings, logically organizing dependencies. Implement the `void builder(Scope currentScope)` method to create a custom module.
|
||||||
|
|
||||||
##### Example:
|
##### Example:
|
||||||
|
|
||||||
@@ -48,13 +60,13 @@ class AppModule extends Module {
|
|||||||
|
|
||||||
#### Scope
|
#### Scope
|
||||||
|
|
||||||
A Scope is the container that manages your dependency tree, holding modules and instances. Use the scope to access dependencies with the `resolve<T>()` method.
|
A Scope manages your dependency tree, holding modules and instances. Use the scope to access dependencies with `resolve<T>()` or `resolveAsync<T>()` for asynchronous operations.
|
||||||
|
|
||||||
##### Example:
|
##### Example:
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
// Open the main scope
|
// Open the main scope
|
||||||
final rootScope = Cherrypick.openRootScope();
|
final rootScope = CherryPick.openRootScope();
|
||||||
|
|
||||||
// Install custom modules
|
// Install custom modules
|
||||||
rootScope.installModules([AppModule()]);
|
rootScope.installModules([AppModule()]);
|
||||||
@@ -62,13 +74,16 @@ rootScope.installModules([AppModule()]);
|
|||||||
// Resolve an instance
|
// Resolve an instance
|
||||||
final str = rootScope.resolve<String>();
|
final str = rootScope.resolve<String>();
|
||||||
|
|
||||||
|
// Asynchronously resolve an instance
|
||||||
|
final asyncStr = await rootScope.resolveAsync<String>();
|
||||||
|
|
||||||
// Close the main scope
|
// Close the main scope
|
||||||
Cherrypick.closeRootScope();
|
CherryPick.closeRootScope();
|
||||||
```
|
```
|
||||||
|
|
||||||
## Example Application
|
## Example Application
|
||||||
|
|
||||||
The following example demonstrates module setup, scope management, and dependency resolution.
|
The following example demonstrates module setup, scope management, and dependency resolution (both synchronous and asynchronous).
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
@@ -84,26 +99,30 @@ class AppModule extends Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class FeatureModule extends Module {
|
class FeatureModule extends Module {
|
||||||
bool isMock;
|
final bool isMock;
|
||||||
|
|
||||||
FeatureModule({required this.isMock});
|
FeatureModule({required this.isMock});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void builder(Scope currentScope) {
|
void builder(Scope currentScope) {
|
||||||
|
// Using toProvideAsync for async initialization
|
||||||
bind<DataRepository>()
|
bind<DataRepository>()
|
||||||
.withName("networkRepo")
|
.withName("networkRepo")
|
||||||
.toProvide(
|
.toProvideAsync(() async {
|
||||||
() => NetworkDataRepository(
|
final client = await Future.delayed(
|
||||||
currentScope.resolve<ApiClient>(
|
Duration(milliseconds: 100),
|
||||||
named: isMock ? "apiClientMock" : "apiClientImpl",
|
() => currentScope.resolve<ApiClient>(
|
||||||
),
|
named: isMock ? "apiClientMock" : "apiClientImpl"));
|
||||||
),
|
return NetworkDataRepository(client);
|
||||||
)
|
})
|
||||||
.singleton();
|
.singleton();
|
||||||
bind<DataBloc>().toProvide(
|
|
||||||
() => DataBloc(
|
// Asynchronous initialization of DataBloc
|
||||||
currentScope.resolve<DataRepository>(named: "networkRepo"),
|
bind<DataBloc>().toProvideAsync(
|
||||||
),
|
() async {
|
||||||
|
final repo = await currentScope.resolveAsync<DataRepository>(named: "networkRepo");
|
||||||
|
return DataBloc(repo);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,7 +136,8 @@ void main() async {
|
|||||||
.openSubScope("featureScope")
|
.openSubScope("featureScope")
|
||||||
.installModules([FeatureModule(isMock: true)]);
|
.installModules([FeatureModule(isMock: true)]);
|
||||||
|
|
||||||
final dataBloc = subScope.resolve<DataBloc>();
|
// Asynchronous instance resolution
|
||||||
|
final dataBloc = await subScope.resolveAsync<DataBloc>();
|
||||||
dataBloc.data.listen((d) => print('Received data: $d'),
|
dataBloc.data.listen((d) => print('Received data: $d'),
|
||||||
onError: (e) => print('Error: $e'), onDone: () => print('DONE'));
|
onError: (e) => print('Error: $e'), onDone: () => print('DONE'));
|
||||||
|
|
||||||
@@ -128,7 +148,7 @@ class DataBloc {
|
|||||||
final DataRepository _dataRepository;
|
final DataRepository _dataRepository;
|
||||||
|
|
||||||
Stream<String> get data => _dataController.stream;
|
Stream<String> get data => _dataController.stream;
|
||||||
StreamController<String> _dataController = new StreamController.broadcast();
|
StreamController<String> _dataController = StreamController.broadcast();
|
||||||
|
|
||||||
DataBloc(this._dataRepository);
|
DataBloc(this._dataRepository);
|
||||||
|
|
||||||
@@ -185,6 +205,8 @@ class ApiClientImpl implements ApiClient {
|
|||||||
|
|
||||||
- [x] Main Scope and Sub Scopes
|
- [x] Main Scope and Sub Scopes
|
||||||
- [x] Named Instance Initialization
|
- [x] Named Instance Initialization
|
||||||
|
- [x] Asynchronous Dependency Resolution
|
||||||
|
- [x] Dynamic Parameter Support for Providers
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|||||||
@@ -1,39 +1,38 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:cherrypick/cherrypick.dart';
|
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
|
import 'package:cherrypick/cherrypick.dart';
|
||||||
|
|
||||||
class AppModule extends Module {
|
class AppModule extends Module {
|
||||||
@override
|
@override
|
||||||
void builder(Scope currentScope) {
|
void builder(Scope currentScope) {
|
||||||
bind<ApiClient>().withName('apiClientMock').toInstance(ApiClientMock());
|
bind<ApiClient>().withName("apiClientMock").toInstance(ApiClientMock());
|
||||||
bind<ApiClient>().withName('apiClientImpl').toInstance(ApiClientImpl());
|
bind<ApiClient>().withName("apiClientImpl").toInstance(ApiClientImpl());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FeatureModule extends Module {
|
class FeatureModule extends Module {
|
||||||
bool isMock;
|
final bool isMock;
|
||||||
|
|
||||||
FeatureModule({required this.isMock});
|
FeatureModule({required this.isMock});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void builder(Scope currentScope) {
|
void builder(Scope currentScope) {
|
||||||
bind<DataRepository>()
|
// Using toProvideAsync for async initialization
|
||||||
.withName('networkRepo')
|
bind<DataRepository>().withName("networkRepo").toProvideAsync(() async {
|
||||||
.toProvide(
|
final client = await Future.delayed(
|
||||||
() => NetworkDataRepository(
|
Duration(milliseconds: 100),
|
||||||
currentScope.resolve<ApiClient>(
|
() => currentScope.resolve<ApiClient>(
|
||||||
named: isMock ? 'apiClientMock' : 'apiClientImpl',
|
named: isMock ? "apiClientMock" : "apiClientImpl"));
|
||||||
),
|
return NetworkDataRepository(client);
|
||||||
),
|
}).singleton();
|
||||||
)
|
|
||||||
.singleton();
|
|
||||||
|
|
||||||
bind<DataBloc>().toProvideWithParams(
|
// Asynchronous initialization of DataBloc
|
||||||
(param) => DataBloc(
|
bind<DataBloc>().toProvideAsync(
|
||||||
currentScope.resolve<DataRepository>(named: 'networkRepo'),
|
() async {
|
||||||
param,
|
final repo = await currentScope.resolveAsync<DataRepository>(
|
||||||
),
|
named: "networkRepo");
|
||||||
|
return DataBloc(repo);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,10 +43,11 @@ void main() async {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
final subScope = scope
|
final subScope = scope
|
||||||
.openSubScope('featureScope')
|
.openSubScope("featureScope")
|
||||||
.installModules([FeatureModule(isMock: true)]);
|
.installModules([FeatureModule(isMock: true)]);
|
||||||
|
|
||||||
final dataBloc = subScope.resolve<DataBloc>(params: 'PARAMETER');
|
// Asynchronous instance resolution
|
||||||
|
final dataBloc = await subScope.resolveAsync<DataBloc>();
|
||||||
dataBloc.data.listen((d) => print('Received data: $d'),
|
dataBloc.data.listen((d) => print('Received data: $d'),
|
||||||
onError: (e) => print('Error: $e'), onDone: () => print('DONE'));
|
onError: (e) => print('Error: $e'), onDone: () => print('DONE'));
|
||||||
|
|
||||||
@@ -60,13 +60,11 @@ class DataBloc {
|
|||||||
Stream<String> get data => _dataController.stream;
|
Stream<String> get data => _dataController.stream;
|
||||||
final StreamController<String> _dataController = StreamController.broadcast();
|
final StreamController<String> _dataController = StreamController.broadcast();
|
||||||
|
|
||||||
final String param;
|
DataBloc(this._dataRepository);
|
||||||
|
|
||||||
DataBloc(this._dataRepository, this.param);
|
|
||||||
|
|
||||||
Future<void> fetchData() async {
|
Future<void> fetchData() async {
|
||||||
try {
|
try {
|
||||||
_dataController.sink.add(await _dataRepository.getData(param));
|
_dataController.sink.add(await _dataRepository.getData());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
_dataController.sink.addError(e);
|
_dataController.sink.addError(e);
|
||||||
}
|
}
|
||||||
@@ -78,7 +76,7 @@ class DataBloc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract class DataRepository {
|
abstract class DataRepository {
|
||||||
Future<String> getData(String param);
|
Future<String> getData();
|
||||||
}
|
}
|
||||||
|
|
||||||
class NetworkDataRepository implements DataRepository {
|
class NetworkDataRepository implements DataRepository {
|
||||||
@@ -88,42 +86,26 @@ class NetworkDataRepository implements DataRepository {
|
|||||||
NetworkDataRepository(this._apiClient);
|
NetworkDataRepository(this._apiClient);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<String> getData(String param) async => await _apiClient.sendRequest(
|
Future<String> getData() async => await _apiClient.sendRequest(
|
||||||
url: 'www.google.com',
|
url: 'www.google.com', token: _token, requestBody: {'type': 'data'});
|
||||||
token: _token,
|
|
||||||
requestBody: {'type': 'data'},
|
|
||||||
param: param);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class ApiClient {
|
abstract class ApiClient {
|
||||||
Future sendRequest({
|
Future sendRequest({@required String url, String token, Map requestBody});
|
||||||
@required String url,
|
|
||||||
String token,
|
|
||||||
Map requestBody,
|
|
||||||
String param,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ApiClientMock implements ApiClient {
|
class ApiClientMock implements ApiClient {
|
||||||
@override
|
@override
|
||||||
Future sendRequest({
|
Future sendRequest(
|
||||||
@required String? url,
|
{@required String? url, String? token, Map? requestBody}) async {
|
||||||
String? token,
|
return 'Local Data';
|
||||||
Map? requestBody,
|
|
||||||
String? param,
|
|
||||||
}) async {
|
|
||||||
return 'Local Data $param';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ApiClientImpl implements ApiClient {
|
class ApiClientImpl implements ApiClient {
|
||||||
@override
|
@override
|
||||||
Future sendRequest({
|
Future sendRequest(
|
||||||
@required String? url,
|
{@required String? url, String? token, Map? requestBody}) async {
|
||||||
String? token,
|
return 'Network data';
|
||||||
Map? requestBody,
|
|
||||||
String? param,
|
|
||||||
}) async {
|
|
||||||
return 'Network data $param';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
library;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Copyright 2021 Sergey Penkovsky <sergey.penkovsky@gmail.com>
|
/// Copyright 2021 Sergey Penkovsky <sergey.penkovsky@gmail.com>
|
||||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@@ -11,8 +13,6 @@
|
|||||||
/// limitations under the License.
|
/// limitations under the License.
|
||||||
///
|
///
|
||||||
|
|
||||||
library cherrypick;
|
|
||||||
|
|
||||||
export 'package:cherrypick/src/binding.dart';
|
export 'package:cherrypick/src/binding.dart';
|
||||||
export 'package:cherrypick/src/helper.dart';
|
export 'package:cherrypick/src/helper.dart';
|
||||||
export 'package:cherrypick/src/module.dart';
|
export 'package:cherrypick/src/module.dart';
|
||||||
|
|||||||
@@ -1,20 +1,24 @@
|
|||||||
///
|
//
|
||||||
/// Copyright 2021 Sergey Penkovsky <sergey.penkovsky@gmail.com>
|
// Copyright 2021 Sergey Penkovsky <sergey.penkovsky@gmail.com>
|
||||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
/// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
/// You may obtain a copy of the License at
|
// You may obtain a copy of the License at
|
||||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
/// Unless required by applicable law or agreed to in writing, software
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
/// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
/// limitations under the License.
|
// limitations under the License.
|
||||||
///
|
//
|
||||||
|
|
||||||
enum Mode { simple, instance, providerInstance, providerInstanceWithParams }
|
enum Mode { simple, instance, providerInstance, providerInstanceWithParams }
|
||||||
|
|
||||||
typedef ProviderWithParams<T> = T Function(dynamic params);
|
typedef ProviderWithParams<T> = T Function(dynamic params);
|
||||||
|
|
||||||
|
typedef AsyncProvider<T> = Future<T> Function();
|
||||||
|
|
||||||
|
typedef AsyncProviderWithParams<T> = Future<T> Function(dynamic params);
|
||||||
|
|
||||||
/// RU: Класс Binding<T> настраивает параметры экземпляра.
|
/// RU: Класс Binding<T> настраивает параметры экземпляра.
|
||||||
/// ENG: The Binding<T> class configures the settings for the instance.
|
/// ENG: The Binding<T> class configures the settings for the instance.
|
||||||
///
|
///
|
||||||
@@ -24,6 +28,9 @@ class Binding<T> {
|
|||||||
late String _name;
|
late String _name;
|
||||||
T? _instance;
|
T? _instance;
|
||||||
T? Function()? _provider;
|
T? Function()? _provider;
|
||||||
|
AsyncProvider<T>? asyncProvider;
|
||||||
|
AsyncProviderWithParams<T>? asyncProviderWithParams;
|
||||||
|
|
||||||
ProviderWithParams<T>? _providerWithParams;
|
ProviderWithParams<T>? _providerWithParams;
|
||||||
late bool _isSingleton = false;
|
late bool _isSingleton = false;
|
||||||
late bool _isNamed = false;
|
late bool _isNamed = false;
|
||||||
@@ -94,6 +101,16 @@ class Binding<T> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// RU: Инициализация экземляпяра через провайдер [value].
|
||||||
|
/// ENG: Initialization instance via provider [value].
|
||||||
|
///
|
||||||
|
/// return [Binding]
|
||||||
|
Binding<T> toProvideAsync(AsyncProvider<T> provider) {
|
||||||
|
_mode = Mode.providerInstance;
|
||||||
|
asyncProvider = provider;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/// RU: Инициализация экземляпяра через провайдер [value] c динамическим параметром.
|
/// RU: Инициализация экземляпяра через провайдер [value] c динамическим параметром.
|
||||||
/// ENG: Initialization instance via provider [value] with a dynamic param.
|
/// ENG: Initialization instance via provider [value] with a dynamic param.
|
||||||
///
|
///
|
||||||
@@ -104,6 +121,16 @@ class Binding<T> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// RU: Инициализация экземляра через асинхронный провайдер [value] с динамическим параметром.
|
||||||
|
/// ENG: Initializes the instance via async provider [value] with a dynamic param.
|
||||||
|
///
|
||||||
|
/// return [Binding]
|
||||||
|
Binding<T> toProvideAsyncWithParams(AsyncProviderWithParams<T> provider) {
|
||||||
|
_mode = Mode.providerInstanceWithParams;
|
||||||
|
asyncProviderWithParams = provider;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/// RU: Инициализация экземляпяра как сингелтон [value].
|
/// RU: Инициализация экземляпяра как сингелтон [value].
|
||||||
/// ENG: Initialization instance as a singelton [value].
|
/// ENG: Initialization instance as a singelton [value].
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
///
|
//
|
||||||
/// Copyright 2021 Sergey Penkovsky <sergey.penkovsky@gmail.com>
|
// Copyright 2021 Sergey Penkovsky <sergey.penkovsky@gmail.com>
|
||||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
/// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
/// You may obtain a copy of the License at
|
// You may obtain a copy of the License at
|
||||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
/// Unless required by applicable law or agreed to in writing, software
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
/// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
/// limitations under the License.
|
// limitations under the License.
|
||||||
///
|
//
|
||||||
import 'package:cherrypick/src/scope.dart';
|
import 'package:cherrypick/src/scope.dart';
|
||||||
|
|
||||||
abstract class Factory<T> {
|
abstract class Factory<T> {
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
///
|
//
|
||||||
/// Copyright 2021 Sergey Penkovsky <sergey.penkovsky@gmail.com>
|
// Copyright 2021 Sergey Penkovsky <sergey.penkovsky@gmail.com>
|
||||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
/// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
/// You may obtain a copy of the License at
|
// You may obtain a copy of the License at
|
||||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
/// Unless required by applicable law or agreed to in writing, software
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
/// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
/// limitations under the License.
|
// limitations under the License.
|
||||||
///
|
//
|
||||||
import 'package:cherrypick/src/scope.dart';
|
import 'package:cherrypick/src/scope.dart';
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
///
|
//
|
||||||
/// Copyright 2021 Sergey Penkovsky <sergey.penkovsky@gmail.com>
|
// Copyright 2021 Sergey Penkovsky <sergey.penkovsky@gmail.com>
|
||||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
/// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
/// You may obtain a copy of the License at
|
// You may obtain a copy of the License at
|
||||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
/// Unless required by applicable law or agreed to in writing, software
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
/// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
/// limitations under the License.
|
// limitations under the License.
|
||||||
///
|
//
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'package:cherrypick/src/binding.dart';
|
import 'package:cherrypick/src/binding.dart';
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
///
|
//
|
||||||
/// Copyright 2021 Sergey Penkovsky <sergey.penkovsky@gmail.com>
|
// Copyright 2021 Sergey Penkovsky <sergey.penkovsky@gmail.com>
|
||||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
/// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
/// You may obtain a copy of the License at
|
// You may obtain a copy of the License at
|
||||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
/// Unless required by applicable law or agreed to in writing, software
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
/// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
/// limitations under the License.
|
// limitations under the License.
|
||||||
///
|
//
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'package:cherrypick/src/binding.dart';
|
import 'package:cherrypick/src/binding.dart';
|
||||||
@@ -132,4 +132,45 @@ class Scope {
|
|||||||
// 2 Поиск зависимостей в родительском скоупе
|
// 2 Поиск зависимостей в родительском скоупе
|
||||||
return _parentScope?.tryResolve(named: named);
|
return _parentScope?.tryResolve(named: named);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// RU: Асинхронно возвращает найденную зависимость, определенную параметром типа [T].
|
||||||
|
/// Выдает [StateError], если зависимость не может быть разрешена.
|
||||||
|
/// Если хотите получить [null], если зависимость не может быть найдена, используйте [tryResolveAsync].
|
||||||
|
/// return - возвращает объект типа [T] or [StateError]
|
||||||
|
///
|
||||||
|
/// ENG: Asynchronously returns the found dependency specified by the type parameter [T].
|
||||||
|
/// Throws [StateError] if the dependency cannot be resolved.
|
||||||
|
/// If you want to get [null] if the dependency cannot be found, use [tryResolveAsync] instead.
|
||||||
|
/// return - returns an object of type [T] or [StateError]
|
||||||
|
///
|
||||||
|
Future<T> resolveAsync<T>({String? named, dynamic params}) async {
|
||||||
|
var resolved = await tryResolveAsync<T>(named: named, params: params);
|
||||||
|
if (resolved != null) {
|
||||||
|
return resolved;
|
||||||
|
} else {
|
||||||
|
throw StateError(
|
||||||
|
'Can\'t resolve async dependency `$T`. Maybe you forget register it?');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<T?> tryResolveAsync<T>({String? named, dynamic params}) async {
|
||||||
|
if (_modulesList.isNotEmpty) {
|
||||||
|
for (var module in _modulesList) {
|
||||||
|
for (var binding in module.bindingSet) {
|
||||||
|
if (binding.key == T &&
|
||||||
|
((!binding.isNamed && named == null) ||
|
||||||
|
(binding.isNamed && named == binding.name))) {
|
||||||
|
if (binding.asyncProvider != null) {
|
||||||
|
return await binding.asyncProvider?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (binding.asyncProviderWithParams != null) {
|
||||||
|
return await binding.asyncProviderWithParams!(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _parentScope?.tryResolveAsync(named: named, params: params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
name: cherrypick
|
name: cherrypick
|
||||||
description: Cherrypick is a small dependency injection (DI) library for dart/flutter projects.
|
description: Cherrypick is a small dependency injection (DI) library for dart/flutter projects.
|
||||||
version: 2.0.1
|
version: 2.1.0-dev.0
|
||||||
homepage: https://pese-git.github.io/cherrypick-site/
|
homepage: https://pese-git.github.io/cherrypick-site/
|
||||||
documentation: https://github.com/pese-git/cherrypick/wiki
|
documentation: https://github.com/pese-git/cherrypick/wiki
|
||||||
repository: https://github.com/pese-git/cherrypick
|
repository: https://github.com/pese-git/cherrypick
|
||||||
@@ -13,9 +13,8 @@ dependencies:
|
|||||||
meta: ^1.3.0
|
meta: ^1.3.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
#pedantic: ^1.11.0
|
lints: ^5.0.0
|
||||||
|
test: ^1.25.15
|
||||||
test: ^1.17.2
|
|
||||||
|
|
||||||
mockito: ^5.0.6
|
mockito: ^5.0.6
|
||||||
lints: ^2.1.0
|
melos: ^6.3.2
|
||||||
|
|||||||
@@ -188,6 +188,25 @@ void main() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('Check Async provider.', () {
|
||||||
|
test('Binding resolves value asynchronously', () async {
|
||||||
|
final expectedValue = 5;
|
||||||
|
final binding = Binding<int>().toProvideAsync(() async => expectedValue);
|
||||||
|
|
||||||
|
final result = await binding.asyncProvider?.call();
|
||||||
|
expect(result, expectedValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Binding resolves value asynchronously with params', () async {
|
||||||
|
final expectedValue = 5;
|
||||||
|
final binding = Binding<int>().toProvideAsyncWithParams(
|
||||||
|
(param) async => expectedValue + (param as int));
|
||||||
|
|
||||||
|
final result = await binding.asyncProviderWithParams?.call(3);
|
||||||
|
expect(result, expectedValue + 3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
group('Check singleton provide.', () {
|
group('Check singleton provide.', () {
|
||||||
group('Without name.', () {
|
group('Without name.', () {
|
||||||
test('Binding resolves null', () {
|
test('Binding resolves null', () {
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
## 1.1.1-dev.0
|
||||||
|
|
||||||
|
- Update a dependency to the latest release.
|
||||||
|
|
||||||
## 1.1.0
|
## 1.1.0
|
||||||
|
|
||||||
- **FIX**: update description.
|
- **FIX**: update description.
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
library;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Copyright 2021 Sergey Penkovsky <sergey.penkovsky@gmail.com>
|
/// Copyright 2021 Sergey Penkovsky <sergey.penkovsky@gmail.com>
|
||||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@@ -10,6 +12,5 @@
|
|||||||
/// See the License for the specific language governing permissions and
|
/// See the License for the specific language governing permissions and
|
||||||
/// limitations under the License.
|
/// limitations under the License.
|
||||||
///
|
///
|
||||||
library cherrypick_flutter;
|
|
||||||
|
|
||||||
export 'src/cherrypick_provider.dart';
|
export 'src/cherrypick_provider.dart';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
name: cherrypick_flutter
|
name: cherrypick_flutter
|
||||||
description: "Flutter library that allows access to the root scope through the context using `CherryPickProvider`."
|
description: "Flutter library that allows access to the root scope through the context using `CherryPickProvider`."
|
||||||
version: 1.1.0
|
version: 1.1.1-dev.0
|
||||||
homepage: https://pese-git.github.io/cherrypick-site/
|
homepage: https://pese-git.github.io/cherrypick-site/
|
||||||
documentation: https://github.com/pese-git/cherrypick/wiki
|
documentation: https://github.com/pese-git/cherrypick/wiki
|
||||||
repository: https://github.com/pese-git/cherrypick
|
repository: https://github.com/pese-git/cherrypick
|
||||||
@@ -13,12 +13,14 @@ environment:
|
|||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
cherrypick: ^2.0.0
|
cherrypick: ^2.1.0-dev.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_lints: ^4.0.0
|
flutter_lints: ^5.0.0
|
||||||
|
test: ^1.25.7
|
||||||
|
melos: ^6.3.2
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
|||||||
10
melos.yaml
10
melos.yaml
@@ -8,8 +8,10 @@ packages:
|
|||||||
|
|
||||||
scripts:
|
scripts:
|
||||||
analyze:
|
analyze:
|
||||||
run: |
|
exec: dart analyze
|
||||||
flutter analyze
|
|
||||||
format:
|
format:
|
||||||
run: |
|
exec: dart format
|
||||||
flutter format
|
|
||||||
|
test:
|
||||||
|
exec: flutter test
|
||||||
Reference in New Issue
Block a user