Flutter Отправить данные на другой экран без навигатора - PullRequest
0 голосов
/ 22 апреля 2020

У меня есть вопрос, как передавать данные между страницами / экраном во флаттере без навигатора и только с использованием onChanged и streambuilder.

Все, что я хочу, это когда пользователь пишет в текстовое поле на первом виджете, второй виджет автоматически refre sh с новыми данными из первого виджета.

Вот мой код для first.dart

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

class First extends StatefulWidget {
  First({Key key}) : super(key: key);

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

class _FirstState extends State<First> {
      final TextEditingController _myTextController =
        new TextEditingController(text: "");


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: new AppBar(
        title: Text("Passing Data"),
      ),
      body: Column(
        children: <Widget>[
          Container(
            height: 120.0,
            child: Column(
              children: <Widget>[
                TextField(
                  controller: _myTextController,
                  onChanged: (String value) {
                    // refresh second with new data
                  },
                )
              ]
            )
          ),
          Container(
            height: 120.0,
            child: Second(
              myText: _myTextController.text,
            ),
          )
        ],
      ),
    );
  }
}

и вот мой second.dart как второй виджет для получения данных из первого виджета.

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

class Second extends StatefulWidget {
  Second({Key key, @required this.myText}) : super(key: key);

  final String myText;

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

class _SecondState extends State<Second> {
  StreamController _dataController;
  loadPosts() async {
    ApiServices.getDetailData(widget.myText).then((res) async {
      _dataController.add(res);
      return res;
    });
  }

  @override
  void initState() {
    _dataController = new StreamController();
    loadPosts();
    super.initState();
    print(widget.myText);
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
        stream: _dataController.stream,
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          if (snapshot.hasError) {
            return Text(snapshot.error);
          }
          if (snapshot.hasData) {
            return Container();
          }

          if (snapshot.connectionState == ConnectionState.waiting) {
            return Row(
              children: <Widget>[
                Text("Please Write A Text"),
              ],
            );
          } else if (snapshot.connectionState != ConnectionState.active) {
            return CircularProgressIndicator();
          }

          if (!snapshot.hasData &&
              snapshot.connectionState == ConnectionState.done) {
            return Text('No Data');
          } else if(snapshot.hasData && snapshot.connectionState == ConnectionState.done) {
            return Text(widget.myText);
          }
          return null;
        });
  }
}

1 Ответ

1 голос
/ 25 апреля 2020

У вас есть несколько вариантов. Два самых простых: передача самого контроллера редактирования текста во второй виджет, затем прослушивание его и вызов setState для изменения текста во втором виджете.

Пример

class Second extends StatefulWidget {
  Second({Key key, @required this.textController}) : super(key: key);

  final TextEditingController textController;

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

class _SecondState extends State<Second> {
// made this private
String _myText;

@override
void initState() {
  _myText = widget.textController.text
  widget.textController.addListener(() {
    setState((){_myText = widget.textController.text});
    );
  });
  super.initState();
}

...

// then in your build method, put this in place of return Text(widget.myText);
return Text(_myText);

Вариант 2 прослушивает контроллер в вашем первом виджете и вызывает там setState. Это восстановит и первый и второй виджеты, хотя, и я думаю, что не так эффективно, как первый вариант.

Надеюсь, это поможет

...