вызов метода в одном виджете с контролем состояния из другого виджета с контролем состояния - Flutter - PullRequest
0 голосов
/ 25 июня 2018

У меня есть проект флаттера, над которым я работаю, я не могу поместить весь код, потому что он содержит более 500 строк кода, поэтому я постараюсь задать свой вопрос так же просто, как я использую imp.раздел кода.

У меня есть виджет с состоянием и некоторые функции внутри этого виджета с состоянием в классе, который расширяет, расширяет State<MusicPlayer>

файл lib\main.dart

просто возьмите простую функциюкак

class MyAppState extends State<MyApp>{
...
void printSample (){
  print("Sample text");
}
...

эта функция находится внутри виджета с контролем состояния внутри основного класса.

есть еще один файл lib\MyApplication.dart

этот файл также содержит виджет с сохранением состояния, могу ли я что-то сделать, чтобы я мог вызвать функцию printSample() здесь ..

class MyApplicationState extends State<MyApplication>{
...
@override
  Widget build(BuildContext context) {
    return new FlatButton(
      child: new Text("Print Sample Text"),
      onPressed :(){
       // i want to cal the function here how is it possible to call the 
       // function 
       // printSample()  from here??  
      }
    );
  }
...
}

Ответы [ 4 ]

0 голосов
/ 27 июля 2019

Вы можете попробовать, он вызовет метод, определенный в Page2 (StatefulWidget) из Page1 (StatefulWidget) виджета.

class Page1 extends StatefulWidget {
  @override
  _Page1State createState() => _Page1State();
}

class _Page1State extends State<Page1> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: RaisedButton(
          child: Text("Call page 2 method"),
          onPressed: () => Page2().method(),
        ),
      ),
    );
  }
}

class Page2 extends StatefulWidget {
  method() => createState().methodInPage2();

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

class _Page2State extends State<Page2> {
  methodInPage2() => print("method in page 2");

  @override
  Widget build(BuildContext context) => Container();
}
0 голосов
/ 31 января 2019

Я нашел другое решение методом проб и ошибок, но оно сработало.

import 'main.dart' as main;

Затем добавьте эту строку под onPressed.

main.MyAppState().printSample();
0 голосов
/ 12 февраля 2019

если вы хотите вызвать функцию printSample (), вы можете использовать:

class Myapp extends StatefulWidget{
...
    MyappState myAppState=new MyappState();
    @override
    MyappState createState() => myAppState;
    void printSample(){
        myAppState.printSample();
    }
}
class MyAppState extends State<MyApp>{
    void printSample (){
        print("Sample text");
    }
}

...............
Myapp _myapp = new Myapp();
myapp.printSample();
...
0 голосов
/ 26 июня 2018

Чтобы вызвать функцию родителя, вы можете использовать шаблон обратного вызова.В этом примере функция (onColorSelected) передается дочернему элементу.Ребенок вызывает функцию при нажатии кнопки:

import 'package:flutter/material.dart';

class Parent extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return ParentState();
  }
}

class ParentState extends State<Parent> {
  Color selectedColor = Colors.grey;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Container(
          color: selectedColor,
          height: 200.0,
        ),
        ColorPicker(
          onColorSelect: (Color color) {
            setState(() {
              selectedColor = color;
            });
          },
        )
      ],
    );
  }
}

class ColorPicker extends StatelessWidget {
  const ColorPicker({this.onColorSelect});

  final ColorCallback onColorSelect;

  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        RaisedButton(
          child: Text('red'),
          color: Colors.red,
          onPressed: () {
            onColorSelect(Colors.red);
          },
        ),
        RaisedButton(
          child: Text('green'),
          color: Colors.green,
          onPressed: () {
            onColorSelect(Colors.green);
          },
        ),
        RaisedButton(
          child: Text('blue'),
          color: Colors.blue,
          onPressed: () {
            onColorSelect(Colors.blue);
          },
        )
      ],
    );
  }
}

typedef ColorCallback = void Function(Color color);

Внутренние виджеты Flutter, такие как кнопки или поля формы, используют точно такой же шаблон.Если вы хотите вызывать функцию только без аргументов, вы можете использовать тип VoidCallback вместо определения своего собственного типа обратного вызова.


Если вы хотите уведомить вышестоящего родителя, вы можете просто повторитьэтот шаблон на каждом уровне иерархии:

class ColorPickerWrapper extends StatelessWidget {
  const ColorPickerWrapper({this.onColorSelect});

  final ColorCallback onColorSelect;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.all(20.0),
      child: ColorPicker(onColorSelect: onColorSelect),
    )
  }
}

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


Один альтернативный подход - классы controller в Flutter (ScrollController, AnimationController, ...).Они также передаются дочерним элементам в качестве параметров конструктора и содержат методы для управления состоянием дочернего элемента без вызова setState для родительского элемента.Пример:

scrollController.animateTo(200.0, duration: Duration(seconds: 1), curve: Curves.easeInOut);

Затем дети должны прослушать эти изменения, чтобы обновить свое внутреннее состояние.Конечно, вы также можете реализовать свой собственный класс контроллера.Если вам нужно, я рекомендую вам взглянуть на исходный код Flutter, чтобы понять, как это работает.


Фьючерсы и потоки являются еще одной альтернативой для передачи состояния и могут также использоваться для вызовафункция ребенка.

Но я действительно не рекомендую это.Если вам нужно вызвать метод дочернего виджета, очень похоже, что ваша прикладная архитектура имеет недостатки. Попробуйте переместить состояние до общего предка!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...