常用的Flutter第三方库 2022-05-17 周二

简介

不论是iOS开发,还是Android开发,使用第三方库是必不可少的。
现在,切换到Flutter,面临的第一个问题就是该用哪些第三方库?
所有代码都需要自己写?当然不会。

常用的第三方库概览

dependencies:
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.4
  get: ^4.6.3
  flutter_screenutil: ^5.5.2
  linkify: ^4.1.0   #提取链接
  flutter_swiper_plus: ^2.0.4
  validation_textformfield: ^2.2.5
  dio: ^4.0.6
  connectivity_plus: ^2.3.0
  device_info_plus: ^3.2.3
  encrypt: ^5.0.1 #RSA加密
  mz_rsa_plugin: ^0.0.4
  shared_preferences: ^2.0.15
  tab_indicator_styler: ^2.0.0
  webview_flutter: ^3.0.4
  dotted_line: ^3.1.0
  group_button: ^5.0.1
  cart_stepper: ^2.0.2
  badges: ^2.0.2
  flutter_tags_x: ^1.0.0
  flutter_easyrefresh: ^2.2.1
  fbutton_nullsafety: ^5.0.0

flutter和cupertino_icons也算作第三方,由此可见,离开第三方,根本就是寸步难行。
第三方库指定具体的版本是个好习惯;升级应该手动进行,防止静默升级带来不可预料的变故。

GetX

在配置文件中,就是简单的一行get: ^4.6.3,但是这却是除了系统的flutter之外最重要的一个第三方库。这设置改变了一些编程习惯。

  • 把state独立出来,这个太重要了,这把人的习惯转移到状态数据,UI跟随数据自动变化。这和OC中ReactiveCocoa是一个作用。把一个页面分为state、logic、view的想法也很不错。

  • 路由管理。说实话,Flutter的路由管理虽然比Objective-C的原生好那么一点,但仅仅是一点点而已,非常不明显,只是难兄难弟而已。BuiderContext,上下文?什么鬼?什么都是,什么都不是。并且还像个拖油瓶,明明什么用也没有(至少表面上看起来没用),还非要带着,不胜其烦。路由表,动态路由,命名路由,自作主张提供三种模式,你让使用者怎么选?

仅仅统一路由方式,去掉BuiderContext,就值得引入GetX
如果用Flutter自己的路由,我只会选择动态路由一种,其他什么路由表,命名路由,全部滚一边去。想一目了然,比得过iOS原生的故事版吗?Flutter是纯代码写界面,提供这种鸡肋的功能简直是副作用。

网络

  • 一般都会选择Dio;目前这个和Objective-C中的AFNetworking地位差不多
 dio: ^4.0.6
  • 一般外面会套个单例
class DioManager {
  /// *********************************** 实例变量 ***********************************

  Dio dio;
  String dioManageID;

  /// [DioManager]持有的 - 静态的final实例对象, 并进行初始化
  static final DioManager _dioManager = DioManager._instance();

  /// *********************************** 构造函数 ***********************************

  /// [DioManager]私有的 自定义命名式构造方法, Ps:instance不是关键字, 可随意命名
  /// 加 _ 表示该命名式构造函数为[DioManager]私有, 外部是不可调用的,
  /// 从而确保该命名式构造函数的使用, 仅可用来创建 _dioManager 这个静态的final实例对象
  DioManager._instance() {
    dio = Dio();
    dioManageID = "看看ID是啥" + Random().nextInt(1000).toString();
  }

  /// 工厂化的主构造函数 - 返回私有的实例对象
  /// 返回的就是唯一的实例 _dioManager
  factory DioManager() {
    return _dioManager;
  }

  /// *********************************** 实例方法 ***********************************

}

dart中factory关键词的使用
Flutter 单例的写法及理解注释

  • 一般都会配一个网络状态检查的插件
connectivity_plus: ^2.3.0

本地缓存

  • 一般都会选择key-value形式的shared_preferences
shared_preferences: ^2.0.15
  • 使用方式和Objective-C开发的plist读写差不多
// Obtain shared preferences.
final prefs = await SharedPreferences.getInstance();

// Save an integer value to 'counter' key.
await prefs.setInt('counter', 10);
// Save an boolean value to 'repeat' key.
await prefs.setBool('repeat', true);
// Save an double value to 'decimal' key.
await prefs.setDouble('decimal', 1.5);
// Save an String value to 'action' key.
await prefs.setString('action', 'Start');
// Save an list of strings to 'items' key.
await prefs.setStringList('items', <String>['Earth', 'Moon', 'Sun']);

// Try reading data from the 'counter' key. If it doesn't exist, returns null.
final int? counter = prefs.getInt('counter');
// Try reading data from the 'repeat' key. If it doesn't exist, returns null.
final bool? repeat = prefs.getBool('repeat');
// Try reading data from the 'decimal' key. If it doesn't exist, returns null.
final double? decimal = prefs.getDouble('decimal');
// Try reading data from the 'action' key. If it doesn't exist, returns null.
final String? action = prefs.getString('action');
// Try reading data from the 'items' key. If it doesn't exist, returns null.
final List<String>? items = prefs.getStringList('items');

设备信息

  • iOS和Android是不一样的,需要区分设备类型。

  • 可以用device_info_plus这个插件:

device_info_plus: ^3.2.3
  • 一般用来获取设备唯一标识符
  void getDeviceCode() async{
    DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
    if(Platform.isAndroid) {
      AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
      print('设备唯一标识: ${androidInfo.androidId}');
    }else{
      IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
      print('设备唯一标识:${iosInfo.identifierForVendor}');
    }
  }

屏幕适配

  • 接入:
flutter_screenutil: ^5.5.3+1
  • 使用方式和iOS开发的相对布局差异很大
    ScreenUtil().setWidth(540)  (sdk>=2.6 : 540.w)   //根据屏幕宽度适配尺寸
    ScreenUtil().setHeight(200) (sdk>=2.6 : 200.h)   //根据屏幕高度适配尺寸(一般根据宽度适配即可)
    ScreenUtil().radius(200)    (sdk>=2.6 : 200.r)   //根据宽度或高度中的较小者进行调整
    ScreenUtil().setSp(24)      (sdk>=2.6 : 24.sp)   //适配字体
    12.sm   // 取12和12.sp中的最小值

    ScreenUtil.pixelRatio       //设备的像素密度
    ScreenUtil.screenWidth   (sdk>=2.6 : 1.sw)   //设备宽度
    ScreenUtil.screenHeight  (sdk>=2.6 : 1.sh)   //设备高度
    ScreenUtil.bottomBarHeight  //底部安全区距离,适用于全面屏下面有按键的
    ScreenUtil.statusBarHeight  //状态栏高度 刘海屏会更高
    ScreenUtil.textScaleFactor //系统字体缩放比例

    ScreenUtil().scaleWidth  // 实际宽度设计稿宽度的比例
    ScreenUtil().scaleHeight // 实际高度与设计稿高度度的比例

    ScreenUtil().orientation  //屏幕方向

    0.2.sw  //屏幕宽度的0.2倍
    0.5.sh  //屏幕高度的50%
    20.setVerticalSpacing  // SizedBox(height: 20 * scaleHeight)
    20.horizontalSpace  // SizedBox(height: 20 * scaleWidth)
    const RPadding.all(8)   // Padding.all(8.r) - take advantage of const key word
    REdgeInsts.all(8)       // EdgeInsets.all(8.r)
    EdgeInsets.only(left:8,right:8).r // EdgeInsets.only(left:8.r,right:8.r).

轮播图

  • 引入
flutter_swiper_plus: ^2.0.4

*参考文章
flutter_swiper_plus
Flutter 轮播图flutter_swiper的使用

从字符串提取链接

  • 接入
linkify: ^4.1.0   #提取链接
  • 简单使用
import 'package:linkify/linkify.dart';

linkify("Made by https://cretezy.com person@example.com");
// Output: [TextElement: 'Made by ', UrlElement: 'https://cretezy.com' (cretezy.com), TextElement: ' ', EmailElement: 'person@example.com' (person@example.com)]

表单验证

  • 引入
validation_textformfield: ^2.2.5
  • 比如Email验证
EmailValidationTextField(
 whenTextFieldEmpty: "Please enter  email",
 validatorMassage: "Please enter valid email",
 decoration: InputDecoration(
 focusedBorder: OutlineInputBorder(
 borderSide: BorderSide(color: Colors.black, width: 0.5),
),
 enabledBorder: OutlineInputBorder(
 borderSide: BorderSide(color: Colors.black, width: 0.5),
),
 border: OutlineInputBorder(),
 counterText: '',
 hintStyle: TextStyle(color: Colors.black, fontSize: 18.0)),
 textEditingController: txtEmailCtrl,
)

WebView

  • flutter没有WebView,通过插件的方式使用原生的WebView。官方也提供了相关的插件。

  • 引入:

webview_flutter: ^3.0.4
  • 参考文章

webview_flutter
Flutter应用开发之webview_flutter插件

Flutter WebView使用以及分析
flutter_inappwebview

单选框,复选框

  • 引入
group_button: ^5.0.1
  • 单选按钮,复选按钮都是一组组出现的,世界使用CheckBox不是很方便。单选按钮还没有。所以用这个插件就很方便。

  • 使用很方便

GroupButton(
    isRadio: false,
    onSelected: (index, isSelected) => print('$index button is selected'),
    buttons: ["12:00", "13:00", "14:30", "18:00", "19:00", "21:40"],
)
  • 参考文章

group_button

虚线

实线有Divide()但是,虚线却没有,所以需要插件

  • 引入
dotted_line: ^3.1.0
  • 使用很方便,大多数时候用默认的虚线就可以了
import 'package:dotted_line/dotted_line.dart';

DottedLine()
  • 参考文章

dotted_line

购物车加减按钮

购物车加1减1按钮也有插件,真是强大

  • 引入
cart_stepper: ^2.0.2
  • 使用
Widget _buildStepper() {
  return CartStepperInt(
               count: _counter,
               size: 30,
               activeForegroundColor: Colors.purple,
               didChangeCount: (count) {
               setState(() {
                _counter = count;
               });
             },
          );
}
  • 参考文章

cart_stepper: ^2.0.2

小红点

一般用来提示未读消息的数量等等,用得还是比较多的。

  • 引入
badges: ^2.0.2
  • 使用
import 'package:badges/badges.dart';

Badge(
      badgeContent: Text('3'),
      child: Icon(Icons.settings),
    )
  • 参考文章

badges: ^2.0.2

标签

说实话,标签有长有短,流式排列,要做起来还是很麻烦的,幸好有第三方的插件。

  • 引入
flutter_tags_x: ^1.0.0
  • 参看文章

flutter_tags_x: ^1.0.0

上拉刷新下拉加载

就像iOS中的MJRefresh,这是一个很常用的功能,但是系统提供的API很不好用,所以找相应的第三方插件就很迫切。

  • 引入
flutter_easyrefresh: ^2.2.1
  • 参考文章:

flutter_easyrefresh: ^2.2.1

按钮

flutter只提供三种按钮,并且感觉都不好用。大多数时候是用一个手势包含一个Container来实现的。

  • 引入
fbutton_nullsafety: ^5.0.0
  • 参考文章

fbutton_nullsafety: ^5.0.0

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,858评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,372评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,282评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,842评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,857评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,679评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,406评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,311评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,767评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,945评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,090评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,785评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,420评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,988评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,101评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,298评论 3 372
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,033评论 2 355

推荐阅读更多精彩内容