Flutter riverpod 更新 ListView 中特定索引的状态

问题描述

我有一个应用程序可以向 API 发出发布请求,其中包含有关司机和订单的数据。初始页面在各个列表磁贴中显示驱动程序列表。列表磁贴有一个下拉选项。单击该选项会将您带到一个页面,其中包含该驱动程序的订单列表视图。单击单个订单会将您带到一个表单。在提交和验证此表单时,我想将该订单文本的颜色从红色更改为绿色。每个订单都有一个已提交的标志,当它提交时,我想将其更改为 true,然后更改颜色。当列表视图中的所有订单均为绿色时,我希望该驱动程序的颜色变为绿色。我一直在阅读 Riverpod 教程和文档,但无法弄清楚如何完成这项工作。有人能指出我正确的方向吗?

ma​​in.dart

void main() {
  runApp(ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',theme: ThemeData(
        primarySwatch: Colors.blue,),debugShowCheckedModeBanner: false,home: DriversPage(),);
  }
}

drivers.dart - 这是显示驱动程序的地方

class DriversPage extends StatelessWidget {
  final HttpService httpService = HttpService();
  var colorChoice = Colors.red;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: Color(0xFFFAFAFA),appBar: AppBar(
        title: Text("Drivers")
      ),body: Container(
        child: FutureBuilder(
        future: httpService.getorders(),builder: (BuildContext context,AsyncSnapshot<List<Order>> snapshot) {
          if (snapshot.hasData) {
            List<Order> orders = snapshot.data;
            return ListView(
              children: orders.map((Order order) => Card(child: ExpansionTile(
                title: Text(order.driver,style: TextStyle(color: colorChoice),children: <Widget>[
                  Container(
                    alignment: Alignment.center,margin: EdgeInsets.all(10.0),decoration: Boxdecoration(
                      color: Colors.white,borderRadius: BorderRadius.circular(2.0),border: Border.all(color: Colors.black26)
                    ),child: ListTile(title: Text("Orders"),trailing: Icon(Icons.keyboard_arrow_right),onTap: () => Navigator.of(context).push(MaterialPageRoute(builder: (context) => OrdeRSState(driverName: order.driver,driverOrders: order.orders))),],))).toList(),);
          }
          return Center(child: CircularProgressIndicator());
        }),));
  }
}

orders.dart - 这是显示司机订单的地方。我最初把它作为一个有状态的小部件,但把它变成了一个消费者小部件,并尝试制作一个提供者,但在如何在这样的列表视图中处理它时迷失了。正如你在这里看到的,我使用了基于 item.submitted

文本颜色的三元运算符
final driverListProvider = StateNotifierProvider((ref) => new DriverListtest());

class OrdeRSState extends ConsumerWidget {
  final String driverName;
  final List<OrderElement> driverOrders;

  const OrdeRSState({Key key,this.driverName,this.driverOrders}) : super(key: key);

  @override
  Widget build(BuildContext context,ScopedReader watch) {
    return Scaffold(
      appBar: AppBar(
        title: Text(driverName),body: ListView.builder(
          itemCount: driverOrders.length,itemBuilder: (context,index){
            final item = driverOrders[index];
            return Card(
                key: UniqueKey(),child: ListTile(title: Text(item.order,style: TextStyle(color: item.submitted? Colors.green : Colors.red),subtitle: Text('${item.company}\n${item.address}'),onTap: () => Navigator.of(context).push(MaterialPageRoute(builder: (context) => OrderForm(orderTitle: item.order,))),));
          }),);
  }
}

orderform.dart - 只显示表单的一个字段,认为其余的不是必需的,只需要显示提交时发生的事情。

class OrderForm extends StatefulWidget {
  final String orderTitle;

  const OrderForm({this.orderTitle});

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

class _OrderFormState extends State<OrderForm> {
  @override
  final _formKey = GlobalKey<FormState>();
  final _orderModel = Order();
  List<String> _pickerNames = ['Loader 1','Loader 2','Loader 3','Loader 4'];
  String _selectedPickedBy;
  String _selectedCheckedBy;


  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(backgroundColor: Colors.blueGrey,title: Center(
          child: Text(widget.orderTitle),floatingActionButton: FloatingActionButton(
          child: Icon(
              Icons.delete
          ),onpressed: () {
            showDialog(
                context: context,builder: (BuildContext context) {
                  return AlertDialog(
                    scrollable: true,title: Text('Login'),content: Padding(
                      padding: const EdgeInsets.all(8.0),child: Form(
                        child: Column(
                          children: <Widget>[
                            TextFormField(
                              decoration: Inputdecoration(
                                labelText: 'Reason',icon: Icon(Icons.account_Box),TextFormField(
                              decoration: Inputdecoration(
                                labelText: 'Reason 1',icon: Icon(Icons.email),TextFormField(
                              decoration: Inputdecoration(
                                labelText: 'Reason 2',icon: Icon(Icons.message),actions: [
                      RaisedButton(
                          child: Text("Submit"),onpressed: () {

                          })
                    ],);
            });
          }
        ),body: Container(
          padding: const EdgeInsets.symmetric(vertical: 16.0,horizontal: 16.0),child: Builder(
            builder: (context) => Form(
                key: _formKey,child: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,children: [
                    DropdownButtonFormField(
                      isExpanded: true,hint: Text('Picked By'),value: _selectedPickedBy,onChanged: (newValue){
                        setState(() {
                          _selectedPickedBy = newValue;
                        });
                      },validator: (value) => value == null
                          ? 'Picked By required' : null,items: _pickerNames.map((picker) {
                        return DropdownMenuItem(
                          child: new Text(picker),value: picker,);
                      }).toList(),onSaved: (value) => setState(() => _orderModel.pickedBy = value),Container(
                      padding: const EdgeInsets.symmetric(
                          vertical: 16.0,horizontal: 16.0
                      ),child: RaisedButton(
                        onpressed: (){
                          final form = _formKey.currentState;
                          if (form.validate()){
                            form.save();
                            Navigator.pop(context,);
                          }
                        },child: Text("Submit"),)
                  ],)),)
    );

  }
}

ordermodel.dart - 这是向我的 api 发出 http 请求时驱动程序和订单的模型。在底部,您可以看到我尝试制作 statenotifier 的位置以及我尝试接受 OrderElement 列表(订单列表)的目的。

List<Order> orderFromJson(String str) => List<Order>.from(json.decode(str).map((x) => Order.fromJson(x)));

String orderToJson(List<Order> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class Order {
  Order({
    this.driver,this.orders,});

  String driver;
  List<OrderElement> orders;

  factory Order.fromJson(Map<String,dynamic> json) => Order(
    driver: json["Driver"],orders: List<OrderElement>.from(json["Orders"].map((x) => OrderElement.fromJson(x))),);

  Map<String,dynamic> toJson() => {
    "Driver": driver,"Orders": List<dynamic>.from(orders.map((x) => x.toJson())),};
}

class OrderElement {
  OrderElement({
    this.order,this.company,this.address,this.submitted,this.index,});

  String order;
  String company;
  String address;
  bool submitted;
  num index;

  factory OrderElement.fromJson(Map<String,dynamic> json) => OrderElement(
    order: json["Order"],company: json["Company"],address: json["Address"],submitted: json["submitted"],index: json["index"]
  );

  Map<String,dynamic> toJson() => {
    "Order": order,"Company": company,"Address": address,};
}

class DriverListTest extends StateNotifier<List<OrderElement>> {
  DriverListTest([List<OrderElement> drivers1]) : super(drivers1 ?? []);


  void onSubmit(num index) {
    state = [
      for(final currentOrder in state)
        if (currentOrder.index == index)
          OrderElement(
            order: currentOrder.order,company: currentOrder.company,address: currentOrder.address,submitted: !currentOrder.submitted,index: currentOrder.index,)
      else
        currentOrder,];
  }
}

不知道是否需要我的 Http 类,但如果需要,请告诉我。我尝试遵循 https://www.refactord.com/guides/riverpod-state-management-explainedHow to set the state of a widget at an index in a listview.builder in flutter 如何处理单个小部件,但我又迷路了。任何帮助将不胜感激!提前致谢。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)