203 votes

Passer des données à StatefulWidget et y accéder dans son état dans Flutter

J'ai 2 écrans dans mon application Flutter : une liste d'enregistrements et un écran pour créer et modifier des enregistrements.

Si je passe un objet au deuxième écran, cela signifie que je vais modifier cet élément et si je passe null, cela signifie que je crée un nouvel élément. L'écran d'édition est un widget Stateful et je ne sais pas comment utiliser cette approche. https://flutter.io/cookbook/navigation/passing-data/ pour mon cas.

class RecordPage extends StatefulWidget {
  final Record recordObject;

  RecordPage({Key key, @required this.recordObject}) : super(key: key);

  @override
  _RecordPageState createState() => new _RecordPageState();
}

class _RecordPageState extends State<RecordPage> {
  @override
  Widget build(BuildContext context) {
   //.....
  }
}

Comment puis-je accéder à recordObject à l'intérieur de _RecordPageState ?

2 votes

0 votes

comment utiliser la valeur de la variable 'recordObject' dans une fonction de la classe _RecordPageState ?

1 votes

334voto

dhuma1981 Points 378

Pour utiliser recordObject dans _RecordPageState, vous devez simplement écrire widget.objectname comme ci-dessous

class _RecordPageState extends State<RecordPage> {
  @override
  Widget build(BuildContext context) {
   .....
   widget.recordObject
   .....
  }
}

11 votes

Pour les novices de Flutter, n'oubliez pas de définir le widget comme "@override RecordPage get widget => super.widget ;".

29 votes

@hhk Pourquoi est-ce nécessaire ?

4 votes

Ne devrait-on pas recordObject faire partie de la State classe ? Logiquement, l'avoir dans StatefulWidget est incorrect (en termes de cohésion). Par ailleurs, tous les domaines de StatefulWidget doivent être immuables - que se passe-t-il si vous voulez modifier l'élément recordObject référence ?

51voto

Sanjayrajsinh Points 1098

Exemple complet


Vous n'avez pas besoin de passer des paramètres à State en utilisant son constructeur. Vous pouvez facilement y accéder en utilisant widget.myField .

class MyRecord extends StatefulWidget {
  final String recordName;
  const MyRecord(this.recordName);

  @override
  MyRecordState createState() => MyRecordState();
}

class MyRecordState extends State<MyRecord> {
  @override
  Widget build(BuildContext context) {
    return Text(widget.recordName); // Here you direct access using widget
  }
}

Transmettez vos données lorsque vous naviguez à l'écran :

 Navigator.of(context).push(MaterialPageRoute(builder: (context) => MyRecord("WonderWorld")));

0 votes

Cela a déjà été mentionné ici il y a plusieurs années. Veuillez lire les autres réponses avant d'écrire la vôtre.

0 votes

Et si je dois changer sa valeur ?

44voto

John Mcfetridge Points 589
class RecordPage extends StatefulWidget {
  final Record recordObject;

  RecordPage({Key key, @required this.recordObject}) : super(key: key);

  @override
  _RecordPageState createState() => new _RecordPageState(recordObject);
}

class _RecordPageState extends State<RecordPage> {
  Record  recordObject
 _RecordPageState(this. recordObject);  //constructor
  @override
  Widget build(BuildContext context) {.    //closure has access
   //.....
  }
}

1 votes

Veuillez expliquer pourquoi il s'agit d'un widget d'état.

1 votes

@atilkan car OP initial script est un StatefulWidget, il a juste ajouté quelques lignes pour répondre aux besoins.

4 votes

Je ne pense pas qu'avoir recordObject à la fois dans State et StatefulWidget est une très bonne idée (même si j'ai vu des tutoriels faisant exactement la même chose). L'approche consistant à accéder aux champs de StatefulWidget en utilisant widget domaine de State semble être une approche plus correcte (même si elle a ses propres problèmes).

5voto

Paresh Mangukiya Points 13942

Souvent, vous souhaitez non seulement naviguer vers un nouvel écran, mais aussi transmettre des données à cet écran. Par exemple, vous pouvez vouloir transmettre des informations sur l'élément qui a été touché.

Dans cet exemple, créez une liste de tâches à accomplir. Lorsque l'on touche à un todo, on accède à un nouvel écran (widget) qui affiche des informations sur l'enregistrement. Cette recette utilise les étapes suivantes :

  • Définir une classe RecordObject.
  • Créer un StatefulWidget . Nous l'appelons RecordsScreen (pour : afficher une liste d'enregistrements).
  • Créez un écran de détail qui peut afficher des informations sur un enregistrement.
  • Naviguez et transmettez les données à l'écran de détail.

Définir une classe RecordObject

class RecordsScreen extends StatefulWidget {
  List<RecordObject> records;
  RecordsScreen({Key key, @required this.records}) : super(key: key);
  @override
  _RecordsScreenState createState() => _RecordsScreenState();
}

class _RecordsScreenState extends State<RecordsScreen> {

  @override
  Widget build(BuildContext context) {
    widget.records = List<RecordObject>.generate(20,
          (i) => RecordObject(
        'Record $i',
        'A description of what needs to be done for Record $i',
      ),
    );
    return Scaffold(
      appBar: AppBar(
        title: Text('Records'),
      ),
      body: ListView.builder(
        itemCount:  widget.records.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text( widget.records[index].title),
            // When a user taps the ListTile, navigate to the DetailScreen.
            // Notice that you're not only creating a DetailScreen, you're
            // also passing the current todo through to it.
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => DetailScreen(recordObject:  widget.records[index]),
                ),
              );
            },
          );
        },
      ),
    );
  }

Créer un écran de détail - Le titre de l'écran contient le titre de l'enregistrement, et le corps de l'écran affiche la description.

class DetailScreen extends StatefulWidget {
  // Declare a field that holds the RecordObject.
  final RecordObject recordObject;

  // In the constructor, require a RecordObject.
  DetailScreen({Key key, @required this.recordObject}) : super(key: key);

  @override
  _DetailScreenState createState() => _DetailScreenState();
}

class _DetailScreenState extends State<DetailScreen> {
  @override
  Widget build(BuildContext context) {
    // Use the RecordObject to create the UI.
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.recordObject.title),
      ),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Text(widget.recordObject.description),
      ),
    );
  }
}

enter image description here

0 votes

Il s'agit d'un widget sans état, l'auteur de la question a spécifiquement demandé comment passer des variables à l'état d'un widget avec état.

0 votes

Mes excuses, maintenant cette réponse est dans statefulwidget.

1voto

Bilal Ali Points 1

Je dois revenir à n'importe quel écran des pages de la liste, mais lorsque je fais cela, la fonction onTap ne fonctionne plus et la navigation s'arrête.

class MyBar extends StatefulWidget {
  MyBar({this.pageNumber});
  final pageNumber;
  static const String id = 'mybar_screen';
  @override
  _MyBarState createState() => _MyBarState();
}

class _MyBarState extends State<MyBar> {
  final List pages = [
    NotificationScreen(),
    AppointmentScreen(),
    RequestBloodScreen(),
    ProfileScreen(),
  ];
  @override
  Widget build(BuildContext context) {
    var _selectedItemIndex = widget.pageNumber;
    return Scaffold(
        bottomNavigationBar: BottomNavigationBar(
          elevation: 0,
          backgroundColor: Colors.white,
          unselectedItemColor: Colors.grey.shade700,
          selectedItemColor: Color(kAppColor),
          selectedIconTheme: IconThemeData(color: Color(kAppColor)),
          currentIndex: _selectedItemIndex,
          type: BottomNavigationBarType.fixed,
          onTap: (int index) {
            setState(() {
              _selectedItemIndex = index;
            });
          },

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X