溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Flutter重構(gòu)屬性透傳及函數(shù)透傳如何使用

發(fā)布時間:2023-01-09 09:19:56 來源:億速云 閱讀:92 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“Flutter重構(gòu)屬性透傳及函數(shù)透傳如何使用”的相關(guān)知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Flutter重構(gòu)屬性透傳及函數(shù)透傳如何使用”文章能幫助大家解決問題。

    一、來源

    今天在研究 flutter 相冊庫 wechat_assets_picker 遇到一個問題:(我需要在第三方庫基礎(chǔ)上封裝一個組件,供項目內(nèi)部調(diào)用,組件內(nèi)封裝一些公共邏輯。)但是 AssetPicker.pickAssets 的屬性太多了,一個個傳遞實在太麻煩,就想是否有 vue 中那種數(shù)據(jù)透傳的解決方法呢(已知 flutter 中目前不支持這種屬性透傳)?苦苦思索5分鐘之后,靈光一閃:

    函數(shù)透傳

    /// pickAssets 方法源碼:
    static Future<List<AssetEntity>?> pickAssets(
      BuildContext context, {
      List<AssetEntity>? selectedAssets,
      int maxAssets = 9,
      int pageSize = 80,
      int gridThumbSize = Constants.defaultGridThumbSize,
      int pathThumbSize = 80,
      int gridCount = 4,
      RequestType requestType = RequestType.image,
      List<int>? previewThumbSize,
      SpecialPickerType? specialPickerType,
      Color? themeColor,
      ThemeData? pickerTheme,
      SortPathDelegate<AssetPathEntity>? sortPathDelegate,
      AssetsPickerTextDelegate? textDelegate,
      FilterOptionGroup? filterOptions,
      WidgetBuilder? specialItemBuilder,
      IndicatorBuilder? loadingIndicatorBuilder,
      SpecialItemPosition specialItemPosition = SpecialItemPosition.none,
      bool allowSpecialItemWhenEmpty = false,
      AssetSelectPredicate<AssetEntity>? selectPredicate,
      bool? shouldRevertGrid,
      bool useRootNavigator = true,
      Curve routeCurve = Curves.easeIn,
      Duration routeDuration = const Duration(milliseconds: 300),
    }) async {
    ...

    二、 WechatPhotoPicker 使用示例

    class WechatPhotoPickerDemo extends StatefulWidget {
      WechatPhotoPickerDemo({ Key? key, this.title}) : super(key: key);
      final String? title;
      @override
      _WechatPhotoPickerDemoState createState() => _WechatPhotoPickerDemoState();
    }
    class _WechatPhotoPickerDemoState extends State<WechatPhotoPickerDemo> {
      int maxCount = 9;
      List<AssetEntity> entitys = [];
      GlobalKey<WechatPhotoPickerState> _globalKey = GlobalKey();
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
              title: Text(widget.title ?? "$widget"),
              actions: ['選擇',].map((e) => TextButton(
                child: Text(e,
                  style: TextStyle(color: Colors.white),
                ),
                onPressed: onPicker,
              )).toList(),
            ),
            body: Column(
              children: [
                WechatPhotoPicker(
                  key: _globalKey,
                  selectedAssets: entitys,
                  onChanged: (List<AssetEntity> selectedAssets) {
                    print("selectedAssets: ${selectedAssets.length}");
                  },
                  onPicker: () => AssetPicker.pickAssets(
                      context,
                      maxAssets: 8,
                      selectedAssets: entitys,
                    ),
                )
              ],
            )
        );
      }
      onPicker() async {
        _globalKey.currentState?.onPicker();
        print(entitys.length);
      }
    }

    二、 WechatPhotoPicker 組件源碼

    /// 基于 wechat_assets_picker 的圖片選擇組件
    class WechatPhotoPicker extends StatefulWidget {
      WechatPhotoPicker({
        Key? key,
        this.selectedAssets = const [],
        this.maxCount = 9,
        this.rowCount = 3,
        this.spacing = 10,
        this.decoration,
        this.addBuilder,
        required this.onChanged,
        this.onPicker,
      }) : super(key: key);
      /// 媒體對象數(shù)組
      List<AssetEntity> selectedAssets;
      /// 最大個數(shù)
      int maxCount;
      /// 每行元素個數(shù)
      int rowCount;
      /// 元素間距
      double spacing;
      /// 元素修飾器
      BoxDecoration? decoration;
      /// 添加圖片
      Widget Function(BuildContext context, double itemWidth)? addBuilder;
      /// 確認選擇回調(diào)函數(shù)
      void Function(List<AssetEntity> selectedAssets) onChanged;
      /// 解決flutter數(shù)據(jù)無法透傳的問題(透傳 AssetPicker.pickAssets 方法)
      Future<List<AssetEntity>?> Function()? onPicker;
      @override
      WechatPhotoPickerState createState() => WechatPhotoPickerState();
    }
    class WechatPhotoPickerState extends State<WechatPhotoPicker> {
      @override
      Widget build(BuildContext context) {
        return photoSection(
          selectedAssets: widget.selectedAssets,
          maxCount: widget.maxCount,
          rowCount: widget.rowCount,
          spacing: widget.spacing,
        );
      }
      photoSection({
        List<AssetEntity> selectedAssets = const [],
        int maxCount = 9,
        int rowCount = 3,
        double spacing = 10,
      }) {
        return LayoutBuilder(
            builder: (BuildContext context, BoxConstraints constraints){
              double itemWidth = ((constraints.maxWidth - spacing * (rowCount - 1))/rowCount).truncateToDouble();
              // print("itemWidth: $itemWidth");
              return Wrap(
                  spacing: spacing,
                  runSpacing: spacing,
                  children: [
                    ...selectedAssets.map((e) => Container(
                      clipBehavior: Clip.antiAlias,
                      decoration: widget.decoration ?? BoxDecoration(
                        // border: Border.all(width: 2),
                        borderRadius: BorderRadius.all(Radius.circular(4)),
                      ),
                      child: FadeInImage(
                        width: itemWidth,
                        height: itemWidth,
                        placeholder: AssetImage('images/img_placeholder.png'),
                        image: AssetEntityImageProvider(e, isOriginal: false),
                        fit: BoxFit.cover,
                      ),
                    )).toList(),
                    if (selectedAssets.length < maxCount)
                      InkWell(
                        onTap: () {
                          onPicker();
                        },
                        child: Container(
                          width: itemWidth,
                          height: itemWidth,
                          decoration: BoxDecoration(
                            color: Colors.black.withOpacity(0.1),
                            // border: Border.all(width: 1),
                            borderRadius: BorderRadius.all(Radius.circular(4)),
                          ),
                          child: widget.addBuilder != null ? widget.addBuilder!(context, itemWidth) : Icon(
                            Icons.add, 
                            size: itemWidth/3, 
                            color: Colors.black.withOpacity(0.3),
                          ),
                        ),
                      )
                  ]
              );
            }
        );
      }
      onPicker() async {
        List<AssetEntity>? result = widget.onPicker != null ? await widget.onPicker!() :
        await AssetPicker.pickAssets(
          context,
          maxAssets: widget.maxCount,
          selectedAssets: widget.selectedAssets,
        );
        widget.selectedAssets = result ?? [];
        widget.onChanged(widget.selectedAssets);
        setState(() { });
      }
    }

    總結(jié)

    1、onPicker 參數(shù)需要和調(diào)用方法搭配使用,即實現(xiàn)了函數(shù)透傳,函數(shù)里的參數(shù)直接暴露給外部使用者,做二次定制開發(fā);如果默認參數(shù)(可以適量添加)能夠滿足通用需求,則無需使用 onPicker 可選參數(shù);

      onPicker: () => AssetPicker.pickAssets(
          context,
          maxAssets: 8,
          selectedAssets: entitys,
        ),
        List<AssetEntity>? result = widget.onPicker != null ? await widget.onPicker!() :
        await AssetPicker.pickAssets(
          context,
          maxAssets: widget.maxCount,
          selectedAssets: widget.selectedAssets,
        );

    2、WechatPhotoPickerState,沒有使用下?lián)Q線(私有)實現(xiàn)是為了向外部暴露 State, 可以通過 GlobalKey 獲取 State 實例對象,進而調(diào)用一些封裝方法;達到更高的代碼復用;

    聲明 GlobalKey:

     GlobalKey:<WechatPhotoPickerState> _globalKey = GlobalKey();

    調(diào)用 State 方法:

    _globalKey.currentState?.onPicker();

    3、所有自定義組件原則上都要支持 key 屬性,才是一個完整的組件 Widget;

    無論是移動原生、前端 h6 或者 flutter 跨平臺,各種數(shù)據(jù)透傳的思想是相近,在一端取得突破之后,其他端基本都是平移實現(xiàn),這些可以減少代碼量又不損失功能,而且維護性和擴展性更優(yōu)的實現(xiàn)方式就是代碼重構(gòu)的本質(zhì)。

    關(guān)于“Flutter重構(gòu)屬性透傳及函數(shù)透傳如何使用”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識,可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會為大家更新不同的知識點。

    向AI問一下細節(jié)

    免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI