使用名稱管理route,並移動state到main.dart,會使程式的重用性更高,並且不會因為切換頁面而將剛剛加好的state洗掉。
一樣的檔案結構
import 'package:flutter/material.dart';
import './pages/products_admin.dart';
import './pages/products.dart';
import './pages/product.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
//根組件變成stateful
@override
State<StatefulWidget> createState() {
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
List<Map<String, String>> _products = [];
void _addProduct(Map<String, String> product) {
setState(() {
_products.add(product);
});
}
void _deleteProduct(int index) {
setState(() {
_products.removeAt(index);
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
...
),
routes: {
'/': (BuildContext context) => ProductsPage(_products, _addProduct, _deleteProduct),
//根目錄是商品列表,並傳入控制state的新增刪除方法與商品list
'/admin': (BuildContext context) => ProductsAdminPage(),
//admin是有tab的那頁
},
onGenerateRoute: (RouteSettings settings) {
//route產生好後
final List<String> pathElements = settings.name.split('/');
//是個把route字串用/分隔的list
if (pathElements[0] != '') {
return null;
}
//若剛剛定義的list第一個值不是空字串(代表route字串不是/開頭)
//就不回傳東西
if (pathElements[1] == 'product') {
//第二個是product
final int index = int.parse(pathElements[2]);
//第三個就是你商品列表按下去的商品索引數
return MaterialPageRoute<bool>(
builder: (BuildContext context) => ProductPage(
_products[index]['title'], _products[index]['image']
//直接把商品列表的標題和圖片傳進去商品頁面
//因此如果route是'/product/1'
//就會傳到第一個商品的商品細節
),
);
}
return null;
},
onUnknownRoute: (RouteSettings settings) {
//若上面的function回傳null就進來
return MaterialPageRoute(
builder: (BuildContext context) =>
ProductsPage(_products, _addProduct, _deleteProduct)
//未知的route就直接切到首頁
);
},
);
}
}
...
//收合視窗的all product列表按下去以後,導到名稱為/的頁面
//此例為ProductsPage
ListTile(
title: Text('All Products'),
onTap: () {
Navigator.pushReplacementNamed(context, '/');
},
)
...
...
//收合視窗的all product列表按下去以後,導到名稱為/的頁面
//此例為ProductsAdminPage
ListTile(
title: Text('Manage Products'),
onTap: () {
Navigator.pushReplacementNamed(context, '/admin');
},
)
...
如果state改成上面傳下來,那下面就改回stateless
...
class ProductsPage extends StatelessWidget {
final List<Map<String, String>> products;
final Function addProduct;
final Function deleteProduct;
ProductsPage(this.products, this.addProduct, this.deleteProduct);
...
body: ProductManager(products, addProduct, deleteProduct),
final List<Map<String, String>> products;
final Function addProduct;
final Function deleteProduct;
ProductManager(this.products, this.addProduct, this.deleteProduct);
...
Expanded(child: Products(products, deleteProduct: deleteProduct))
final List<Map<String, String>> products;
final Function deleteProduct;
Products(this.products, {this.deleteProduct});
...
FlatButton(
child: Text('Details'),
onPressed: () => Navigator.pushNamed<bool>(
context, '/product/' + index.toString()
//商品細節按鈕按下去後,導到/product/你點的項次頁面
//此例為ProductPage
).then((bool value) {
if (value) {
deleteProduct(index);
}
}),
)
主題來源:
Learn Flutter & Dart to Build iOS & Android Apps