简体   繁体   中英

Force rebuild of a stateful child widget in flutter

Let's suppose that I have a Main screen (stateful widget) where there is a variable count as state. In this Main screen there is a button and another stateful widget (let's call this MyListWidget . MyListWidget initialize it's own widgets in the initState depending by the value of the count variable. Obviously if you change the value of count and call SetState , nothing will happen in MyListWidget because it create the values in the initState . How can I force the rebuilding of MyListWidget ? I know that in this example we can just move what we do in the initState in the build method. But in my real problem I can't move what I do in the initState in the build method.

Here's the complete code example:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key}) : super(key: key);

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

class _MyHomePageState extends State<MyHomePage> {
  int count = 5;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Row(
      children: [
        Expanded(
          child: MaterialButton(
            child: Text('Click me'),
            color: Colors.red,
            onPressed: () {
              setState(() {
                count++;
              });
            },
          ),
        ),
        MyListWidget(count),
      ],
    ));
  }
}

class MyListWidget extends StatefulWidget {
  final int count;

  const MyListWidget(this.count, {Key? key}) : super(key: key);

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

class _MyListWidgetState extends State<MyListWidget> {
  late List<int> displayList;

  @override
  void initState() {
    super.initState();
    displayList = List.generate(widget.count, (int index) => index);
  }

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: ListView.builder(
        itemBuilder: (BuildContext context, int index) => ListTile(
          title: Text(displayList[index].toString()),
        ),
        itemCount: displayList.length,
      ),
    );
  }
}

USE THIS:

class _MyHomePageState extends State<MyHomePage> {
  int count = 5;
  MyListWidget myListWidget = MyListWidget(5);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Row(
      children: [
        Expanded(
          child: MaterialButton(
            child: Text('Click me'),
            color: Colors.red,
            onPressed: () {
              setState(() {
                 count++;
                 myListWidget = MyListWidget(count);
               });
            },
          ),
        ),
        myListWidget,
      ],
    ));
  }
}

I don't think the accepted answer is accurate, Flutter will retain the state of MyListWidget because it is of the same type and in the same position in the widget tree as before.

Instead, force a widget rebuild by changing its key :

class _MyHomePageState extends State<MyHomePage> {
  int count = 5;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Row(
      children: [
        Expanded(
          child: MaterialButton(
            child: Text('Click me'),
            color: Colors.red,
            onPressed: () {
              setState(() {
                count++;
              });
            },
          ),
        ),
        MyListWidget(count, key: ValueKey(count)),
      ],
    ));
  }
}

Using a ValueKey in this example means the state will only be recreated if count is actually different.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM