iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 12
0
自我挑戰組

使用flutter建構Android和iOs APP系列 第 12

使用名稱管理route,並移動state到main.dart

使用名稱管理route,並移動state到main.dart,會使程式的重用性更高,並且不會因為切換頁面而將剛剛加好的state洗掉。

一樣的檔案結構
https://ithelp.ithome.com.tw/upload/images/20181008/20111840tioAaZBwTd.png

  1. main.dart
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就直接切到首頁
            );
      },
    );
  }
}

  1. pages/product_admin.dart
...
//收合視窗的all product列表按下去以後,導到名稱為/的頁面
//此例為ProductsPage
ListTile(
  title: Text('All Products'),
  onTap: () {
    Navigator.pushReplacementNamed(context, '/');
  },
)
...
  1. pages/products.dart
...
//收合視窗的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),
  1. product_manager.dart
    一模模一樣樣的傳遞方式再往下傳
  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))
  1. products.dart
  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


上一篇
頁籤
下一篇
提示框與光箱
系列文
使用flutter建構Android和iOs APP17

尚未有邦友留言

立即登入留言