首页 > 解决方案 > 从 Flutter 中的 SecondScreen 调用 FirstScreen 的设置状态

问题描述

我有两个名为“FirstScreen”的颤振屏幕,其中包含订单列表和用于某些操作的“SecondScreen”。

我想在“SecondScreen”弹出窗口中调用“FirstScreen”的 setstate,以便“FirstScreen”重新加载挂单列表第一屏

SecondScreen 将接受或拒绝订单,FirstScreen 应该从服务器重新加载数据,这由 FirstScreen 中的方法 getOrders() 调用。 第二屏

第一屏代码

import 'package:flutter/material.dart';
import 'package:nobleappshop/model/jobOrderItem.dart';
import 'package:nobleappshop/screens/SeconScreen.dart';
import 'package:nobleappshop/constants/constants.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

class FirstScreen extends StatefulWidget {
  @override
  FirstScreenState createState() => FirstScreenState();
}
class FirstScreenState extends State<FirstScreen> {

  Future<List<JobOrders>> _getPendingOrder() async {
    var data = await http.get("$ApiServer/JobOrders/smOrdersPending");
    var jsonData = json.decode(data.body);
    List<JobOrders> joborderitemlist = [];
    for (var i in jsonData) {
      JobOrders jobOrders = JobOrders(
        Eid: i["Eid"],
        Uid: i["Uid"],
        Name: i["Name"],
        Contact: i["Contact"].toString(),
        OrderStat: i["OrderStat"],
      );
      joborderitemlist.add(jobOrders);
    }
    return joborderitemlist;
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('FirstScreen'),
      ),
      body: FutureBuilder(
        future: _getPendingOrder(),
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            if (snapshot.data.length <= 0) {
              return Container(
                child: Center(
                  child: Text('You have not made any orders yet...'),
                ),
              );
            } else {
              return ListView.builder(
                itemCount: snapshot.data.length,
                itemBuilder: (BuildContext context, int index) {
                  return OrdersListWidget(
                    Eid: snapshot.data[index].Eid,
                    Uid: snapshot.data[index].Uid.toString(),
                    Name: snapshot.data[index].Name.toString(),
                    Contact: snapshot.data[index].Contact.toString(),
                    Status: snapshot.data[index].OrderStat.toString(),
                  );
                },
              );
            }
          } else {
            return Container(
              child: Center(
                child: CircularProgressIndicator(),
              ),
            );
          }
        },
      ),
    );
  }
}
class OrdersListWidget extends StatelessWidget {
  int Eid;
  String Uid;
  String Name;
  String Contact;
  String Status;
  OrdersListWidget(
      {@required this.Eid,
        @required this.Uid,
        @required this.Name,
        @required this.Contact,
        @required this.Status});

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        ListTile(
          leading: Text('#$Eid'),
          title: Text(Name),
          subtitle: Text(Contact),
          trailing: Text(Status),
          onTap: () {
            showModalBottomSheet(
              context: context,
              isScrollControlled: true,
              builder: (context) => SingleChildScrollView(
                child: Container(
                  padding: EdgeInsets.only(
                      bottom: MediaQuery.of(context).viewInsets.bottom),
                  child: SecondScreen(OrderId: Eid),
                ),
              ),
            );
          },
        ),
        Divider(),
      ],
    );
  }
}

第二屏幕代码

import 'package:flutter/material.dart';
import 'package:nobleappshop/model/orderItem.dart';
import 'package:http/http.dart' as http;
import 'package:nobleappshop/widgets/iconTextWidget.dart';
import 'package:nobleappshop/widgets/scOrderItems.dart';
import 'package:nobleappshop/constants/constants.dart';

class SecondScreen extends StatefulWidget {

  int OrderId;
  SecondScreen({@required this.OrderId});

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

class _SecondScreenState extends State<SecondScreen> {

  Future<http.Response> _updateJobOrder() async {
//Run Update code here
  }
  double totalAmount = 0;
  String token;

  List<OrderItem> orderitemlist = [];

  Future<List<OrderItem>> _getMyOrders() async {
//Call for orderitemslist
    return orderitemlist;
  }

  @override
  void initState() {
    super.initState();
    _getMyOrders();
  }
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Color(0xff757575),
      child: Container(
        padding: EdgeInsets.all(8.0),
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.only(
            topLeft: Radius.circular(20.0),
            topRight: Radius.circular(20.0),
          ),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[

            IconTextRowWidget(btnIcon: Icons.credit_card,btnText: 'Amount Due',btnSubText: '${totalAmount<10?10:totalAmount} QAR',),
            Row(
              children: <Widget>[
                Expanded(
                  child: FlatButton(
                    color: Colors.green,
                    onPressed: (){
                      // Here I would like to close my current screen and reload orderslist, so that it will load all other pending joborders
                      _updateJobOrder();
                      Navigator.pop(context);
                    },
                    child: Text('Approve',style: TextStyle(color: Colors.white),),
                  ),
                ),
                Expanded(
                  child: FlatButton(
                    color: Colors.blueGrey,
                    onPressed: (){
// Here I would like to close my current screen and reload orderslist, so that it will load all other pending joborders
                      _updateJobOrder();
                      Navigator.pop(context);
                    },
                    child: Text('Reject',style: TextStyle(color: Colors.white),),
                  ),
                ),
              ],
            ),
            SizedBox(height: 10,)
//            SizedBox(
//              height: 30.0,
//            ),
          ],
        ),
      ),
    );
  }
}

标签: flutterdartmobile

解决方案


当我检查你的代码时,我意识到你需要向你的第一个小部件的孙子发送函数,

  1. 您需要在您的中声明一个函数,OrdersListWidget因为此小部件是访问第二个屏幕的唯一方法。
    class OrdersListWidget extends StatelessWidget {
      int Eid;
      String Uid;
      String Name;
      String Contact;
      String Status;
      final VoidCallback setStateOfFirstScreen;
    
      OrdersListWidget(
          {@required this.Eid,
          @required this.Uid,
          @required this.Name,
          @required this.Contact,
          @required this.Status,
          @required this.setStateOfFirstScreen});
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: <Widget>[
            ListTile(
              leading: Text('#$Eid'),
              title: Text(Name),
              subtitle: Text(Contact),
              trailing: Text(Status),
              onTap: () {
                showModalBottomSheet(
                  context: context,
                  isScrollControlled: true,
                  builder: (context) => SingleChildScrollView(
                    child: Container(
                      padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
                      child: SecondScreen(OrderId: Eid, setStateOfFirstScreen: setStateOfFirstScreen),
                    ),
                  ),
                );
              },
            ),
            Divider(),
          ],
        );
      }
    }
  1. 并将 setStateOrdersListWidget作为参数发送到您的第一页;
    ListView.builder(
      itemCount: snapshot.data.length,
      itemBuilder: (BuildContext context, int index) {
        return OrdersListWidget(
          Eid: snapshot.data[index].Eid,
          Uid: snapshot.data[index].Uid.toString(),
          Name: snapshot.data[index].Name.toString(),
          Contact: snapshot.data[index].Contact.toString(),
          Status: snapshot.data[index].OrderStat.toString(),
          setStateOfFirstScreen: () => setState(() {}),
        );
      },
    );
  1. 发送setStateOfFirstScreen SecondScreen并在那里使用它来设置第一个屏幕的状态;

    class SecondScreen extends StatefulWidget {
      final int OrderId;
      final VoidCallback setStateOfFirstScreen;
    
      SecondScreen({@required this.OrderId, @required this.setStateOfFirstScreen});
    
      @override
      _SecondScreenState createState() => _SecondScreenState();
    }
    
    class _SecondScreenState extends State<SecondScreen> {
      Future<http.Response> _updateJobOrder() async {
    //Run Update code here
      }
      double totalAmount = 0;
      String token;
    
      List<OrderItem> orderitemlist = [];
    
      Future<List<OrderItem>> _getMyOrders() async {
    //Call for orderitemslist
        return orderitemlist;
      }
    
      @override
      void initState() {
        super.initState();
        _getMyOrders();
      }
    
      @override
      Widget build(BuildContext context) {
        return Container(
          color: Color(0xff757575),
          child: Container(
            padding: EdgeInsets.all(8.0),
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.only(
                topLeft: Radius.circular(20.0),
                topRight: Radius.circular(20.0),
              ),
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                IconTextRowWidget(
                  btnIcon: Icons.credit_card,
                  btnText: 'Amount Due',
                  btnSubText: '${totalAmount < 10 ? 10 : totalAmount} QAR',
                ),
                Row(
                  children: <Widget>[
                    Expanded(
                      child: FlatButton(
                        color: Colors.green,
                        onPressed: () {
                          // Here I would like to close my current screen and reload orderslist, so that it will load all other pending joborders
                          _updateJobOrder();
                          Navigator.pop(context);
                          widget.setStateOfFirstScreen();
                        },
                        child: Text(
                          'Approve',
                          style: TextStyle(color: Colors.white),
                        ),
                      ),
                    ),
                    Expanded(
                      child: FlatButton(
                        color: Colors.blueGrey,
                        onPressed: () {
    // Here I would like to close my current screen and reload orderslist, so that it will load all other pending joborders
                          _updateJobOrder();
                          Navigator.pop(context);
                          widget.setStateOfFirstScreen();
                        },
                        child: Text(
                          'Reject',
                          style: TextStyle(color: Colors.white),
                        ),
                      ),
                    ),
                  ],
                ),
                SizedBox(
                  height: 10,
                )
    //            SizedBox(
    //              height: 30.0,
    //            ),
              ],
            ),
          ),
        );
      }
    }


推荐阅读