-
Notifications
You must be signed in to change notification settings - Fork 254
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: New Modular 6 #829
feat: New Modular 6 #829
Conversation
Codecov Report
@@ Coverage Diff @@
## master #829 +/- ##
==========================================
Coverage 100.00% 100.00%
==========================================
Files 8 38 +30
Lines 114 920 +806
==========================================
+ Hits 114 920 +806
|
Acho interessante fazer um breaking change mesmo no Bind para não precisar criar um AutoBind, como alternativa, ter apenas o Bind padrão. |
Eu manteria os dois, pois da nova forma eu nao conseguiria registrar um método estático no Bind (tecnica utilizada para desacoplar os Packages com métodos estático), obviamente nao precisaria de todos os ciclos de vida (lazySingleton, Singleton, etc) apenas o factory entao poderia colocar os demais como Deprecated, para nao causar breaking changes inesperados, e dpois de 2 versões retirar eles, mas mantendo o factory (ou chamar de outoro nome) |
No modelo novo eu conseguiria ter um construtor passando uma constante como parâmetro? |
outra coisa, ja que tem o |
Na nova versão vc pode usar função anonima sem o (i) AutoBind.factory<HiveServiceFactory>(() => const HiveServiceFactory(path: 'database')); |
Dá pra fazer a mesma coisa: AutoBind.factory<FShowDialog>(() ⇒ (Widget child) async {
return await Asuka.showDialog(builder: (context) ⇒ child);
}),
AutoBind.factory<FAlert>(() ⇒ (String text) {
AsukaSnackbar.alert("success").show();
}),
AutoBind.factory<IDialogAdapter>(() ⇒ AsukaDialog(
fShowDialog: i<FShowDialog>(),
fAlert: i<FAlert>(),
)),
O Class.new cria uma função, () => Class(); |
O escopo de registro é feito por módulo. Sem esse limite pode haver incongruência de dados, visto que o Modular lida com contexto de módulo e não registro 1 a 1. |
Acredito que substituir totalmente o Bind pelo AutoBind seja a forma mais correta, pois é uma melhoria de como sempre deveria ser. Manter a forma antiga fará com que as pessoas não se atualizem |
Mas aí vai quebrar de cara os projetos ou vai por como |
Só dá pra colocar @deprecated quando o método vai ter um substituto. Ali é refatoração, assim como foi no BLoC 7 pro 8 |
Temos duas decisões a tomar: |
Olá @jacobaraujo7, Aproveitando que teremos uma alteração na "major version" do Modular e, consequentemente, possíveis breaking changes, gostaria de sugerir uma alteração no WidgetModule, pois atualmente ele possui um problema que temos que contornar. class LocalModule extends WidgetModule{
@override
List<Bind> get binds => [
Bind.singleton((i) => MySpecialController())
];
@override
Widget get view => MyWidget(Modular.get<MySpecialController>());
} O exemplo acima (parecido com o da documentação) lança um erro, pois Widget Function() get view => () => MyWidget(Modular.get<MySpecialController>()); Atualmente para contornar, eu crio um widget "wrap" dessa forma: class WidgetModuleView extends StatelessWidget {
const WidgetModuleView({super.key, required this.child});
final Widget Function() child;
@override
Widget build(BuildContext context) => child();
} E uso assim: Widget get view => WidgetModuleView(child: () => MyWidget(Modular.get<MySpecialController>())); O que acha? |
Perfeito. |
break change nos Binds mesmo. |
Um sugestão que me ocorreu aqui. |
Estou trabalhando em tornar o WidgetModule um Widget puro e assim poderemos chegar em uma sintaxe melhor. Com esse código podemos Chegar a uma sintaxe assim: class MyWidgetModule extends WidgetModule {
@override
List<Bind> get binds => []
@override
Widget build(BuildContext context){
return Container();
}
} Assim acredito que fica com mais cada Widget. |
Assim vai ficar bem melhor @jacobaraujo7. Dentro do método build poderemos passar o Bind via constructor para o widget que é responsável pela view, certo? Exemplo: class MyWidgetModule extends WidgetModule {
@override
List<Bind> get binds => [
Bind.singleton(MyController.new)
];
@override
Widget build(BuildContext context){
return HomePage(Modular.get<MyController>());
}
} |
Hi, any ETA on this PR ? I'm still stuck with the v4.5.* and flutter 2 (because modular v5 has too many DI problems). I'm still hoping this version will allow me to migrate to flutter 3 soon... Thanks for your work |
Estou testando o release do Modular 6.0.0-beta.1. O novo WidgetModule ainda está com o problema do Bind ser chamado antes de ser injetado. Fiz um ajuste para que isso não aconteça, permitindo o uso de suas dependências imediatamente. class _ModuleElement extends ComponentElement {
/// Creates an element that uses the given widget as its configuration.
_ModuleElement(PageWidget super.widget);
@override
Widget build() {
final widgetModule = widget as PageWidget;
final child = () => widgetModule.build(this);
return _ModularProvider(
module: _ModuleImpl(
binds: widgetModule.binds,
exportedBinds: widgetModule.exportedBinds,
imports: widgetModule.imports,
),
tag: widgetModule.runtimeType.toString(),
child: child,
);
}
@override
void update(StatelessWidget newWidget) {
super.update(newWidget);
assert(widget == newWidget, 'widget == newWidget');
rebuild(force: true);
}
}
class _ModularProvider extends StatefulWidget {
final Widget Function() child;
final Module module;
final String tag;
const _ModularProvider({
super.key,
required this.child,
required this.module,
required this.tag,
});
@override
_ModularProviderState createState() => _ModularProviderState();
}
class _ModularProviderState extends State<_ModularProvider> {
@override
void initState() {
super.initState();
injector.get<BindModule>().call(widget.module, widget.tag);
}
@override
Widget build(BuildContext context) {
return widget.child();
}
@override
void dispose() {
super.dispose();
injector.get<UnbindModule>().call(type: widget.tag);
}
} Com esse ajuste, consigo consumir sem problemas. :). Essa nova sintaxe está muito boa, abraços à equipe. |
Version: ˆ6.0.0-beta.3 routerConfig: Modular.routerConfig,
// routerDelegate: Modular.routerDelegate,
// routeInformationParser: Modular.routeInformationParser, Works normally on the old setup: // routerConfig: Modular.routerConfig,
routerDelegate: Modular.routerDelegate,
routeInformationParser: Modular.routeInformationParser, |
Exception on Flutter Web. App will work normally on debug but on release Modular will not work: AutoInjectorException: minified:I Class is already added. Problem:
Solution:
import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart';
void main() {
runApp(ModularApp(module: AppModule(), child: const AppWidget()));
}
class AppWidget extends StatelessWidget {
const AppWidget({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerConfig: Modular.routerConfig,
routeInformationParser: Modular.routeInformationParser,
);
}
}
class AController {}
class BController {}
class AppModule extends Module {
@override
final List<Bind> binds = [
// AutoBind.singleton(AController.new), <-- this will pass
// AutoBind.singleton(BController.new), <-- this will throw "AutoInjectorException: Class is already added"
AutoBind.singleton<AController>(AController.new), // <-- this works
AutoBind.singleton<BController>(BController.new), // <-- this works
];
@override
final List<ModularRoute> routes = [
ChildRoute('/', child: (_, args) => const Page()),
];
}
class Page extends StatelessWidget {
const Page({super.key});
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text('Hello World!'),
),
);
}
} The environment: name: modular_web
description: A new Flutter project.
publish_to: 'none'
version: 0.1.0
environment:
sdk: '>=3.0.5 <4.0.0'
dependencies:
flutter_modular: ^6.0.0-beta.5
flutter:
sdk: flutter
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
flutter:
uses-material-design: true |
Small improvements on the wording, nothing too important but wanted to help correct this. Thanks for this great package!
Descrição
Esse PR se trata das alterações feitas no
modular_core
,flutter_modular
eshelf_modular
.Inicialização no flutter_modular
Melhoramos a forma de iniciar o Modular no widget principal:
Mudança no sistema de Injeção
A principal mudança será a substituição do modular_core pelo
AutoInjector
como sistema de injeção de dependência, melhorando a sintaxe de registro:Modular 5<
Nova sintaxe de registro Modular 6>
Nessa nova versão será introduzido o
AutoBind
que permite a nova sintaxe de registro dos binds.A ideia inicial era substituir a sintaxe atual do
Bind
, porém estamos decidindo se iremos manteros dois conceitos (
Bind
eAutoBind
).O novo sistema de injeção parece está trabalhando bem em demandas mais altas, porém alguns testes adicionais
ainda precisam ser realizados comprovar isso. Esses testes estão sendo feito no repositório do
AutoInjector
.Adicionar Módulo em tempo de execução (Injeção)
Também estamos adicionando dois métodos para adição e remoção de módulo fora da árvore do Flutter:
Modular.bindModule
eModular.unbindModule
.Essa forma coloca módulos fora da árvore do Flutter, não participando dos eventos de dispose solicitado pelo ciclo de vida do
ModularApp
. Por tanto, essa prática deve ser usada com cuidado e o desenvolvedor deve ter a consciência de remover os módulos quando não precisar mais. Essa feature será útil para aplicações que precisão iniciar o sistema de injeção antes mesmo do próprio Flutter.Colocaremos warnings na documentação para evitar incongruências no código.
Remoção do AsyncBinds
Como teremos mais liberdade com os Binds, os AsyncBinds passam a ser desnecessários, visto que um módulo pode ser resolvido e adicionado ao sistema de injeção fora da inicialização comum no ModularApp.
Percebemos que o sistema do modular funciona melhor de forma síncrona, e vamos colocar na documentação uma forma melhor de trabalhar com dados que precisam ser resolvidos assincronamente.
Adições de classes e métodos:
AutoBind
-> Nova forma de registrar Binds sem a necessidade de pré-declaração de dependências (i);Modular.tryGet
-> retorna null se não encontrar alguma referência/instância.Modular.bindModule
-> adiciona um módulo em tempo de execução. (Esse módulo não participa da sessão de "dispose automático").Modular.unbindModule
-> remove um módulo;Modular.routerConfig
-> iniciar Navigator 2.0;As correções de issues serão listadas a baixo.
Checklist
fix:
,feat:
,docs:
etc).docs
and added dartdoc comments with///
.examples
.Breaking Change
Yes, this is a breaking change.
No, this is not a breaking change.
Remove AsyncBind class.
Remove constructors Bind() e Bind.scoped.
Remove method Modular.isModuleReady, Modular.getAsync, Modular.reassemble, Modular.releaseScopedBinds;
Related Issues
#649