Как вызвать функцию в виджете с отслеживанием состояния из другого виджета с отслеживанием состояния?

Здравствуйте, я хочу вызвать функцию, которая находится внутри StatefulWidget класса formCliente, чтобы очистить контроллеры. Но я хочу получить к ней доступ через кнопку, которая находится внутри StatefulWidget класса formFinanceiro. Помоги мне, пожалуйста! Благодарю.

      class _CadastrarClienteState extends State<CadastrarCliente>
with TickerProviderStateMixin {     
    body: Form(
      key: formkey,
      child: TabBarView(
        physics: physics, //NeverScrollableScrollPhysics()
        controller: _tabController,
        children: [
          FormCliente(),
          FormDocumento(),
          FormVeiculo(),
          FormContrato(),
          FutureBuilder(
              future: getTrabalhaComCota(),
              builder: (context, snapshot) {
                if (snapshot.hasData && !snapshot.hasError) {
                  //   print(' chamada cota:${snapshot.data}');
                  return FormFinanceiro(
                      itemsCota: snapshot.data, formKey: formkey);
                } else {
                  return Center(
                    child: CircularProgressIndicator(),
                  );
                }
              }),
        ],
      ),
    ),

} ]


person Marcelo Cajaiba    schedule 08.11.2020    source источник


Ответы (2)


Вы можете использовать Streams, чтобы добиться того же, см. Код ниже:

import 'package:flutter/material.dart';
import 'dart:async';

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(title: Text("Demo")),
        body: MyApps(),
      ),
    );
  }
}

class MyApps extends StatefulWidget {
  @override
  _MyAppsState createState() => _MyAppsState();
}

class _MyAppsState extends State<MyApps> {
  final changeNotifier = new StreamController.broadcast();

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

  buttonClicked() => changeNotifier.sink.add(null);

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        FormCliente(
          shouldTriggerChange: changeNotifier.stream,
        ),
        FormFinanceiro(buttonClicked: buttonClicked),
      ],
    );
  }
}

class FormCliente extends StatefulWidget {
  final Stream shouldTriggerChange;

  FormCliente({this.shouldTriggerChange});

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

class _FormClienteState extends State<FormCliente> {
  StreamSubscription streamSubscription;

  @override
  initState() {
    super.initState();
    if (widget.shouldTriggerChange != null) {
      streamSubscription =
          widget.shouldTriggerChange.listen((_) => clearYourFormMethod());
    }
  }

  @override
  didUpdateWidget(FormCliente old) {
    super.didUpdateWidget(old);
    if (widget.shouldTriggerChange != old.shouldTriggerChange) {
      streamSubscription.cancel();
      streamSubscription =
          widget.shouldTriggerChange.listen((_) => clearYourFormMethod());
    }
  }

  @override
  dispose() {
    super.dispose();
    streamSubscription.cancel();
  }

  void clearYourFormMethod() {
    print('Please clear your form here');
  }

  @override
  Widget build(BuildContext context) {
    return Text("FormCliente");
  }
}

class FormFinanceiro extends StatefulWidget {
  final Function buttonClicked;

  FormFinanceiro({this.buttonClicked});

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

class _FormFinanceiroState extends State<FormFinanceiro> {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        RaisedButton(
          child: new Text("FormFinanceiro"),
          onPressed: widget.buttonClicked,
        )
      ],
    );
  }
}
person bluenile    schedule 08.11.2020
comment
Могу ли я использовать тот же метод для классов пыльников? - person Marcelo Cajaiba; 09.11.2020
comment
Да, вы можете использовать тот же метод для другого класса - person bluenile; 09.11.2020
comment
Bluenile Я не понял, зачем вы использовали этот код? didUpdateWidget (старый FormCliente) {super.didUpdateWidget (старый); если (widget.shouldTriggerChange! = old.shouldTriggerChange) {streamSubscription.cancel (); streamSubscription = widget.shouldTriggerChange.listen ((_) = ›clearYourFormMethod ()); }} - person Marcelo Cajaiba; 09.11.2020
comment
Для этого вам необходимо понимать жизненный цикл виджетов. См. api.flutter.dev/flutter/widgets/State/didUpdateWidget.html. Если метод сборки State зависит от объекта, который может сам изменять состояние, например, ChangeNotifier или Stream, или какого-либо другого объекта, на который можно подписаться для получения уведомлений, тогда обязательно подпишитесь и отмените подписку должным образом в initState, didUpdateWidget и удалите : - person bluenile; 09.11.2020
comment
В initState подпишитесь на объект. В didUpdateWidget отмените подписку на старый объект и подпишитесь на новый, если обновленная конфигурация виджета требует замены объекта. В утилизации отказаться от подписки на объект. - person bluenile; 09.11.2020
comment
Таким образом, код просто отписывается от старого объекта и подписывается на новый из обновлений виджета. - person bluenile; 09.11.2020

Вам нужно поднять state вверх:

  1. Создайте контроллер в _CadastrarClienteState классе.
  2. Создать обратный вызов в _CadastrarClienteState
  3. Передайте контроллер дочернему элементу FormFinanceiro.
  4. Передайте обратный вызов дочернему элементу FormCliente.
  5. Теперь измените функцию onbuttonpressed в FormCliente так, чтобы функция обратного вызова вызывалась при нажатии кнопки.
  6. Наконец, в методе обратного вызова, представленном в _CadastrarClienteState, очистите значения с помощью контроллеров.
person Joy Terence    schedule 08.11.2020
comment
спасибо Джой Теренс очень хорошо! но есть много полей для прохода, это будет сложно - person Marcelo Cajaiba; 09.11.2020