Flutterando / modular

A smart project structure
https://pub.dev/packages/flutter_modular
Other
1.31k stars 254 forks source link

UnregisteredBind in AppModule #973

Open jhonathanqz opened 3 weeks ago

jhonathanqz commented 3 weeks ago

Describe the bug A clear and concise description of what the bug is.

Environment Add your flutter doctor -v

[✓] Flutter (Channel stable, 3.24.3, on macOS 15.1 24B83 darwin-x64, locale pt-BR)
    • Flutter version 3.24.3 on channel stable at /Users/jhonathanqz/fvm/versions/3.24.3
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 2663184aa7 (7 weeks ago), 2024-09-11 16:27:48 -0500
    • Engine revision 36335019a8
    • Dart version 3.5.3
    • DevTools version 2.37.3

[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0-rc3)
    • Android SDK at /Users/jhonathanqz/Library/Android/sdk
    • Platform android-35, build-tools 35.0.0-rc3
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.10+0-17.0.10b1087.21-11572160)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 16.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 16B40
    • CocoaPods version 1.15.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2023.3)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.10+0-17.0.10b1087.21-11572160)

[✓] VS Code (version 1.95.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.92.0

[✓] Connected device (4 available)
    • iPhone de jhonathan queiroz (mobile) • 00008130-000064912291001C            • ios            • iOS 18.1 22B83
    • iPhone 16 Plus (mobile)              • 33CD0F9C-E97D-4C64-94BF-1200C31EDFCE • ios            • com.apple.CoreSimulator.SimRuntime.iOS-18-1 (simulator)
    • macOS (desktop)                      • macos                                • darwin-x64     • macOS 15.1 24B83 darwin-x64
    • Chrome (web)                         • chrome                               • web-javascript • Google Chrome 130.0.6723.70

[✓] Network resources
    • All expected network resources are available.

• No issues found!

Add your pubspec.yaml

version: 1.0.0+1

environment:
  sdk: ">=3.4.4 <4.0.0"

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^1.0.2
  animate_do: ^3.3.4
  cached_network_image: ^3.3.1
  camera: ^0.11.0+2
  device_info_plus: ^11.1.0
  dio: ^5.5.0+1
  dio_logger_request: ^1.0.3
  equatable: ^2.0.5
  flutter_cache_manager: ^3.3.0
  flutter_carousel_widget: ^3.1.0
  flutter_dotenv: ^5.1.0
  flutter_mobx: ^2.2.1+1
  flutter_modular: ^6.3.4
  google_mlkit_face_detection: ^0.12.0
  hive: ^2.2.3
  image: ^4.1.3
  internet_connection_checker_plus: ^2.5.2
  intl: ^0.19.0
  mask_text_input_formatter: ^2.1.0
  mobx: ^2.3.3+2
  path_provider: ^2.1.2
  permission_handler: ^11.3.1
  sqflite: ^2.3.3+1
  tflite_flutter: ^0.11.0
  #

  animated_face_detection:
    path: ../animated_face_detection

  flutter_localizations:
    sdk: flutter

dev_dependencies:
  build_runner: ^2.4.9
  json_serializable: ^6.7.1
  mobx_codegen: ^2.6.1
  flutter_test:
    sdk: flutter
  integration_test:
    sdk: flutter

  flutter_lints: ^4.0.0

flutter:
  uses-material-design: true

Add your Info.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSCameraUsageDescription</key>
<string>your usage description here</string>
<key>NSMicrophoneUsageDescription</key>
<string>your usage description here</string>
    <key>CFBundleDevelopmentRegion</key>
    <string>$(DEVELOPMENT_LANGUAGE)</string>
    <key>CFBundleDisplayName</key>
    <string>Realtime Face Recognition</string>
    <key>CFBundleExecutable</key>
    <string>$(EXECUTABLE_NAME)</string>
    <key>CFBundleIdentifier</key>
    <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundleName</key>
    <string>realtime_face_recognition</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleShortVersionString</key>
    <string>$(FLUTTER_BUILD_NAME)</string>
    <key>CFBundleSignature</key>
    <string>????</string>
    <key>CFBundleVersion</key>
    <string>$(FLUTTER_BUILD_NUMBER)</string>
    <key>LSRequiresIPhoneOS</key>
    <true/>
    <key>UILaunchStoryboardName</key>
    <string>LaunchScreen</string>
    <key>UIMainStoryboardFile</key>
    <string>Main</string>
    <key>UISupportedInterfaceOrientations</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
    <key>UISupportedInterfaceOrientations~ipad</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
        <string>UIInterfaceOrientationPortraitUpsideDown</string>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
    <key>CADisableMinimumFrameDurationOnPhone</key>
    <true/>
    <key>UIApplicationSupportsIndirectInputEvents</key>
    <true/>
</dict>
</plist>

Add your AppDelegate.swift

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

Add your MainActivity

package com.example.realtime_face_recognition

import io.flutter.embedding.android.FlutterActivity

class MainActivity: FlutterActivity() {
}

Add your AndroidManifest.xml Add your /app/res/values/strings.xml

To Reproduce Minha classe AppModule está criando uma instancia de GlobalStore que deveria ser GLOBAL para todos os módulos dentro do AppModule e isso não acontece.

class AppModule extends Module {
  @override
  List<Module> get imports => [
        PackagesModule(),
        LocalstorageModule(),
        SharedModule(),
      ];

  @override
  void binds(i) {
    i.add<INavigator>(AppNavigator.new);
    i.addSingleton<GlobalStore>(() => GlobalStore());
  }

  @override
  void routes(r) {
    r.module('/splash', module: SplashModule());
    r.module('/home', module: HomeModule());
    r.module('/settings', module: SettingsModule());
    r.wildcard(child: (context) => const PageNotFound());
  }

  @override
  // ignore: override_on_non_overriding_member
  Widget get bootstrap => const App();
}

Expected behavior A clear and concise description of what you expected to happen.

Screenshots image

eduardoflorence commented 3 weeks ago

Hi @jhonathanqz Try removing exportedBinds in AppModule

jhonathanqz commented 3 weeks ago

@eduardoflorence também não funciona

eduardoflorence commented 3 weeks ago

Você experimentou assim?

i.addSingleton<GlobalStore>(GlobalStore.new);
jhonathanqz commented 3 weeks ago

@eduardoflorence sim, mesma coisa.... segue imagem:

Se eu criar esse bind em um modulo a parte, exemplo CoreModule colocar no export e depois importar esse modulo CoreModule em todos os modulos que fazem uso da globalStore, ai funciona... mas nao é o correto. até a versao 5 do modular, está tudo certo.

image

eduardoflorence commented 3 weeks ago

ah sim, agora entendi. A versão 6.x do modular exige que você faça do jeito que comentou (CoreModule com export). Isso traz mais segurança de qual bind realmente você está usando em cada módulo, além de proteger contra importação de binds indevidos apenas por ser um submódulo na árvore. Por exemplo, você agora pode ter um bind de mesma interface em appmodule e moduleX com implementações diferentes e terá certeza que o que será usado será o do moduleX

jhonathanqz commented 3 weeks ago

@eduardoflorence Vai ter que ser conforme imagem abaixo entao? Minha globalStore está com o bind nesse sharedModule, em todos os módulos que usam a globalStore eu vou ter que fazer o import do SharedModule ? No caso esse GlobalStore é um singleton, eu vou ter a garantia que é sempre a mesma instancia? por que falando assim, nao me da muita segurança, parece que ele vai ser criado uma nova instancia para cada modulo que estiver importando o sharedModule.

image

eduardoflorence commented 3 weeks ago

@jhonathanqz esse foi um teste que fiz logo que lançou a versão 6.x, pois também fiquei preocupado e realmente será somente uma instância, desde que no SharedModule você instancie a GlobalStore com addSingleton. E sobre sua pergunta inicial, realmente é do jeito que mostrou na imagem. Eu uso assim em produção e está funcionando perfeito. Em todos os lugares que precisar do GlobalStore é só importar o SharedModule.