it-swarm.com.de

aufrufmethode in einem Stateful-Widget von einem anderen Stateful-Widget - Flutter

Ich habe ein Flatterprojekt, an dem ich arbeite. Ich kann nicht den ganzen Code verwenden, da er mehr als 500 Zeilen Code enthält. Ich werde also versuchen, meine Frage so einfach zu stellen, wie ich mit dem Kobold arbeite. Abschnitt des Codes. 

ich habe ein Stateful-Widget und einige Funktionen in diesem Stateful-Widget unter der Klasse, die erweitert wird, State<MusicPlayer>

datei lib\main.Dart

nimm einfach eine einfache Funktion wie 

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

diese Funktion befindet sich im Stateful-Widget in der Hauptklasse. 

es gibt eine andere Datei lib\MyApplication.Dart

diese Datei hat auch ein Stateful Widget. Kann ich etwas tun, damit ich die Funktion printSample() hier aufrufen kann.

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??  
      }
    );
  }
...
}
7
Aman Malhotra

Um eine Funktion eines Elternteils aufzurufen, können Sie das Callback-Muster verwenden. In diesem Beispiel wird eine Funktion (onColorSelected) an das untergeordnete Objekt übergeben. Das Kind ruft die Funktion auf, wenn eine Taste gedrückt wird:

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);

Interne Flattern-Widgets wie Schaltflächen oder Formularfelder verwenden genau dasselbe Muster. Wenn Sie eine Funktion nur ohne Argumente aufrufen möchten, können Sie den Typ VoidCallback verwenden, anstatt Ihren eigenen Callback-Typ zu definieren.


Wenn Sie ein höheres Elternteil benachrichtigen möchten, können Sie dieses Muster einfach auf jeder Hierarchieebene wiederholen:

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),
    )
  }
}

Das Aufrufen einer Methode eines untergeordneten Widgets von einem übergeordneten Widget wird in Flutter nicht empfohlen. Stattdessen fordert Flutter Sie auf, den Status eines untergeordneten Objekts als Konstruktorparameter weiterzugeben. Anstatt eine Methode des untergeordneten Objekts aufzurufen, rufen Sie einfach setState im übergeordneten Widget auf, um die untergeordneten Elemente zu aktualisieren.


Ein alternativer Ansatz sind die controller-Klassen in Flutter (ScrollController, AnimationController, ...). Diese werden auch als Konstruktorparameter an die untergeordneten Elemente übergeben. Sie enthalten Methoden zur Steuerung des Status des untergeordneten Objekts, ohne setState für das übergeordnete Element aufzurufen. Beispiel:

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

Die Kinder müssen dann auf diese Änderungen achten, um ihren internen Zustand zu aktualisieren. Natürlich können Sie auch Ihre eigene Controller-Klasse implementieren. Wenn Sie möchten, empfehle ich Ihnen, sich den Quellcode von Flutter anzusehen, um zu verstehen, wie das funktioniert.


Futures und Streams sind eine weitere Alternative zum Weiterleiten des Zustands und könnten auch dazu verwendet werden, eine Funktion eines Kindes aufzurufen. 

Aber ich kann es wirklich nicht empfehlen. Wenn Sie eine Methode eines untergeordneten Widgets aufrufen müssen, ist Ihre Anwendungsarchitektur sehr fehlerhaft. Versuchen Sie, den Staat zum gemeinsamen Vorfahren zu bringen!

13
boformer

Sie können dies ausprobieren, es wird eine in Page2 (StatefulWidget) definierte Methode aus dem Widget Page1 (StatefulWidget) aufgerufen.

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();
}
1
CopsOnRoad

wenn Sie printSample () aufrufen möchten, können Sie Folgendes verwenden:

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

Ich habe eine andere Lösung durch Ausprobieren gefunden, aber es hat funktioniert.

import 'main.Dart' as main;

Dann fügen Sie diese Zeile unter onPressed ein.

main.MyAppState().printSample();
0
mn128b