不论是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也算作第三方,由此可见,离开第三方,根本就是寸步难行。
第三方库指定具体的版本是个好习惯;升级应该手动进行,防止静默升级带来不可预料的变故。
在配置文件中,就是简单的一行get: ^4.6.3,但是这却是除了系统的flutter之外最重要的一个第三方库。这设置改变了一些编程习惯。
把state独立出来,这个太重要了,这把人的习惯转移到状态数据,UI跟随数据自动变化。这和OC中ReactiveCocoa是一个作用。把一个页面分为state、logic、view的想法也很不错。
路由管理。说实话,Flutter的路由管理虽然比Objective-C的原生好那么一点,但仅仅是一点点而已,非常不明显,只是难兄难弟而已。BuiderContext,上下文?什么鬼?什么都是,什么都不是。并且还像个拖油瓶,明明什么用也没有(至少表面上看起来没用),还非要带着,不胜其烦。路由表,动态路由,命名路由,自作主张提供三种模式,你让使用者怎么选?
仅仅统一路由方式,去掉BuiderContext,就值得引入GetX
如果用Flutter自己的路由,我只会选择动态路由一种,其他什么路由表,命名路由,全部滚一边去。想一目了然,比得过iOS原生的故事版吗?Flutter是纯代码写界面,提供这种鸡肋的功能简直是副作用。
一个GetX可以替换Bloc,fish_redux,fluro等几个,性价比还是很高的。
多语言,换皮肤,snackbar(其实就是toast),对话框,本地缓存,等等麻烦事也顺手处理了,非常赞。
参考文章:
官网
Flutter GetX 使用 --- 简洁的魅力!
大佬手把手教你优雅地进行Flutter开发(GetX值得一试)
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
一般我们会用到GET,POST等方法,如果封装最顶层的API,有好几个,比较麻烦,所以一般会直接封装第2层的request()方法。具体的封装可以看下面的参考文章。
参考文章:
Flutter Dio源码分析(四)--封装
Flutter Dio源码分析(三)--深度剖析
Flutter Dio源码分析(二)--HttpClient、Http、Dio对比
Flutter Dio源码分析(一)--Dio介绍
shared_preferences: ^2.0.15
// 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
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
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,
)
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"],
)
实线有Divide()但是,虚线却没有,所以需要插件
dotted_line: ^3.1.0
import 'package:dotted_line/dotted_line.dart';
DottedLine()
购物车加1减1按钮也有插件,真是强大
cart_stepper: ^2.0.2
Widget _buildStepper() {
return CartStepperInt(
count: _counter,
size: 30,
activeForegroundColor: Colors.purple,
didChangeCount: (count) {
setState(() {
_counter = count;
});
},
);
}
一般用来提示未读消息的数量等等,用得还是比较多的。
badges: ^2.0.2
import 'package:badges/badges.dart';
Badge(
badgeContent: Text('3'),
child: Icon(Icons.settings),
)
说实话,标签有长有短,流式排列,要做起来还是很麻烦的,幸好有第三方的插件。
flutter_tags_x: ^1.0.0
就像iOS中的MJRefresh,这是一个很常用的功能,但是系统提供的API很不好用,所以找相应的第三方插件就很迫切。
flutter_easyrefresh: ^2.2.1
flutter只提供三种按钮,并且感觉都不好用。大多数时候是用一个手势包含一个Container来实现的。
fbutton_nullsafety: ^5.0.0
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我需要在rail3中使用标准注册/登录/忘记密码功能进行身份验证。是否有大多数人为此使用的插件或其他东西? 最佳答案 我不确定最常用的方法是什么-但可以肯定的是,Plataformatec的“Devise”是一个非常流行的方法:http://github.com/plataformatec/devise我已经尝试了一些authgem,对我来说,它是最简单的设置和修改以满足我的需要。它内置了密码恢复、帐户确认(如果需要)和其他一些非常方便的功能。 关于ruby-on-rails-在Rail
我有两个文本文件,master.txt和926.txt。如果926.txt中有一行不在master.txt中,我想写入一个新文件notinbook.txt。我写了我能想到的最好的东西,但考虑到我是一个糟糕的/新手程序员,它失败了。这是我的东西g=File.new("notinbook.txt","w")File.open("926.txt","r")do|f|while(line=f.gets)x=line.chompifFile.open("master.txt","w")do|h|endwhile(line=h.gets)ifline.chomp!=xputslineendende
我在ruby表单中有一个提交按钮f.submitbtn_text,class:"btnbtn-onemgt12mgb12",id:"btn_id"我想在不使用任何javascript的情况下通过ruby禁用此按钮 最佳答案 添加disabled:true选项。f.submitbtn_text,class:"btnbtn-onemgt12mgb12",id:"btn_id",disabled:true 关于ruby-on-rails-如何在Rails中添加禁用的提交按钮,我们在St
关闭。这个问题是off-topic.它目前不接受答案。想改进这个问题吗?Updatethequestion所以它是on-topic用于堆栈溢出。关闭11年前。Improvethisquestion我不经常使用ruby-通常它加起来相当于每两个月或更长时间编写一次脚本。我的大部分编程都是使用C++进行的,这与ruby有很大不同。由于我与ruby之间的差距如此之大,我总是忘记语言的基本方面(比如解析文本文件和其他简单的东西)。我想每天练习一些基本的东西,我想知道是否有一些我可以订阅的网站,并且会向我发送当天的Ruby问题或类似的东西。有人知道这样的站点/Internet服务吗?
3月26日,映宇宙(HK:03700,即“映客”)发布截至2022年12月31日的2022年度业绩财务报告。财报显示,映宇宙2022年的总营收为63.19亿元,较2021年同期的91.76亿元下降31.1%。2022年,映宇宙的经营亏损为4698.7万元,2021年同期则为净利润4.57亿元;期内亏损(净亏损)为1.68亿元,2021年同期的净利润为4.33亿元;非国际财务报告准则经调整净利润为3.88亿元,2021年同期为4.82亿元,同比下降19.6%。 映宇宙在财报中表示,收入减少主要是由于行业竞争加剧,该集团对旗下产品采取更为谨慎的运营策略以应对市场变化。不过,映宇宙的毛利率则有所提升
电脑上可以截取图片吗?如果可以,该如何操作呢?相信很多小伙伴都只知道一两种截图的方式,知道的并不全面。其实,电脑上有多种方式截图的,而且非常方便。电脑怎么截图?今天我们就来教大家如何使用电脑截取图片的8种常用方式!操作环境:演示机型:Delloptiplex7050系统版本:Windows10方法一:系统自带截图具体操作:同时按下电脑的自带截图键【Windows+shift+S】,可以选择其中一种方式来截取图片:截屏有矩形截屏、任意形状截屏、窗口截屏和全屏截图。 方法二:QQ截图具体操作:在电脑登录QQ,然后同时按下【Ctrl+Alt+A】,可以任意截图你需要的界面,可以把截图的页面直接下载,
我已经安装了最新版本的compass、sass和susy。但我仍然收到此错误:Unabletoactivatesusy-2.1.1,becausesass-3.2.17conflictswithsass(~>3.3.0)有人知道这个Ruby是如何工作的吗?这是我安装的gem的列表:***LOCALGEMS***CFPropertyList(2.2.0)chunky_png(1.3.0)compass(0.12.4)compass-core(1.0.0.alpha.19)compass-import-once(1.0.4)compass-rails(1.1.3)fssm(0.2.10)l
1.Scenes游戏场景文件夹用于放置unity的场景文件 2.Plugins插件文件夹用于放置unity的依赖文件,例如dll 3.Scripts脚本文件夹用于放置unity的c#脚本文件 4.Resources游戏资源文件夹用于放置unity的各种游戏资源,比如images,prefabs,同时只有放到Resources文件夹的游戏资源才能使用Resource.load(资源路径不加后缀)加载到游戏内存中进行使用 5.EditorUnity编辑器扩展脚本文件夹usingUnityEditor;这个名称空间就是Unity编辑器的名称空间这个名称空间提供了扩展Unity编辑器的各种类 【你所有
如何用IDEA2022创建并初始化一个SpringBoot项目?目录如何用IDEA2022创建并初始化一个SpringBoot项目?0. 环境说明1. 创建SpringBoot项目 2.编写初始化代码0. 环境说明IDEA2022.3.1JDK1.8SpringBoot1. 创建SpringBoot项目 打开IDEA,选择NewProject创建项目。 填写项目名称、项目构建方式、jdk版本,按需要修改项目文件路径等信息。 选择springboot版本以及需要的包,此处只选择了springweb。 此处需特别注意,若你使用的是jdk1