简体   繁体   English

我如何使用 Flutter 中从 json 解析的嵌套映射列表中的函数创建对象

[英]How do i create an object using a function from a list of nested maps parse from json in Flutter

I'm looking for help expanding on an earlier question Question which showed me one way to access the json data in MovementDataSource .我正在寻求帮助扩展之前的问题Question ,该问题向我展示了一种访问MovementDataSource的 json 数据的方法。 In that case on the first page the user is presented a list of movements using a listview and getMovements() .在这种情况下,在第一页上,用户会看到一个使用 listview 和getMovements()的运动列表。 After selecting a movement the user on page 2 is presented a list of variations via a listview and getVariationsByMovement() .选择一个动作后,第 2 页上的用户会通过列表视图和getVariationsByMovement()一个变化列表。 Then after selecting the variation the user is presented page 3 that gives me access to all of the items in the singular VariationModel .然后在选择变体后,用户会看到第 3 页,让我可以访问单一VariationModel中的所有项目。 (right now it's only variationName) (现在它只是variationName)

I have another use case where I am in another part of the application but need to jump directly to page 3 bypassing the user workflow of Page 1 and Page 2 above.我还有另一个用例,我在应用程序的另一部分,但需要绕过上面第 1 页和第 2 页的用户工作流直接跳转到第 3 页。 At that moment I have access to the String Movement and the String VariationName .那时我可以访问String MovementString VariationName I'm looking for help - an example of a function that I could pass in those two variables and give me back a VariationName object to pass in the constructor of the link directly to page 3. In MovementDataSource below there is a getVariation() function I am hoping to have help with.我正在寻求帮助 - 一个函数示例,我可以传入这两个变量并返回一个VariationName对象,以将链接的构造函数直接传递到第 3 页。在下面的MovementDataSource中有一个getVariation()函数我希望得到帮助。

class MovementDataSource extends ChangeNotifier{

  List<Map> getAll() => _movement;

  List<String> getMovements()=> _movement
      .map((map) => MovementModel.fromJson(map))
      .map((item) => item.movement)
      .toList();

  getVariationsByMovement(String movement) => _movement
      .map((map) => MovementModel.fromJson(map))
      .where((item) => item.movement == movement)
      .map((item) => item.variation)
      .expand((i) => i)
      .toList();

  VariationModel getVariation(String movement, String variation){
       **Return VariationModel from List _movement json**
  }


  List _movement = [
    {
      "movement": "Plank",
      "alias": "plank",
      "variation": [
        {"variationName": "High Plank"}, {"variationName": "Forearm Plank"},
      ]
    },
    {
      "movement": "Side Plank",
      "alias": "side plank",
      "variation": [
        {"variationName": "Side Plank Right"}, {"variationName": "Side Plank Left"},
      ],
    },
  ];
}

class MovementModel {
  MovementModel({
    this.movement,
    this.alias,
    this.variation,
  });

  String movement;
  String alias;
  List<VariationModel> variation;

  factory MovementModel.fromJson(Map<String, dynamic> json) => MovementModel(
        movement: json["movement"],
        alias: json["alias"],
        variation: List<VariationModel>.from(
            json["variation"].map((x) => VariationModel.fromJson(x))),
      );

  Map<String, dynamic> toJson() => {
        "movement": movement,
        "alias": alias,
        "variation": List<dynamic>.from(variation.map((x) => x.toJson())),
      };
}

class VariationModel {
  VariationModel({
    this.variationName,
  });

  String variationName;

  factory VariationModel.fromJson(Map<String, dynamic> json) => VariationModel(
        variationName: json["variationName"],
      );

  Map<String, dynamic> toJson() => {
        "variationName": variationName,
      };
}

An example of the Page 3 above - the direct target in this use case.上面第 3 页的示例 - 本用例中的直接目标。

class TargetPage extends StatelessWidget {
  final VariationModel variation;
  SelectDefaultItemPage({this.variation});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("test"),
        ),
        body: Text(variation.variationName));
  }
}

example of the source page that includes a direct link to page 3 target above.包含指向上述第 3 页目标的直接链接的源页面示例。 This is where the getVariation() function would be called passing a VariationModel to SourcePage above.这是getVariation()函数的地方,将 VariationModel 传递给上面的 SourcePage。

class SourcePage extends StatelessWidget {
  final VariationModel variation;
  SelectDefaultItemPage({this.variation});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("test"),
        ),
        body:FlatButton(
              child: Text(
                "Go to TargetPage",
              ),
              onPressed: () async {Navigator.push(context, MaterialPageRoute(
                            builder: (_) => SourcePage(getVariation(movement: movement, variation: 
                            variation)));
              },
         )
  }
}

Thanks for your help.谢谢你的帮助。

You can copy paste run full code below您可以在下面复制粘贴运行完整代码
You can pass movementDataSource , movement and variation to SourcePage您可以将movementDataSourcemovementvariation传递给SourcePage
And in SourcePage call并在SourcePage调用中

TargetPage(variation: movementDataSource.getVariation(
                            movement: movement,
                            variation: variation.variationName))

code snippet代码片段

VariationModel getVariation({String movement, String variation}) => _movement
      .map((map) => MovementModel.fromJson(map))
      .where((item) => item.movement == movement)
      .map((item) => item.variation)
      .expand((i) => i)
      .where((e) => e.variationName == variation)
      .first;
...
onTap: () async {
                  Navigator.push(
                      context,
                      MaterialPageRoute(
                          builder: (_) => SourcePage(
                              movementDataSource: _movementDataSource,
                              movement: movement,
                              variation: vList[index])));
                },
                
...             
class SourcePage extends StatelessWidget {
  final MovementDataSource movementDataSource;
  final String movement;
  final VariationModel variation;
  SourcePage({this.movementDataSource, this.movement, this.variation});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        ...
          onPressed: () async {
            Navigator.push(
                context,
                MaterialPageRoute(
                    builder: (_) => TargetPage(
                        variation: movementDataSource.getVariation(
                            movement: movement,
                            variation: variation.variationName))));
          },
        ));     

...
class TargetPage extends StatelessWidget {
  final VariationModel variation;
  TargetPage({this.variation});
        

working demo工作演示

在此处输入图片说明

full code完整代码

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

List<MovementModel> movementModelFromJson(String str) =>
    List<MovementModel>.from(
        json.decode(str).map((x) => MovementModel.fromJson(x)));
String movementModelToJson(List<MovementModel> data) =>
    json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class MovementDataSource extends ChangeNotifier {
  List<Map> getAll() => _movement;

  List<String> getMovements() => _movement
      .map((map) => MovementModel.fromJson(map))
      .map((item) => item.movement)
      .toList();

// I'd  like this to return a list of movement.variation.variationName

  getVariationsByMovement(String movement) => _movement
      .map((map) => MovementModel.fromJson(map))
      .where((item) => item.movement == movement)
      .map((item) => item.variation)
      .expand((i) => i)
      .toList();

  VariationModel getVariation({String movement, String variation}) => _movement
      .map((map) => MovementModel.fromJson(map))
      .where((item) => item.movement == movement)
      .map((item) => item.variation)
      .expand((i) => i)
      .where((e) => e.variationName == variation)
      .first;

  List _movement = [
    {
      "movement": "Plank",
      "alias": "plank",
      "variation": [
        {"variationName": "High Plank"},
        {"variationName": "Forearm Plank"},
      ]
    },
    {
      "movement": "Side Plank",
      "alias": "side plank",
      "variation": [
        {"variationName": "Side Plank Right"},
        {"variationName": "Side Plank Left"},
      ],
    },
  ];
}

class MovementModel {
  MovementModel({
    this.movement,
    this.alias,
    this.variation,
  });

  String movement;
  String alias;
  List<VariationModel> variation;

  factory MovementModel.fromJson(Map<String, dynamic> json) => MovementModel(
        movement: json["movement"],
        alias: json["alias"],
        variation: List<VariationModel>.from(
            json["variation"].map((x) => VariationModel.fromJson(x))),
      );

  Map<String, dynamic> toJson() => {
        "movement": movement,
        "alias": alias,
        "variation": List<dynamic>.from(variation.map((x) => x.toJson())),
      };
}

class VariationModel {
  VariationModel({
    this.variationName,
  });

  String variationName;

  factory VariationModel.fromJson(Map<String, dynamic> json) => VariationModel(
        variationName: json["variationName"],
      );

  Map<String, dynamic> toJson() => {
        "variationName": variationName,
      };
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  String movement = "Plank";
  MovementDataSource _movementDataSource = MovementDataSource();
  void _incrementCounter() {
    List<VariationModel> vList =
        _movementDataSource.getVariationsByMovement("Plank");

    for (int i = 0; i < vList.length; i++) {
      print(vList[i].variationName);
    }

    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    List<VariationModel> vList =
        _movementDataSource.getVariationsByMovement(movement);

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: ListView.builder(
          scrollDirection: Axis.vertical,
          shrinkWrap: true,
          itemCount: vList.length,
          itemBuilder: (buildContext, index) {
            return Card(
              child: ListTile(
                title: Text(
                  vList[index].variationName.toString(),
                  style: TextStyle(fontSize: 20),
                ),
                trailing: Icon(Icons.keyboard_arrow_right),
                onTap: () async {
                  Navigator.push(
                      context,
                      MaterialPageRoute(
                          builder: (_) => SourcePage(
                              movementDataSource: _movementDataSource,
                              movement: movement,
                              variation: vList[index])));
                },
              ),
            );
          }),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

class SourcePage extends StatelessWidget {
  final MovementDataSource movementDataSource;
  final String movement;
  final VariationModel variation;
  SourcePage({this.movementDataSource, this.movement, this.variation});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("Source page"),
        ),
        body: FlatButton(
          child: Text(
            "Go to TargetPage",
          ),
          onPressed: () async {
            Navigator.push(
                context,
                MaterialPageRoute(
                    builder: (_) => TargetPage(
                        variation: movementDataSource.getVariation(
                            movement: movement,
                            variation: variation.variationName))));
          },
        ));
  }
}

class TargetPage extends StatelessWidget {
  final VariationModel variation;
  TargetPage({this.variation});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("Target page"),
        ),
        body: Text(variation.variationName));
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM