Flutter обращается к переменной класса State для StatefulWidget из другого класса

У меня есть класс StatefulWidget «FirstClass», который расширяет состояние «_FirstClassState». Из отдельного класса состояния, называемого «_SecondClassState», я пытаюсь получить доступ к значению переменной (называемой «счетчиком» в «_FirstClassState»).

Я нашел решение, но не уверен, что это лучшее решение проблемы. Я пробовал смотреть на другие похожие вопросы:

second_class.dart:

import 'package:brew_crew/question/first_class.dart';
import 'package:flutter/material.dart';

class SecondClass extends StatefulWidget {
  @override
  _SecondClassState createState() => _SecondClassState();
}

class _SecondClassState extends State<SecondClass> {
  final FirstClass firstClass = FirstClass();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("MyApp"),
        centerTitle: true,
      ),
      body: Column(
        children: <Widget>[
          firstClass, //Displays the button to increase 'counter'
          FlatButton(
              child: Text("Submit"),
              onPressed: () {
                print(firstClass
                    .getCounter()); //I need to get the value of 'counter' here to use elsewhere
              }),
        ],
      ),
    );
  }
}

first_class.dart

import 'package:flutter/material.dart';

class FirstClass extends StatefulWidget {
  final _FirstClassState firstClassState = _FirstClassState();

  @override
  _FirstClassState createState() => firstClassState;

  int getCounter() {
    return firstClassState.counter;
  }
}

class _FirstClassState extends State<FirstClass> {
  int counter = 0;

  //Increases counter by 1
  void _increaseCounter() {
    setState(() {
      counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    //A button which increases counter when clicked
    return FlatButton.icon(
      icon: Icon(Icons.add),
      label: Text("Counter: $counter"),
      onPressed: () {
        _increaseCounter();
      },
    );
  }
}

Как видите, в «FirstClass» я инициализирую новый экземпляр «_FirstClassState». Используя это в функции getCounter (), я могу получить значение счетчика.

Есть ли лучший способ (например, передовой опыт, меньше строк кода, более простой для понимания метод и т. Д.), Чем этот, для достижения того, что я пытаюсь сделать?


person Sidharth Ranjith    schedule 07.11.2020    source источник
comment
Как структурированы ваши FirstClass и SecondClass? Находится ли SecondClass ниже или выше FirstClass в дереве виджетов, или они являются братьями и сестрами?   -  person Ashutosh Singh    schedule 07.11.2020
comment
@AshutoshSingh Извините, я новичок во Flutter, поэтому извиняюсь, если это не ответ. Сначала я загружаю виджет «Второй класс», а затем виджет «Первый класс» загружается в виджет «Второй класс». Поэтому я думаю, что «SecondClass» будет родителем «FirstClass».   -  person Sidharth Ranjith    schedule 07.11.2020


Ответы (1)


Использование GlobalKey - определенно рекомендуемый подход, если вам абсолютно необходимо получить доступ к состоянию виджета извне. Однако в этом случае вам не следует использовать ни один из подходов.

_SecondClassState должен содержать counter, и вы должны передать его вместе с функцией increaseCounter в качестве параметров в FirstClass. Если вы хотите увеличить число, просто вызовите эту функцию.

Что-то в этом роде:

class SecondClass extends StatefulWidget {
  @override
  _SecondClassState createState() => _SecondClassState();
}

class _SecondClassState extends State<SecondClass> {
  int counter = 0;

  //Increases counter by 1
  void _increaseCounter() {
    setState(() {
      counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("MyApp"),
        centerTitle: true,
      ),
      body: Column(
        children: <Widget>[
          FirstClass(counter: counter, increaseCounter: _increaseCounter), //Displays the button to increase 'counter'
          FlatButton(
              child: Text("Submit"),
              onPressed: () {
                print(counter.toString()); //I need to get the value of 'counter' here to use elsewhere
              }),
        ],
      ),
    );
  }
}
class FirstClass extends StatefulWidget {
  final int counter;
  final Function increaseCounter;

  FirstClass({this.counter, this.increaseCounter});

  final _FirstClassState firstClassState = _FirstClassState();

  @override
  _FirstClassState createState() => firstClassState;
}

class _FirstClassState extends State<FirstClass> {
  @override
  Widget build(BuildContext context) {
    //A button which increases counter when clicked
    return FlatButton.icon(
      icon: Icon(Icons.add),
      label: Text("Counter: ${widget.counter}"),
      onPressed: () {
        widget.increaseCounter();
      },
    );
  }
}

person Riwen    schedule 07.11.2020
comment
Спасибо за ответ. Я пробовал реализовать это, но получаю следующую ошибку: «Вызов метода был вызван с нулевым значением. Получатель: null Пробовал вызвать: call () '. Функция «Увеличить счетчик ()» передается как «null» в конструкторе «FirstClass» (но значение «counter» передается правильно). Вы знаете, почему это могло быть? - person Sidharth Ranjith; 07.11.2020
comment
@SidharthRanjith Не уверен. Попробуйте перезапустить процесс отладки, приведенный выше код работает на моей стороне. - person Riwen; 07.11.2020
comment
обнаружил ошибку. Я передал «Увеличить счетчик ()» вместо «Увеличить счетчик» в качестве одного из параметров для «Первого класса». Спасибо за вашу помощь в этом. Не могли бы вы из интереса сообщить мне, почему это считается лучше, чем то слово, которое я использовал в вопросе? - person Sidharth Ranjith; 07.11.2020
comment
@SidharthRanjith А, тогда понятно, почему это не сработало. Что ж, в общем, данные текут вниз от родительских виджетов к дочерним. Если у вас нет очень веских причин для доступа к состоянию виджета извне, вам не следует этого делать, поскольку это антипаттерн. Вот хорошая статья о том, где следует управлять состоянием. - person Riwen; 08.11.2020