J'ai une erreur avec Provider que j'arrive pas à régler

Bonjour, j’ai un soucis avec Provider, voici mon code

import 'package:flutter/material.dart';

import 'package:flutter/services.dart';

import 'package:provider/provider.dart';

import 'package:toast/toast.dart';

import 'package:date_format/date_format.dart';

import '../../models/whatsapp_model.dart';

import '../../controllers/whatsapp_controller.dart';

class LinkListBuilder extends StatelessWidget {

  @override

  Widget build(BuildContext context) {

    // il inque que l'erreur se trouve a se niveau

    List<WhatsappModel> _linksList =

        Provider.of<WhatsappController>(context).getList();

    final WhatsappController _provider =

        Provider.of<WhatsappController>(context);

    if (_linksList.isEmpty) {

      return Container(

        padding: EdgeInsets.all(20.0),

        alignment: Alignment.center,

        child: Text(

          "Vous n'avez pas encore créer de lien !",

          textAlign: TextAlign.center,

          style: TextStyle(

            color: Colors.orange[600],

            fontSize: 18.0,

          ),

        ),

      );

    }

    return ListView.builder(

      itemCount: _linksList.length,

      itemBuilder: (context, index) {

        final DateTime _dateString = DateTime.tryParse(_linksList[index].date);

        final String _dateFormated = _dateString != null

            ? formatDate(_dateString, [dd, ' ', M])

            : "Erreur";

        final String _dateFormated2 = _dateString != null

            ? formatDate(_dateString, [HH, ':', mm])

            : "Erreur";

        final String _dayFormated =

            _dateString != null ? formatDate(_dateString, [dd]) : "Erreur";

        bool today =

            DateTime.now().day.toString() == _dayFormated ? true : false;

        return Padding(

          padding: const EdgeInsets.only(

            bottom: 3.0,

            left: 8.0,

            right: 8.0,

          ),

          child: Dismissible(

            onDismissed: (direction) {

              if (direction == DismissDirection.endToStart) {

                Scaffold.of(context).showSnackBar(

                  _buildSanackBar(

                    content:

                        "Le challenge ${_linksList[index].number} a bien été validé",

                  ),

                );

                _provider.remove(index: index);

              }

              if (direction == DismissDirection.startToEnd) {

                Scaffold.of(context).showSnackBar(

                  _buildSanackBar(

                    content:

                        "Le challenge ${_linksList[index].number} à bien été suprimé",

                  ),

                );

                _provider.remove(index: index);

              }

            },

            confirmDismiss: (direction) async {

              if (direction == DismissDirection.startToEnd) {

                final bool resultat = await showDialog<bool>(

                    context: context,

                    builder: (context) {

                      return AlertDialog(

                        title: Text("Confimation",

                            style: TextStyle(

                              color: Colors.blue,

                            )),

                        content: Text(

                            "Êtes-vous sûr de vouloir suprimer le challenge"),

                        actions: [

                          FlatButton(

                            onPressed: () {

                              Navigator.pop(context, true);

                            },

                            child: Text("Oui"),

                          ),

                          FlatButton(

                            onPressed: () {

                              Navigator.pop(context, false);

                            },

                            child: Text("Non"),

                          )

                        ],

                      );

                    });

                return resultat;

              }

              // on ajouter une confirmation pour l'autre sens.

              return true;

            },

            background: Container(

              alignment: Alignment.centerLeft,

              color: Colors.red,

              child: Icon(

                Icons.delete,

                size: 50.0,

                color: Colors.white,

              ),

            ),

            // secondaryBackground: Container(

            //   padding: EdgeInsets.only(right: 10.0),

            //   alignment: Alignment.centerRight,

            //   color: Colors.green,

            //   child: Icon(

            //     Icons.check,

            //     size: 50.0,

            //     color: Colors.white,

            //   ),

            // ),

            key: Key(UniqueKey().toString()),

            child: Container(

              color: Colors.white,

              child: Row(

                children: [

                  Column(

                    children: [

                      Text("Numéro: ${_linksList[index].number}"),

                      Text("Message:"),

                      Text("${_linksList[index].message}"),

                      Text(today ? _dateFormated2 : _dateFormated),

                    ],

                  ),

                  IconButton(

                    icon: Icon(

                      Icons.content_copy,

                      color: Colors.grey,

                    ),

                    onPressed: () {

                      Clipboard.setData(

                          ClipboardData(text: _linksList[index].date));

                      Toast.show("Lien copié", context,

                          duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);

                    },

                  ),

                ],

              ),

            ),

          ),

        );

      },

    );

  }

  SnackBar _buildSanackBar({@required String content}) {

    return SnackBar(

      content: Text(

        content,

        textAlign: TextAlign.center,

      ),

    );

  }

}

ici l’erreur qu’il m’affiche, il indique la ligne 16

bjr, je ne comprends pas bien ce que tu veux faire. Mais une question: as tu déclaré ton provider dans la classe main? comme etant un ChangeNotifierProvider?

Oui je l’ai fait, voici le code:

import 'package:flutter/material.dart';

import 'package:provider/provider.dart';

import 'screens/splash_screen.dart';

import 'controllers/whatsapp_controller.dart';

void main() {

  runApp(WhatsAppLink());

}

class WhatsAppLink extends StatelessWidget {

  @override

  Widget build(BuildContext context) {

    return MaterialApp(

      title: 'WhatsApp Link Generator',

      debugShowCheckedModeBanner: false,

      home: ChangeNotifierProvider<WhatsappController>(

        create: (context) => WhatsappController(),

        child: SplashScreen(),

      ),

    );

  }

}

apparemment c’est parce que j’ai mit le splash screen comme enfant. Mais comment faire passer le provider

faut dire que j’ai vraiment besoins de régler se problème, car j’ai rencontré le même problème sur un autre screen.

Peut-être il y a t’il plusieurs WhatsappController en provider, pour ton code essaye déjà de faire un seul appel de contrôleur par Stateless, par exemple :

Avant :

List<WhatsappModel> _linksList =

    Provider.of<WhatsappController>(context).getList();

final WhatsappController _provider =

    Provider.of<WhatsappController>(context);

Après :

final WhatsappController _provider =

    Provider.of<WhatsappController>(context);

List<WhatsappModel> _linksList = _provider.getList();

j’ai essayé et cela ne passe pas. Je me dit que je n’utilise pas le provider correctement, voici l’architecture et mon code
L’ARCHITECTURE:
main ==> SplashScreen ==> HomeScreen qui comprend LinkListBuilder ( ici s’affiche la liste et avec le bouton on va sur) ==> GenerateScreen

LE CODE:

le main

import 'package:flutter/material.dart';

import 'package:provider/provider.dart';

import 'screens/splash_screen.dart';

import 'controllers/whatsapp_controller.dart';

void main() {

  runApp(WhatsAppLink());

}

class WhatsAppLink extends StatelessWidget {

  @override

  Widget build(BuildContext context) {

    return MaterialApp(

      title: 'WhatsApp Link Generator',

      debugShowCheckedModeBanner: false,

      home: ChangeNotifierProvider<WhatsappController>(

        create: (context) => WhatsappController(),

        child: SplashScreen(),

      ),

    );

  }

}

le SplashScreen

import 'package:flutter/material.dart';

import 'home_screen.dart';

class SplashScreen extends StatefulWidget {

  @override

  _SplashScreenState createState() => _SplashScreenState();

}

class _SplashScreenState extends State<SplashScreen> {

  @override

  void initState() {

    super.initState();

    Future.delayed(

      Duration(seconds: 3),

      () {

        Navigator.pushReplacement(

            context, MaterialPageRoute(builder: (_) => HomeScreen()));

      },

    );

  }

  @override

  Widget build(BuildContext context) {

    final size = MediaQuery.of(context).size;

    return Scaffold(

      body: Center(

          child: Container(

        color: Colors.green,

        height: size.height,

        width: size.width,

        child: Container(

          child: Image.asset("assets/logo_t.png"),

        ),

      )),

    );

  }

}

le HomeScreen

import 'package:flutter/material.dart';

import 'components/build_link_list.dart';

import 'generate_screen.dart';

class HomeScreen extends StatelessWidget {

  final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();

  @override

  Widget build(BuildContext context) {

    return Scaffold(

      key: scaffoldKey,

      appBar: AppBar(

        title: Text(" Link whatsapp"),

      ),

      body: LinkListBuilder(),

      floatingActionButton: FloatingActionButton(

        child: Icon(

          Icons.add,

          color: Colors.green,

          size: 50.0,

        ),

        backgroundColor: Colors.white,

        onPressed: () {

          Navigator.push(context, MaterialPageRoute(builder: (context)=>GenerateScreen()));

        },

      ),

    );

  }

}

LinkListBuilder

import 'package:flutter/material.dart';

import 'package:flutter/services.dart';

import 'package:provider/provider.dart';

import 'package:toast/toast.dart';

import 'package:date_format/date_format.dart';

import '../../models/whatsapp_model.dart';

import '../../controllers/whatsapp_controller.dart';

class LinkListBuilder extends StatelessWidget {

  @override

  Widget build(BuildContext context) {

    // il inque que l'erreur se trouve a se niveau

    final WhatsappController _provider =

        Provider.of<WhatsappController>(context);

    List<WhatsappModel> _linksList = _provider.getList();

    if (_linksList.isEmpty) {

      return Container(

        padding: EdgeInsets.all(20.0),

        alignment: Alignment.center,

        child: Text(

          "Vous n'avez pas encore créer de lien !",

          textAlign: TextAlign.center,

          style: TextStyle(

            color: Colors.orange[600],

            fontSize: 18.0,

          ),

        ),

      );

    }

    return ListView.builder(

      itemCount: _linksList.length,

      itemBuilder: (context, index) {

        final DateTime _dateString = DateTime.tryParse(_linksList[index].date);

        final String _dateFormated = _dateString != null

            ? formatDate(_dateString, [dd, ' ', M])

            : "Erreur";

        final String _dateFormated2 = _dateString != null

            ? formatDate(_dateString, [HH, ':', mm])

            : "Erreur";

        final String _dayFormated =

            _dateString != null ? formatDate(_dateString, [dd]) : "Erreur";

        bool today =

            DateTime.now().day.toString() == _dayFormated ? true : false;

        return Padding(

          padding: const EdgeInsets.only(

            bottom: 3.0,

            left: 8.0,

            right: 8.0,

          ),

          child: Dismissible(

            onDismissed: (direction) {

              if (direction == DismissDirection.endToStart) {

                Scaffold.of(context).showSnackBar(

                  _buildSanackBar(

                    content:

                        "Le challenge ${_linksList[index].number} a bien été validé",

                  ),

                );

                _provider.remove(index: index);

              }

              if (direction == DismissDirection.startToEnd) {

                Scaffold.of(context).showSnackBar(

                  _buildSanackBar(

                    content:

                        "Le challenge ${_linksList[index].number} à bien été suprimé",

                  ),

                );

                _provider.remove(index: index);

              }

            },

            confirmDismiss: (direction) async {

              if (direction == DismissDirection.startToEnd) {

                final bool resultat = await showDialog<bool>(

                    context: context,

                    builder: (context) {

                      return AlertDialog(

                        title: Text("Confimation",

                            style: TextStyle(

                              color: Colors.blue,

                            )),

                        content: Text(

                            "Êtes-vous sûr de vouloir suprimer le challenge"),

                        actions: [

                          FlatButton(

                            onPressed: () {

                              Navigator.pop(context, true);

                            },

                            child: Text("Oui"),

                          ),

                          FlatButton(

                            onPressed: () {

                              Navigator.pop(context, false);

                            },

                            child: Text("Non"),

                          )

                        ],

                      );

                    });

                return resultat;

              }

              // on ajouter une confirmation pour l'autre sens.

              return true;

            },

            background: Container(

              alignment: Alignment.centerLeft,

              color: Colors.red,

              child: Icon(

                Icons.delete,

                size: 50.0,

                color: Colors.white,

              ),

            ),

            key: Key(UniqueKey().toString()),

            child: Container(

              color: Colors.white,

              child: Row(

                children: [

                  Column(

                    children: [

                      Text("Numéro: ${_linksList[index].number}"),

                      Text("Message:"),

                      Text("${_linksList[index].message}"),

                      Text(today ? _dateFormated2 : _dateFormated),

                    ],

                  ),

                  IconButton(

                    icon: Icon(

                      Icons.content_copy,

                      color: Colors.grey,

                    ),

                    onPressed: () {

                      Clipboard.setData(

                          ClipboardData(text: _linksList[index].date));

                      Toast.show("Lien copié", context,

                          duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);

                    },

                  ),

                ],

              ),

            ),

          ),

        );

      },

    );

  }

  SnackBar _buildSanackBar({@required String content}) {

    return SnackBar(

      content: Text(

        content,

        textAlign: TextAlign.center,

      ),

    );

  }

}

GenerateScreen

import 'package:flutter/material.dart';

import 'package:provider/provider.dart';

import 'package:country_code_picker/country_code_picker.dart';

import '../controllers/whatsapp_controller.dart';

class GenerateScreen extends StatefulWidget {

  @override

  _GenerateScreenState createState() => _GenerateScreenState();

}

class _GenerateScreenState extends State<GenerateScreen> {

  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  String _code = "";

  String _message = "";

  String _number = "";

  _onCountryChange(CountryCode countryCode) {

    print("New Country selected: " + countryCode.toString());

    setState(() {

      _code = countryCode.toString();

    });

  }

  @override

  Widget build(BuildContext context) {

    final WhatsappController _provider =

        Provider.of<WhatsappController>(context);

    return Scaffold(

      appBar: AppBar(

        title: Text("Link Generator"),

      ),

      body: SafeArea(

        child: Form(

          key: _formKey,

          child: Column(

            children: [

              Row(

                children: [

                  Flexible(

                    child: CountryCodePicker(

                      onChanged: _onCountryChange,

                      initialSelection: 'CI',

                      favorite: ['+225'],

                      enabled: true,

                      showCountryOnly: false,

                      showOnlyCountryWhenClosed: false,

                      alignLeft: true,

                      textStyle: TextStyle(

                        fontSize: 16.0,

                      ),

                    ),

                  ),

                  Flexible(

                    child: TextFormField(

                      keyboardType: TextInputType.number,

                      maxLength: 14,

                      validator: (value) {

                        return null;

                      },

                      onSaved: (value) {

                        _number = value;

                      },

                      decoration: InputDecoration(

                        errorBorder: OutlineInputBorder(

                            borderSide: BorderSide(

                                width: 2.0, color: Colors.redAccent[700]),

                            borderRadius: BorderRadius.circular(32.0)),

                        errorStyle: TextStyle(color: Colors.redAccent[700]),

                        errorMaxLines: 2,

                        contentPadding: EdgeInsets.symmetric(

                          horizontal: 20,

                          vertical: 10.0,

                        ),

                        hintText: "hintText",

                        hintStyle: TextStyle(color: Colors.white38),

                        border: OutlineInputBorder(

                          borderRadius: BorderRadius.circular(32.0),

                        ),

                        enabledBorder: OutlineInputBorder(

                          borderSide: BorderSide(

                            width: 1.0,

                            color: Colors.lightBlueAccent,

                          ),

                          borderRadius: BorderRadius.circular(32.0),

                        ),

                        focusedBorder: OutlineInputBorder(

                          borderSide: BorderSide(

                            width: 2.5,

                            color: Colors.lightBlueAccent,

                          ),

                          borderRadius: BorderRadius.circular(32.0),

                        ),

                      ),

                    ),

                  )

                ],

              ),

              TextFormField(

                keyboardType: TextInputType.text,

                maxLines: 3,

                maxLength: 140,

                style: TextStyle(

                  fontSize: 16.0,

                ),

                onSaved: (value) {

                  setState(() {

                    _message = value;

                  });

                },

              ),

              Text("salut"),

              FlatButton(

                color: Colors.green,

                child: Text(

                  "Evoyer",

                  style: TextStyle(color: Colors.white),

                ),

                onPressed: () async {

                  if (_formKey.currentState.validate()) {

                  print("Lien généré");

                  _formKey.currentState.save();

                  String _link =  _provider.linkBuilder(

                    code: _code,

                    phone: _number,

                    message: _message,

                  );

                  // await _provider.launchURL(link: _link);

                  }

                },

              ),

            ],

          ),

        ),

      ),

    );

  }

}

As-tu le code sur un repo ? Le mieux c’est que l’on teste ton code pour voir.

1 J'aime

oui j’ai le projet sur GitLab, voici le lien https://gitlab.com/bongouade/whatsapp-link-generator sur la branche develop

bonjour, est-ce que tu as pu récupéré le code ?

Oui, c’est un bug assez compliqué à trouver. Le problème vient du placement du Provider dans ton code :

return MaterialApp(

      title: 'WhatsApp Link Generator',

      debugShowCheckedModeBanner: false,

      home: ChangeNotifierProvider<WhatsappController>(

        create: (context) => WhatsappController(),

        child: SplashScreen(),

      ),

Il passe donc ton provider correctement dans SplashScreen, jusqu’ici aucun problème tu as accès au provider tant que tu n’utilise pas le widget Navigator.

Lorsque tu utilise Navigator, Flutter va chercher les informations concernant ta route directement dans ton MaterialApp, or ton provider est fixé uniquement dans ton paramètre home, tu te retrouve donc sans provider.

Pour donner accès à toute ton application au provider, tu dois monter d’un niveau ton provider pour qu’il wrap ton MaterialApp.

1 J'aime

Ha ok je comprends, vraiment merci. Je vais prendre pour habitude de mettre mon MatterialApp dans le provider pour ne plus rencontré ce problème à l’avenir.