Suppose your app, which built by flutter 1.2, has ItemListScreen
and ItemDetailScreen
, and this app uses named route to manage routing of app. Users can click one of item in ItemListScreen and then ItemDetailScreen
will show detail information of the clicked item. You can find following example to decouple between screens by no need importing ItemDetailScreen
class to ItemListScreen file. Solution: Use
ModalRoute.of(context).settings.arguments
in your routes.dart
file to pass arguments to target screen.
Tested Environment:
Flutter 1.2
I set ItemListScreen
and ItemDetailScreen
are StatefulWidget
. I think there is another way to achieve same effect.
Dart 2.2
Let’s start! Keep on eyes on “KEYPOINT of this article”.
You have following file structure:
PROJECT_FOLDER/lib/main.dart
PROJECT_FOLDER/lib/route.dart
PROJECT_FOLDER/lib/screens/Item/ItemListScreen.dart
PROJECT_FOLDER/lib/screens/Item/ItemDetailScreen.dart
PROJECT_FOLDER/lib/screens/Item/index.dart
PROJECT_FOLDER/lib/models/Item.dart
Content of main.dart
import 'routes.dart';
void main() {
new Routes();
}
Content of routes.dart
import 'package:flutter/material.dart';
import 'package:my_appproject/screens/Item/index.dart';
class Routes {
final routes = {
'/': (BuildContext context) => new ItemListScreen(),
'/Item/Detail': (BuildContext context) => new ItemDetailScreen(
item: ModalRoute.of(context).settings.arguments
), // KEYPOINT of this article
};
Routes() {
runApp(new MaterialApp(
theme: ThemeData(
primarySwatch: Colors.orange,
textTheme: TextTheme(
body1: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold
),// TextStyle
), // TextTheme
),//
ThemeDataroutes: routes,
)// materialapp
);
}
}
Content of ItemListScreen.dart:
import 'package:flutter/material.dart';
import 'package:my\_appproject/models/Item.dart';
class ItemListScreen extends StatefulWidget {
@overrideState<StatefulWidget> createState() {
return new ItemListState();
}
}
class ItemListState extends State<ItemListScreen> {
var _itemList = [
{
"name": "AA",
"price": 10,
"qty": 2
},
{
"name": "BB",
"price": 5,
"qty": 3
},
{
"name": "CC",
"price": 7,
"qty": 7
},
];
List<Item> _uiItemList;
@overridevoid initState() {
_uiItemList = _itemList.map<Item>((Map \_item) => Item(
name: _item['name'],
price: _item['price'],
qty: _item['qty']
)
).toList();
super.initState();
}
@overrideWidget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("shelf items")),
body: ListView.separated(
separatorBuilder: (BuildContext context, int index) =>
Divider(color: Colors.black),
padding: EdgeInsets.all(8.0),
itemCount: _uiItemList.length,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(child: Row(
children: <Widget> [
Expanded(
child: Text(_uiItemList[index].name),
flex: 2,
), // Expanded
Expanded(
child: Text(_uiItemList[index].price.toString()),
flex: 1,
),// Expanded
Expanded(
child: Text(_uiItemList[index].qty.toString()),
flex: 1,
),// Expanded
],// children
), // Row
onTap: () {
Navigator.pushNamed(context, '/Item/Detail', arguments: _uiItemList[index]); // KEYPOINT of this article
}
);// GestureDetector
}, // itemBuilder
),// ListView.separated
); // Scaffold
}
}
Content of ItemDetailScreen:
import 'package:flutter/material.dart';
import 'package:my_appproject/models/Item.dart';
class ItemDetailScreen extends StatefulWidget {
final Item item;
ItemDetailScreen({
Key key,
this.item
}) : super(key: key);
@overrideItemDetailState createState() => ItemDetailState();
}
class ItemDetailState extends State<ItemDetailScreen> {
String _displayedText;
@overrideItemDetailScreen get widget => super.widget;// KEYPOINT of this article
@overridevoid initState() { // KEYPOINT of this article
if (widget.item == null) { // if pass no argument to this route, we display empty string
_displayedText = "";
} else { // if pass the item argument to this route, we display the item detail
_displayedText = widget.item.name + "/" + widget.item.price.toString() + "/" + widget.item.qty.toString();
}
super.initState();
}
@overrideWidget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("the Item detail")
),
body: Center(
child: Text(_displayedText),
), // Center
);// Scaffold
}
}
Content of screens/Item/index.dart:
export 'package:my_appproject/screens/Item/ItemListScreen.dart';
export 'package:my_appproject/screens/Item/ItemDetailScreen.dart';
Content of models/Item.dart:
class Item {
String name;
num price;
int qty;
Item({
this.name, this.price, this.qty
});
}
You can find my example code on GitHub repository.
reference link:
2. goderbauer’s PR based on Hixie’s one: https://github.com/flutter/flutter/pull/27058#issue-247522839