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
. In that case on the first page the user is presented a list of movements using a listview and getMovements()
. After selecting a movement the user on page 2 is presented a list of variations via a listview and 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
. (right now it's only 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. At that moment I have access to the String Movement
and the String 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.
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.
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. This is where the getVariation()
function would be called passing a VariationModel to SourcePage above.
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
And in SourcePage
call
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));
}
}
推荐阅读
- regex - nifi routeText 处理器使用问题
- c++ - 期望一个类型,得到一个模板
- python-2.7 - 通过 python 执行 PowerShell 脚本
- redis - Google Cloud - 用于管理队列的 Redis 替代方案?
- c# - 用 TextBox 中的值填充 DropBox
- google-cloud-dataflow - Apache Beam 如何处理多个窗口
- vue.js - 将 vue-router 组件解释为函数
- python-2.7 - 试图将文件与字典进行比较 python 2.7 无输出
- c# - 跳过“添加状态”,直接进入“编辑状态”
- javascript - XML 应用程序字符串无法显示