【Flutter】之便于提高开发效率的周边库和轮子

news2024/11/19 2:19:50

GetX 状态管理

GetX包含很多功能,各种弹出widget、路由管理、国际化、Utils、状态管理等。

基于路由管理

1. 添加到项目中

1.1. 将此添加到pubspec.yaml文件中。

get: 4.1.4 

1.2. 在命令行中运行

flutter packages get 

1.3. 在MaterialApp前面加上 “Get”,就可以把它变成GetMaterialApp

GetMaterialApp( home: MyHome(),
) 

2. 具体的路由使用场景:

2.1 导航到新的页面。

Get.to(NextScreen()); 

2.2 关闭SnackBars、Dialogs、BottomSheets或任何你通常会用Navigator.pop(context)关闭的东西。

Get.back(); 

2.3进入下一个页面,但没有返回上一个页面的选项(用于SplashScreens,登录页面等)。

Get.off(NextScreen()); 

2.4 进入下一个界面并取消之前的所有路由(在购物车、投票和测试中很有用)。

Get.offAll(NextScreen()); 

2.5 要导航到下一条路由,并在返回后立即接收或更新数据。

var data = await Get.to(Payment()); 

2.6 在另一个页面上,发送前一个路由的数据。并使用它,例:

Get.back(result: 'success');
if(data == 'success') madeAnything(); 

2.7 与标准导航的关系 , 只要把 Navigator(大写)改成 navigator(小写),就可以拥有标准导航的所有功能,而不需要使用context // 默认的Flutter导航

Navigator.of(context).push(context,MaterialPageRoute(builder: (BuildContext context) {return HomePage();},),
); 

// 使用Flutter语法获得,而不需要context。

navigator.push(MaterialPageRoute(builder: (_) {return HomePage();},),
); 

// get语法 (这要好得多)

Get.to(HomePage()); 

dio:http 请求库

dio是一个强大的Dart Http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时、自定义适配器等…

1. 添加到项目中

1.1. 将此添加到pubspec.yaml文件中。

dio: ^4.0.6
dio_cookie_manager: ^2.0.0
cookie_jar: ^3.0.1 

1.2. 在命令行中运行

flutter packages get 

2.具体的使用

一个极简的示例:

import 'package:dio/dio.dart';
void getHttp() async {try {var response = await Dio().get('http://www.google.com');print(response);} catch (e) {print(e);}
} 

项目中的使用:

config.dart

统一管理请求接口的url地址

 // api地址前缀static String imApiUrl() {return 'https://xxxxxx.xxxxx.com/api/users';} // 接口列表 
class Urls {static var register = "${Config.imApiUrl()}/register";static var login = "${Config.imApiUrl()}/login";static var getCode = "${Config.imApiUrl()}/getCode";static var verifiCode = "${Config.imApiUrl()}/verifiCode";static var setNewPwd = "${Config.imApiUrl()}/setNewPwd";
} 

api_resp.dart

对接口返回的数据,进行统一数据类型校验

class ApiResp {int? code;String? msg;dynamic data;ApiResp.fromJson(Map<String, dynamic> map) {code = map["code"];msg = map["msg"];data = map["data"] ?? {};}Map<String, dynamic> toJson() {final data = <String, dynamic>{};data['code'] = code;data['msg'] = msg;data['data'] = data;return data;}
} 

api_interceptor.dart

对于请求的拦截

import 'package:dio/dio.dart';
import 'config.dart';
import 'api_resp.dart';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';

Dio dio = Dio();

class HttpUtil {HttpUtil._();static void init() {dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {return handler.next(options);}, onResponse: (response, handler) {return handler.next(response);}, onError: (DioError e, handler) {return handler.next(e);}));dio.interceptors.add(CookieManager(CookieJar()));// 配置dio实例dio.options.baseUrl = Config.imApiUrl();dio.options.connectTimeout = 30000;dio.options.receiveTimeout = 30000;}// post 请求static Future<Map<String, dynamic>> post(String path, {dynamic data,Map<String, dynamic>? queryParameters,Options? options,CancelToken? cancelToken,ProgressCallback? onSendProgress,ProgressCallback? onReceiveProgress,}) async {try {var result = await dio.post<Map<String, dynamic>>(path,data: data,queryParameters: queryParameters,options: options,cancelToken: cancelToken,onSendProgress: onSendProgress,onReceiveProgress: onReceiveProgress,);print(result);var resp = ApiResp.fromJson(result.data!);// 成功返回if (resp.code == 0) {var response = {"data": resp.data, "code": resp.code, "msg": resp.msg};return response;} else {// 业务报错return Future.error((resp.msg).toString());}} catch (error) {// 网络报错if (error is DioError) {} else {}return Future.error(error);}}// get请求static Future<Map<String, dynamic>> get(String path, {Map<String, dynamic>? queryParameters,Options? options,CancelToken? cancelToken,ProgressCallback? onReceiveProgress,}) async {try {var result = await dio.get<Map<String, dynamic>>(path,queryParameters: queryParameters,options: options,cancelToken: cancelToken,onReceiveProgress: onReceiveProgress,);var resp = ApiResp.fromJson(result.data!);// 成功返回if (resp.code == 0) {var response = {"data": resp.data ?? {},"code": resp.code,"msg": resp.msg};return response;} else {// 业务报错return Future.error(resp);}} catch (error) {// 网络报错if (error is DioError) {} else {}return Future.error(error);}}
} 

apis.dart

请求的接口管理

import 'package:cookie_jar/cookie_jar.dart';
import 'config.dart';
import 'api_interceptor.dart';

class Api {static final CookieJar cookieJar = CookieJar();
}

class Apis {
// 注册static Future<dynamic> register({required String account,required String password,required String code,required String mobile,}) async {Map<dynamic, dynamic> response;response = (await HttpUtil.post(Urls.register, data: {"account": account,"password": password,"mobile": mobile,"code": code}));return response;}

// 获取验证码 static Future<dynamic> getCode({required mobile}) async {Map<String, dynamic> response;response =await HttpUtil.get(Urls.getCode, queryParameters: {"mobile": mobile});return response;}// 校对验证码static Future<dynamic> verifiCode({required mobile, required code}) async {Map<String, dynamic> response;response = await HttpUtil.post(Urls.verifiCode,data: {"mobile": mobile, "code": code});return response;}// 设置新密码static Future<dynamic> setNewPwd({required mobile, required password, required code}) async {Map<String, dynamic> response;response = await HttpUtil.post(Urls.setNewPwd,data: {"mobile": mobile, "password": password, "code": code});return response;}
} 

国际化

flutter项目中国际化是必不可少的

1. 添加到项目中

1.1. 将此添加到pubspec.yaml文件中。

flutter_localizations:sdk: flutter
intl: ^0.17.0
flutter_intl:enabled: true 

1.2. 在命令行中运行

flutter packages get 

2. 在项目中使用

main.dart中添加国际化

@overrideWidget build(BuildContext context) {return GetMaterialApp( ...// 以下是国际化需要添加的代码localizationsDelegates: const [GlobalMaterialLocalizations.delegate,GlobalWidgetsLocalizations.delegate,GlobalCupertinoLocalizations.delegate,S.delegate], // 中文为首选项,修改后需重启locale: const Locale('zh', 'CN'),supportedLocales: [...S.delegate.supportedLocales],  ...);} 

下载完成后,会自动生生以下文件夹

  • generated是自动生成的dart代码
  • I10n是对应的arb文件目录

编辑对于同一个词汇,在不同环境对应的内容:

English:

{"hello": "hello"
} 

中文:

{"hello": "你好"
} 

在代码中的使用:

import 'package:flutter/material.dart';

// 引入文件
import 'package:im_flutter_demo/generated/l10n.dart';

class FirstScreen extends StatelessWidget {FirstScreen({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(body: Center(child: Text(// 添加文字S.of(context).hello,),),);}
} 

WaterMark 水印

水印组件

可以设置行和列的数量、角度以及显示的文字。

import 'package:flutter/material.dart';

class WatermarkWidget extends StatelessWidget {final int rowCount;final int columnCount;final String text;const WatermarkWidget({Key? key,required this.rowCount,required this.columnCount,required this.text,}) : super(key: key);@overrideWidget build(BuildContext context) {return IgnorePointer(child: Container(margin: const EdgeInsets.only(top: 80, bottom: 80),child: Column(children: creatColumnWidgets(),),),);}

// 行List<Widget> creatRowWdiges() {List<Widget> list = [];for (var i = 0; i < rowCount; i++) {final widget = Expanded(child: Center(child: Transform.rotate(angle: 120,child: Text(text,style: const TextStyle(color: Color.fromARGB(35, 0, 0, 0),fontSize: 16,decoration: TextDecoration.none)))));list.add(widget);}return list;}

// 列List<Widget> creatColumnWidgets() {List<Widget> list = [];for (var i = 0; i < columnCount; i++) {final widget = Expanded(child: Row(children: creatRowWdiges(),));list.add(widget);}return list;}
} 

如何使用水印

import 'package:flutter/material.dart';
import 'package:im_flutter_demo/src/widgets/water1.dart';

class Index extends StatefulWidget {const Index({Key? key}) : super(key: key);@overrideState<Index> createState() {return TextWaterMarkPainterState();}
}

class TextWaterMarkPainterState extends State<Index> {OverlayEntry? overlayEntry;@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('测试水印')),body: Center(child: Column(crossAxisAlignment: CrossAxisAlignment.center,children: [ElevatedButton(child: const Text("添加水印"),onPressed: () {addWaterMarkter(context, "张三 13800138000", 2, 4);},),ElevatedButton(child: const Text("移除水印"),onPressed: () {removeWatermark();},),],),),);}// 添加水印void addWaterMarkter(BuildContext context, String string, int row, int column) async {OverlayState? overlayState = Overlay.of(context);if (overlayEntry == null) {overlayEntry = OverlayEntry(builder: (context) => WatermarkWidget(rowCount: row,columnCount: column,text: string,));overlayState?.insert(overlayEntry!);}}// 移除水印void removeWatermark() async {if (overlayEntry != null) {overlayEntry!.remove();overlayEntry = null;}}
} 

添加后的效果:


移动端适配 flutter_screenutil

 flutter_screenutil: ^5.5.3+2 

如何使用:

定义页面尺寸常量

 static const uIW = 375.0;
 static const uIH = 812.0; 

main.dart 中添加,使全局生效

 @overrideWidget build(BuildContext context) {return ScreenUtilInit(designSize: const Size(Config.uIW, Config.uIH),minTextAdapt: true,splitScreenMode: true,builder: (context, child) {returnMaterialApp(title: '名称',builder: EasyLoading.init(),...)});} 

在布局时如何使用:

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

class FirstScreen extends StatelessWidget FirstScreen({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(body: Center(child: SizedBox(width: 100.w,height: 100.h,)),);}
} 

图片预览

常用于头像预览,图片预览等场景。

 photo_view: ^0.13.0 

根据使用场景封装组件:

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:photo_view/photo_view.dart';

// 单图片预览
class PhotoViewSimpleScreen extends StatelessWidget {const PhotoViewSimpleScreen({Key? key,required this.imageProvider, //图片required this.heroTag, //hero动画tagid , 不设置或null为不启用hero动画this.loadingChild, //加载时的widgetthis.backgroundDecoration = const BoxDecoration(color: Colors.black), //背景修饰this.minScale, //最大缩放倍数this.maxScale, //最小缩放倍数}) : super(key: key);final ImageProvider imageProvider;final LoadingBuilder? loadingChild;final BoxDecoration backgroundDecoration;final dynamic minScale;final dynamic maxScale;final String heroTag;@overrideWidget build(BuildContext context) {return Scaffold(body: Container(constraints: BoxConstraints.expand(height: MediaQuery.of(context).size.height,),child: Stack(children: <Widget>[Positioned(top: 0,left: 0,bottom: 0,right: 0,child: PhotoView(imageProvider: imageProvider,loadingBuilder: loadingChild,backgroundDecoration: backgroundDecoration,minScale: minScale,maxScale: maxScale,heroAttributes: PhotoViewHeroAttributes(tag: heroTag),enableRotation: true, //是否允许旋转),),GestureDetector(onTap: () {// print('context:$context');Get.back();},)],),),);}
} 

具体使用:

...
showDialog(barrierColor: Colors.black,context: context,builder: (context) {return const PhotoViewSimpleScreen(imageProvider: NetworkImage('https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e5677df5f1fe4df2b266273c3188ea37~tplv-k3u1fbpfcp-watermark.image?',),heroTag: 'simple');}
)
... 

列表展示:

预览效果:


CSS Colors 颜色

CSS Colors package

此包定义CSS颜色的颜色常量。这些颜色常量使用dart:ui中的color类,这意味着它们对Flutter应用程序很有用。

1. 在 pubspec.yaml,添加依赖 css-colors

css_colors: ^1.0.0 

2. 在命令行中运行

flutter packages get 

3. 具体使用

import 'package:css_colors/css_colors.dart';
// 这个就是上面下载的package

import 'package:flutter/material.dart';

void main() {runApp(const APage());
}

class APage extends StatelessWidget {const APage({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return const MaterialApp(home: DemoPage(),);}
}

class DemoPage extends StatelessWidget {const DemoPage({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(body: Container(color: CSSColors.orange));}
} 

显示页面:

最后

最近还整理一份JavaScript与ES的笔记,一共25个重要的知识点,对每个知识点都进行了讲解和分析。能帮你快速掌握JavaScript与ES的相关知识,提升工作效率。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/107025.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

centos7 yum安装postgreSQL

安装环境centos7.6 安装步骤&#xff1a; 1、安装postgresql&#xff1a; yum install postgresql-server 2、安装postgresql 扩展包&#xff1a; yum install postgresql-contrib 3、初始化&#xff1a; postgresql-setup initdb 4、启动开机自启动&#xff1a; systemc…

说话人识别神经网络推理方式

概述 说话人识别是一个序列总结&#xff08;Sequence Summarization&#xff09;任务&#xff0c;输入是音频&#xff08;或者说&#xff0c;声学特征的序列&#xff09;&#xff0c;输出是说话人的嵌入码&#xff0c;有的神经网络可以输入一对音频&#xff0c;直接输出这对音…

java微信支付v3系列——9.微信支付之商家转账API

这个功能就比较复杂了&#xff0c;首先是得有90天的资金流水才能开通&#xff0c;其次开通后还需要在官网进行配置&#xff0c;不能直接调用&#xff0c;并且限制了IP地址。 如下图所示&#xff0c;首先需要进行产品设置&#xff0c;将里面都设置好后才能进行开发&#xff0c;…

feign 调用常见问题避坑指南!

摘要&#xff1a;主要是总结了一下这段时间在使用 feign 的过程中的遇到的一些坑点。一、Get请求自动转化成POST的问题1、client 请求参数没有加上 RequestParam 注解问题代码&#xff1a;GetMapping("/showName") String showName(String name);错误提示&#xff1a…

让 APISpace 告诉你什么场景使用什么API

Q1&#xff1a;某商家打算搞年底促销活动&#xff0c;需要将活动信息通过短信的形式通知给用户&#xff0c;这个场景可以用什么接口&#xff1f; 发送通知类的短信&#xff0c;可以使用 通知短信 API~ 通知短信&#xff0c;支持三大运营商&#xff0c;虚拟运营商短信发送&…

第14章 并发控制与恢复

第14章 并发控制与恢复 考试范围&#xff1a; 14.1-14.3, 14.8-14.11 考试题型&#xff1a; 事务操作 考试内容&#xff1a; 1、锁/共享锁/排它锁的概念 2、多粒度锁 Multiple Granularity 3、两阶段封锁协议 The Two-Phase Locking Protocol 两段锁协议是指同一事务对任何…

2.前端笔记-JS-JS3种书写位置、注释、输入输出

书写位置 行内式嵌入式外部文件引入 1、行内式JS 可以将单行或少量的JS代码写在HTML标签的事件属性中&#xff08;以on开头的属性&#xff09;&#xff0c;如onclick单双引号使用&#xff1a;HTML中推荐双引号&#xff0c;JS中推荐单引号&#xff0c;如 <input type&quo…

vue实现将自己网站(h5链接)分享到微信中形成小卡片(超详细)

大家好&#xff0c;我是雄雄。 前言 我们在分享公众号信息到微信或者群中的时候&#xff0c;会出现一个小卡片&#xff0c;如下所示&#xff1a; 但是呢&#xff0c;这种小卡片只能走微信的接口来实现&#xff0c;比如我们从公众号、小程序中分享的内容可以是这样的。如果我们…

0基础转行,四个月,改变了我的人生!

转行对于很多人而言都是一个新的开始&#xff0c;但有的人是决定了立马去做&#xff0c;而有的人则是犹犹豫豫&#xff0c;我考虑考虑吧、还没有决定好、过段时间再说吧…… 就这样&#xff0c;相似情况的两个人&#xff0c;最后有了不同的结果。 很多人总是以我很忙、学历不高…

自学100天,零基础转行软件测试,我要以更好的姿态奔赴下一场山海!

三年大专一场空 专业是电子商务&#xff0c;18年毕业&#xff0c;当时在报考时时觉得电子商务挺高大上的&#xff0c;觉得电商肯定会有前途&#xff0c;以后毕业肯定好找工作&#xff0c;跟大多数人一样&#xff0c;我开始幻想我以后毕业以后的纸醉金迷的生活&#xff0c;我以…

模数转换器ADC

模数转换器ADC F28335内部的ADC模块是一个12位分辨率的、具有流水线结构的模数转换器,其结构框图如图11-1所示。从图11-1可以看到,F28335的ADC模块一共具有16个采样通道,分成了两组,一组为ADCINAO~ ADCINA7,另一组为ADCINBO~ADCINB7。A组的通道使用采样保持器A,也就是图…

【SCI论文解读复现NO.1】基于Transformer-YOLOv5的侧扫声纳图像水下海洋目标实时检测

前言 此前出了目标改进算法专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读最新目标检测算法论文&#xff0…

【小学信息技术教资面试】《制作通讯录》教案

1.题目&#xff1a;制作通讯录 2.内容&#xff1a; 3.基本要求&#xff1a; &#xff08;1&#xff09;使用任务驱动法进行教学。 &#xff08;2&#xff09;掌握表格的插入和信息的填写。 &#xff08;3&#xff09;试讲时间是10分钟。 《制作通讯录》教案 一、教学目标&am…

我国核桃种植深加工行业供给较为充足 未来大健康消费时代将带来广阔市场

根据观研报告网发布的《2022年中国核桃种植深加工行业分析报告-行业竞争策略与发展动向研究》显示&#xff0c;核桃加工分为初加工与深加工。其中核桃深加工包括核桃油的压榨、核桃蛋白粉的制备、以核桃仁为原料生产休闲食品、以核桃青皮、壳等为原料生产加工日化产品等&#x…

Java agent 使用

一、前言 于一个即将上线的应用来说&#xff0c;系统监控是必不可少的&#xff0c;为什么需要监控呢&#xff1f;应用是跑在服务器上的&#xff0c;应用在运行过程中会发生各自意想不到的问题&#xff0c;像大家熟知的OOM&#xff0c;mysql故障&#xff0c;服务器宕机&#xff…

SpringBoot+Vue实现前后端分离的教务评教系统

文末获取源码 开发语言&#xff1a;Java 使用框架&#xff1a;spring boot 前端技术&#xff1a;JavaScript、Vue.js 、css3 开发工具&#xff1a;IDEA/MyEclipse/Eclipse、Visual Studio Code 数据库&#xff1a;MySQL 5.7/8.0 数据库管理工具&#xff1a;phpstudy/Navicat JD…

将spark的数据保存到MySQL

文章目录前言环境的准备是必要的下载解压放置文件代码书写注意事项结束语前言 我们用spark对数据进行分析和提取数据后要对得到的数据进行保存接下来的内容是将数据保存到MySQL数据库中 环境的准备是必要的 下载 &#xff08;本小博主已经为看官大人准备好了下载地址点击下载…

【JVM实战系列】「监控调优体系」实战开发arthas-spring-boot-starter监控你的微服务是否健康

前提介绍 相信如果经历了我的上一篇Arthas的文章[【JVM实战系列】「监控调优体系」针对于Alibaba-Arthas的安装入门及基础使用开发实战指南]之后&#xff0c;相信你对Arthas的功能和使用应该有了一定的理解了。那么我们就要进行下一步的探索功能。 Arthas对于SpringBoot2的支…

无效回表谁的锅?存储引擎:这事儿不赖我

明确场景 要回答这个问题&#xff0c;我们一般分几步来走&#xff1a; 1.确认问题&#xff0c;对齐Sql语句&#xff1b; 2.解答问题本身&#xff0c;也就是时间复杂度分析&#xff1b; 3.针对本身提出这个场景&#xff0c;可能出现的性能瓶颈进行分析&#xff1b; 4.针对瓶…

vue+element模仿腾讯视频电影网站

一.布局设计 官方图例&#xff1a; demo效果&#xff1a; 顶部1&#xff1b;左侧菜单栏2&#xff1b;右侧内容展示区3&#xff1b; 关键点&#xff1a; 顶部固定&#xff0c;不随页面滚动而滚动&#xff1b;左侧可局部滚动显示更多菜单&#xff1b;右侧局部滚动&#xff…