Flutter如何優雅的使用typedef回撥方法

Flutter小菜雞發表於2020-07-14

作者簡介:Flutter小菜雞,5年經驗移動端開發工程師,努力成為Flutter架構的小菜雞,現就職於某豐某大資料產品開發處,擔任移動端搬磚碼農,專注於移動端資料視覺化研究,目前沒有任何可以拿出來說的成績【手動狗頭】


木本水源篇

旨在簡單介紹問題的來源,或技一項技術的背景

在移動開發中,都避免不了回撥方法callBack(),在Flutter程式設計中也不例外,會用到回撥方法,且最開始dart的語法糖把本菜雞搞得暈頭轉向,今天就探究一下,callBack()在Flutter的幾種實現形式和原理。

不求甚解篇

旨在快速針對問題,給出解決方案,和實現步驟

廢話不多說,直接進入正題,首先在心中默唸一句:Flutter萬物皆元件,dart萬物皆物件。默唸完畢之後開始,介紹dart第一種回撥方式typedef:

typedef

使用姿勢:

首先typedef是一個關鍵字或修飾符,因為dart一切皆物件,方法也可理解為物件,所以typedef也可理解為物件的修飾符,具體意思為: 使用typedef 定義一個函式(或匿名函式),可以使用此函式作為其他函式的引數或返回值

所以這裡本菜雞寫了個小demo來使用一下把函式當做引數傳遞。例子很簡單,對法外狂徒張三做一個性別和年齡的調查。

import 'package:flutter/material.dart';

class CallBackHomePage extends StatefulWidget {
  @override
  _CallBackHomePageState createState() => _CallBackHomePageState();
}

class _CallBackHomePageState extends State<CallBackHomePage> {
  String sexStr = '';
  int ageInt;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('回撥方法demo'),
      ),
      body: Column(
        children: [
          Container(
            child: Text('張三的性別是:$sexStr'),
          ),
          Container(
            child: Text(ageInt == null ? '張三的年齡是:' : '張三的年齡是:$ageInt'),
          ),
          BottomView('張三', (sex) {
            setState(() {
              sexStr = sex;
            });
          },
              (age) => setState(() {
                    ageInt = age;
                  }))
        ],
      ),
    );
  }
}

typedef SexFunc = void Function(String sex);
typedef AgeFunc(int age);

class BottomView extends StatelessWidget {
  final SexFunc sexCallBack;
  final AgeFunc ageCallBack;
  BottomView(String name, this.sexCallBack, this.ageCallBack);
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.yellow,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: [
          RaisedButton(
            onPressed: () {
              sexCallBack('男');
            },
            child: Text('調查性別'),
          ),
          RaisedButton(
            onPressed: () {
              ageCallBack(23);
            },
            child: Text('調查年齡'),
          ),
        ],
      ),
    );
  }
}

複製程式碼

其中可以看到這兩行:

typedef SexFunc = void Function(String sex);
typedef AgeFunc(int age);
複製程式碼

其實這是dart的語法糖,SexFuc方法的縮寫就是下面的AgeFunc的寫法,同樣在回撥傳參的地方也是一個語法糖,如下

BottomView('張三', 
        (sex) {
            setState(() {
              sexStr = sex;
            });
        },
          //等價於上面的寫法
        (age) => setState(() {
                    ageInt = age;
                 })
          )
複製程式碼

兩種方式都可以,跟隨自己的喜好選擇即可。

VoidCallback、ValueChanged

在這裡本菜雞也寫了一下所謂的類似OC中的block方法的回撥方式。

class CenterView extends StatelessWidget {
  VoidCallback sexCallBack;
  ValueSetter<int> ageCallBack;
  CenterView({Key key, this.sexCallBack, this.ageCallBack}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.yellow,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: [
          RaisedButton(
            onPressed: () {
              sexCallBack;
            },
            child: Text('調查性別(VoidCallback)'),
          ),
          RaisedButton(
            onPressed: () {
              ageCallBack(23);
            },
            child: Text('調查年齡(ValueSetter)'),
          ),
        ],
      ),
    );
  }
}
複製程式碼

看一下VoidCallback、ValueChanged 的原始碼可以知道

typedef VoidCallback = void Function()

typedef ValueSetter<T> = void Function(T value)
複製程式碼

本質上VoidCallback、ValueChanged 就是typedef的一種寫法而已,只是Flutter幫我們做了一層封裝

格物致知篇

旨在通過舉例或檢視原始碼,進行原始碼解析,探究某項技術的原理或實現步驟

說起回撥函式,其實回撥函式在我們日常工作中的角色是非比尋常的,回撥函式承擔著頁面元件之間互動動作、資料傳遞等重要的工作,同時回撥方法在Flutter的狀態管理中也是承擔著非常重要的角色。 當資料發生改變時,通過回撥方法可以改變外部變數,再通過setState()方法進行頁面重新整理。

由於typedef只是一個方法的修飾符、關鍵字而已,所以並沒有原始碼可以進行分析,在此我們只對其用法和意義進行一個說明

其實本菜雞理解為:typedef修飾的方法,可以當做類C方法中方法指標,被其修飾過之後的方法本身就可以理解為和正常變數用法一直,可以當做其他方法的輸入引數或返回引數進行傳遞。

由於Flutter頁面(或元件)間的傳值有很多種實現方式,而官方最推崇的也是typedef,所以這裡只對typedef進行了一個簡單的介紹用法。

豹尾小結篇

聊天吹水環節

今天的文章主要對狀態管理進行一個簡單分析,做一個拋磚引玉,下一篇將對Flutter中的狀態管理進行詳細剖析,包括現在已經在用的一些優秀的狀態管理庫和Fluuter內建的狀態管理方法。

害, 又水了一篇文章 :)

我是努力成為Flutter架構的Flutter小菜雞,我為自己帶鹽!

相關文章