Flutter參數的傳遞和接收


上次只寫了方法和參數,這次寫了完整的示例,頁面間參數的傳遞和接收的示例。

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是以ScaffoldshowSnackBar方法來進行顯示的。

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'); //返回的參數
              },
            ),
          ],
        ),
      ),
    );
  }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM