Как перерисовать StatefulWidget

В приведенном ниже примере, поскольку MyStatefulWidget имеет состояние, не имеет значения, вызывается ли setState на _MyAppState, потому что оно не будет перерисовано.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _MyAppState();
  }
}

class _MyAppState extends State<MyApp> {
  int value = 0;
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('App Example')),
        body: Row(children:[
          MyStatefulWidget(title: value.toString()), 
          RaisedButton(
            textColor: Colors.white,
            color: Colors.blue,
            onPressed: (){setState(() { value+=1; });},
            child: new Text("Add"),
          )
        ]),
      ),
    );
  }
}

class MyStatefulWidget extends StatefulWidget {
  MyStatefulWidget({Key key, this.title}):super(key: key);
  final String title;
  
  @override
  State<StatefulWidget> createState() {
    return _MyStatefulWidgetState();
  }
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  String title;
   @override
  void initState() {
    super.initState();
    if (widget.title!=null) {
      title = widget.title;
    } else {
      title = "";
    }
  }
  int value = 0;
  @override
  Widget build(BuildContext context) {
    return Text(title);
  }
}

Если бы я использовал StatelessWidget, он был бы перерисован, но это всего лишь пример, бывают случаи, когда мне нужно перерисовать StatefulWidget, когда вызывается setState.

Одним из вариантов было бы дать ему имя и построить его из setState, но мне нужно, чтобы он рисовался в том месте, где он рисуется прямо сейчас.

Дартпад: https://dartpad.dev/968be8755d5deab1ca5c8c84a993eafc

Вопрос не ясен. Ответ @bluenile правильный, но похоже, что вы хотите добиться чего-то другого, чем то, о чем вы просите.

spkersten 27.12.2020 11:13

отредактируйте вопрос, чтобы было очень ясно о результате и о том, что было испробовано до сих пор

Yadu 29.12.2020 05:27
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
2
293
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вы можете напрямую использовать widget.title в текстовом виджете для обновления счетчика на экране. Пожалуйста, смотрите код ниже:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _MyAppState();
  }
}

class _MyAppState extends State<MyApp> {
  void changeVal(int val) {
    setState(() {
      value = val;
    });
  }

  int value = 0;
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('App Example')),
        body: Row(children: [
          MyStatefulWidget(
              title: value.toString(),
              groupValue: value % 10,
              chnageVal: changeVal),
          RaisedButton(
            textColor: Colors.white,
            color: Colors.blue,
            onPressed: () {
              setState(() {
                value += 1;
              });
            },
            child: const Text("Add"),
          )
        ]),
      ),
    );
  }
}

class MyStatefulWidget extends StatefulWidget {
  const MyStatefulWidget({Key key, this.title, this.groupValue, this.chnageVal})
      : super(key: key);
  final String title;
  final int groupValue;
  final Function(int) chnageVal;

  @override
  State<StatefulWidget> createState() {
    return _MyStatefulWidgetState();
  }
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  //String title;
  // @override
  // void initState() {
  // super.initState();
  // if (widget.title!=null) {
  //   title = widget.title;
  // } else {
  //  title = "";
  // }
  // }
  //int value = 0;

  List<int> numbers = List.generate(10, (index) => index);
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 120,
      child: Column(children: [
        Text(widget.title),
        ...numbers
            .map((number) => RadioListTile<int>(
                  title: Text('$number'),
                  value: number,
                  groupValue: widget.groupValue,
                  onChanged: (val) {
                    widget.chnageVal(val);
                  },
                ))
            .toList()
      ]),
    );
  }
}

Это был просто пример. Предположим, что вместо текста MyStatefulWidget была радиогруппой. Сам MyStatefulWidget может изменить состояние радиогруппы, но я также хочу иметь возможность установить радиогруппу из родительского

Gatonito 24.12.2020 19:08

Я обновил код. Я добавил группу Radio из 10 RadioListTile со значением от 0 до 9. Теперь каждый раз, когда вы нажимаете кнопку Add, виджет Text будет обновляться на value, как и раньше. Однако в зависимости от последней цифры value группа радио также будет обновлена.

bluenile 24.12.2020 21:18

Основная проблема в том, что вы все еще читаете widget.groupValue, я не могу этого сделать, потому что виджет радио (MyStatefulWidget в вашем случае) должен иметь возможность изменять выбранный переключатель при нажатии на него. Поэтому мы не можем использовать константу widget.groupVale.

Gatonito 27.12.2020 01:46

Я открыл награду, пожалуйста, посмотрите

Gatonito 27.12.2020 01:47

Обновлен код, теперь вы можете щелкнуть радиокнопку, и значение радиокнопки станет значением текста. Таким образом, значение передается обратно.

bluenile 27.12.2020 02:00

Просто предоставьте уникальный ключ при вызове MyStatefulWidget, как MyStatefulWidget(key: UniqueKey(), title: value.toString()),.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _MyAppState();
  }
}

class _MyAppState extends State<MyApp> {
  int value = 0;
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('App Example')),
        body: Row(children: [
          MyStatefulWidget(key: UniqueKey(), title: value.toString()),
          RaisedButton(
            textColor: Colors.white,
            color: Colors.blue,
            onPressed: () {
              setState(() {
                value += 1;
              });
            },
            child: new Text("Add"),
          )
        ]),
      ),
    );
  }
}

class MyStatefulWidget extends StatefulWidget {
  MyStatefulWidget({Key key, this.title}) : super(key: key);
  final String title;

  @override
  State<StatefulWidget> createState() {
    return _MyStatefulWidgetState();
  }
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  String title;
  @override
  void initState() {
    super.initState();
    if (widget.title != null) {
      title = widget.title;
    } else {
      title = "";
    }
  }

  int value = 0;
  @override
  Widget build(BuildContext context) {
    return Text(title);
  }
}

Чтобы узнать больше о ключе, ознакомьтесь с этой статьей.

Я рекомендую использовать Stream, лучшую производительность и не так сложно использовать для частичного обновления пользовательского интерфейса.

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatefulWidget {
      @override
      State<StatefulWidget> createState() {
        return _MyAppState();
      }
    }
    
    class _MyAppState extends State<MyApp> {
StreamController<int> _streamController = StreamController();
      int value = 0;

  @override
  void dispose() {
    _streamController.close();
    super.dispose();
  }

      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: 
StreamBuilder<int>(
        stream: _streamController.stream,
        initialData: value,
        builder:
            (BuildContext context, AsyncSnapshot<int> snapshot) {
return Scaffold(
            appBar: AppBar(title: Text('App Example')),
            body: Row(children:[
              MyStatefulWidget(title: value.toString()), 
              RaisedButton(
                textColor: Colors.white,
                color: Colors.blue,
                onPressed: (){_streamController.sink.add(value++);},
                child: new Text("Add"),
              )
            ]),
          );},),
        );
      }
    }
    
    class MyStatefulWidget extends StatefulWidget {
      MyStatefulWidget({Key key, this.title}):super(key: key);
      final String title;
      
      @override
      State<StatefulWidget> createState() {
        return _MyStatefulWidgetState();
      }
    }
    
    class _MyStatefulWidgetState extends State<MyStatefulWidget> {
      String title;
       @override
      void initState() {
        super.initState();
        if (widget.title!=null) {
          title = widget.title;
        } else {
          title = "";
        }
      }
      int value = 0;
      @override
      Widget build(BuildContext context) {
        return Text(title);
      }
    }

Другие вопросы по теме