上次只寫了方法和參數,這次寫了完整的示例,頁面間參數的傳遞和接收的示例。
1、參數傳遞
用在程序上解釋就是比如你進入一個商品選擇列表,當你想選擇一個商品的具體信息的時候,你就要傳遞商品編號,詳細頁面接受到編號后,顯示出不同的內容。
聲明數據結構類
Dart中可以使用類來抽象一個數據,比如我們模仿一個商品信息,有商品標題和商品描述。我們定義了一個Product類,里邊有兩個字符型變量,title和description。
- title:是商品標題。
- description: 商品詳情描述
class Product{ final String title; //商品標題 final String description; //商品描述 Product(this.title,this.description); }
構建一個商品列表
作一個商品的列表,這里我們采用動態的構造方法,在主方法里傳遞一個商品列表(List)到自定義的Widget中。
先來看看主方法的編寫代碼:
import 'package:flutter/material.dart'; void main(){ runApp(MaterialApp( title:'數據傳遞案例', home:ProductList( products:List.generate( 20, (i)=>Product('商品 $i','這是一個商品詳情,編號為:$i') ), ) )); }
上面的代碼是主路口文件,主要是在home屬性中,我們使用了ProductList,這個自定義組件,而且時候會報錯,因為我們缺少這個組件。這個組件我們傳遞了一個products參數,也就是商品的列表數據,這個數據是我們用List.generate
生成的。並且這個生成的List原型就是我們剛開始定義的Product這個類(抽象數據)。
ProductList自定義組件的代碼:
class ProductList extends StatelessWidget{ final List<Product> products; ProductList({Key key,@required this.products}):super(key:key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title:Text('商品列表')), body:ListView.builder( itemCount:products.length, itemBuilder: (context,index){ return ListTile( title:Text(products[index].title), onTap:(){ } ); }, ) ); } }
先接受了主方法傳遞過來的參數,接受后用ListView.builder
方法,作了一個根據傳遞參數數據形成的動態列表。
參數的傳遞
還是使用Navigator
組件,然后使用路由MaterialPageRoute
傳遞參數,具體代碼如下。
Navigator.push( context, MaterialPageRoute( builder:(context)=>new ProductDetail(product:products[index]) ) );
子頁面接受參數並顯示
現在需要聲明ProductDetail
這個類(組件),先要作的就是接受參數,具體代碼如下。
class ProductDetail extends StatelessWidget { final Product product; ProductDetail({Key key ,@required this.product}):super(key:key); @override Widget build(BuildContext context) { return new Scaffold( appBar: AppBar( title:Text('${product.title}'), ), body:Center(child: Text('${product.description}'),) ); } }
接受了參數,並把數據顯示在了頁面中。
完成代碼如下:
import 'package:flutter/material.dart'; //傳遞的數據結構,也可以理解為對商品數據的抽象 class Product{ final String title; //商品標題 final String description; //商品描述 Product(this.title,this.description); } void main(){ runApp(MaterialApp( title:'數據傳遞案例', home:ProductList( products:List.generate( 20, (i)=>Product('商品 $i','這是一個商品詳情,編號為:$i') ), ) )); } class ProductList extends StatelessWidget{ final List<Product> products; ProductList({Key key,@required this.products}):super(key:key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title:Text('商品列表')), body:ListView.builder( itemCount:products.length, itemBuilder: (context,index){ return ListTile( title:Text(products[index].title), onTap:(){ Navigator.push( context, MaterialPageRoute( builder:(context)=>new ProductDetail(product:products[index]) ) ); } ); }, ) ); } } class ProductDetail extends StatelessWidget { final Product product; ProductDetail({Key key ,@required this.product}):super(key:key); @override Widget build(BuildContext context) { return new Scaffold( appBar: AppBar( title:Text('${product.title}'), ), body:Center(child: Text('${product.description}'),) ); } }
也可以如下方式,效果是一樣的:
import 'package:flutter/material.dart'; class Product{//抽象類 final String title; //商品標題 final String description; //商品描述 Product(this.title,this.description); } class ProductList extends StatefulWidget{ //接收參數 final List<Product> products; ProductList({Key key,@required this.products}):super(key:key); @override State<StatefulWidget> createState() { return new ProductListState(); } } class ProductListState extends State<ProductList>{ final products = List.generate( 20, (i)=>Product('商品 $i','這是一個商品詳情,編號為:$i') ); @override Widget build(BuildContext context) { return Scaffold( //可以直接用return Scaffold() appBar: AppBar(title:Text('列表頁面')), body: ListView.builder( itemCount:products.length, itemBuilder: (context,index){ return ListTile( title:Text(products[index].title), onTap:(){ Navigator.push( context, MaterialPageRoute(builder:(context) => new ProductDetail(product: products[index]))); } ); }, ) ); } } class ProductDetail extends StatelessWidget{ final Product product; ProductDetail({Key key,@required this.product}):super(key:key); @override Widget build(BuildContext context){ return new Scaffold( appBar: AppBar( title:Text('${product.title}'), ), body:Center(child: Text('${product.description}'),) ); } }
2、頁面跳轉並返回數據
當我們返回頁面時返回結果到上一個頁面(也就是父頁面)。這樣的場景經常用於,我們去子頁面選擇了一項選項,然后把選擇的結果返回給父級頁面。
異步請求和等待
Dart中的異步請求和等待和ES6中的方法很像,直接使用async...await就可以實現。比如下面作了一個找商品的方法,然后進行跳轉,注意這時候是異步的。等待結果回來之后,我們再顯示出來內容。具體代碼如下:
_navigateToXiaoJieJie(BuildContext context) async{ //async是啟用異步方法 final result = await Navigator.push( //等待 context, MaterialPageRoute(builder: (context)=>ItemDetail()) ); //SnackBar是用戶操作后,顯示提示信息的一個控件,類似Tost,會自動隱藏。SnackBar是以Scaffold的showSnackBar方法來進行顯示的 Scaffold.of(context).showSnackBar(SnackBar(content:Text('$result'))); setState(() { showText= '$result'; }); }
SnackBar的使用
SnackBar
是用戶操作后,顯示提示信息的一個控件,類似Tost
,會自動隱藏。SnackBar
是以Scaffold
的showSnackBar
方法來進行顯示的。
Scaffold.of(context).showSnackBar(SnackBar(content:Text('$result')));
返回數據的方式
返回數據其實是特別容易的,只要在返回時帶第二個參數就可以了。
Navigator.pop(context,'xxxx'); //xxx就是返回的參數
我還加了一個showText,方便更好的看清楚效果。代碼如下:
import 'package:flutter/material.dart'; class ItemPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('要編號'),), body: Center( child: RouteButton(), ), ); } } class RouteButton extends StatefulWidget { _RouteButtonState createState() => _RouteButtonState(); } class _RouteButtonState extends State<RouteButton> { String showText = ''; @override Widget build(BuildContext context) { return Container( child: Column( children: <Widget>[ RaisedButton( onPressed: (){ _navigateToXiaoJieJie(context); }, child: Text('要編號'), ), Text(showText), ], ), ); } _navigateToXiaoJieJie(BuildContext context) async{ //async是啟用異步方法 final result = await Navigator.push( //等待 context, MaterialPageRoute(builder: (context)=>ItemDeetail()) ); //SnackBar是用戶操作后,顯示提示信息的一個控件,類似Tost,會自動隱藏。SnackBar是以Scaffold的showSnackBar方法來進行顯示的 Scaffold.of(context).showSnackBar(SnackBar(content:Text('$result'))); setState(() { showText= '$result'; }); } } class ItemDeetail extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('商品編號')), body: Center( child: Column( children: <Widget>[ RaisedButton( child: Text('1號商品'), onPressed: (){ Navigator.pop(context,'1號編號:123'); //第2個參數是返回的參數 }, ), RaisedButton( child: Text('2號商品'), onPressed: (){ Navigator.pop(context,'2號編號:456'); //返回的參數 }, ), ], ), ), ); } }