À quel endroit initialiser les dépendances du viewmodel?

Bonjour à tous,

J’essaye de mettre en pratique toute les connaissances que j’engrange au fur et à mesure

Ma situation est la suivante: je souhaite pratiquer l’injection de dépendance avec Provider, tout en respectant les principes de séparation en clean archi

Voici le main.dart

 @override
  Widget build(BuildContext context) {
    return CupertinoApp(
        home: CupertinoPageScaffold(
            child: MultiProvider(
                  provider: [
                  Provider<SectionsService>(create: (_) => SectionsService(HTTPClient())),
                  ProxyProvider<SectionsService, SectionsRepository>(
          update: (_, service, __) => SectionsRepository(service)),
                  ProxyProvider<SectionsRepository, SectionsUseCase>(
          update: (_, repository, __) => SectionsUseCase(repository)),
                   ProxyProvider<SectionsUseCase, SectionsViewModel>(
          update: (_, sectionsUseCase, __) =>
              SectionsViewModel(sectionsUseCase))]

)

ici on a le sections_viewmodel.dart

class SectionsViewModel extends ChangeNotifier {
  final SectionsUseCase _sectionsUseCase;

  SectionsViewModel(this._sectionsUseCase);
}

et pour finir, voici le sections_view.dart:

class SectionsView extends StatefulWidget {
 @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
        create: (context) => SectionsViewModel(
            Provider.of<SectionsUseCase>(context, listen: false)),
        child: Consumer<SectionsViewModel>(
                builder: (context, viewModel, child) {
              return Center(child: Text(viewModel.value)
   })));}
}

sauf que dans mon sections_view.dart, je fais appel au use case, or la view ne doit pas être au courant d’autre chose que du viewmodel, donc comment créer les dépendances du viewmodel en dehors de la view ?

merci pour votre aide

Hello @anis,

Je ne connais pas bien Provider et je ne suis donc pas certain de pouvoir te répondre correctement.
Mais en effet, ta vue ne doit connaitre qu’un viewmodel qui doit respecter une interface.
Dans cette interface, tu vas trouver toutes les données nécessaires à l’affichage et toutes les fonctions qui seront déclenchées par l’utilisateur. Voici un exemple :

abstract class IProfilViewModel extends ChangeNotifier {
// Les achats à afficher sur la vue
  List<Purchase> get purchase;
// Les actions utilisateurs à fournir au viewmodel
  void onProductTouched({required String productId});
  void onBottomNavBarTouched({required int index});
}

La vue ne requiert qu’en paramètre son viewmodel :

class ProfilView extends StatefulWidget {
  final IProfilViewModel viewmodel;
  const ProfilView({super.key, required this.viewmodel});

Les widgets peuvent accéder aux données et aux fonctions :

Text(viewmodel.purchase[index].title));
onTap: () => viewmodel.onProductTouched(
                          productId: viewmodel.purchase[index].id),

Je pense que c’est le model Provider qui t’impose cette écriture et qui dégouline dans l’ensemble de tes classes. Du coup, pas très clean architecture …

Pourquoi utilises-tu Provider ? C’est imposé par ton projet ?