一个完整的Flutter项目的基本构成

目录

  • 1.页面跳转
  • 2.本地数据库和读取
      • 2.1 在pubspec.yaml中添加数据库框架依赖
      • 2.2 创建db.dart 初始化数据库并创建表
      • 2.3 安装JsonToDart插件
      • 2.4 创建实体类 user_bean.dart
      • 2.5 增删改查:
  • 3.网络请求+数据解析+UI渲染

本篇主要总结下一个完整的Flutter项目有哪些基本构成?
一般来说数据需要展示到页面上面大概需要:

网络请求+数据解析+UI渲染、
本地数据库、
页面跳转导航等

下面一点点开始构建

1.页面跳转

创建my_routers.dart 定义Router

class MyRouter{static const String DOWNLOAD_PAGE = "/DownLoadPage";static const String LANG_PAGE = "/LangPage";}

main.dart 中配置routes

class MyApp extends StatelessWidget {final Locale locale;const MyApp(this.locale, {super.key});// This widget is the root of your application.@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',routes: {MyRouter.DOWNLOAD_PAGE: (context) => DownLoadPage(),MyRouter.LANG_PAGE: (context) => LangPage(),},);}
}

执行跳转

  Navigator.pushNamed(context, MyRouter.DOWNLOAD_PAGE);

2.本地数据库和读取

2.1 在pubspec.yaml中添加数据库框架依赖

  sqflite: ^2.3.0

(简单数据保存可用 shared_preferences: ^2.2.2

2.2 创建db.dart 初始化数据库并创建表

import 'package:sqflite/sqflite.dart';//在Flutter中,创建表时可以使用以下数据类型:
//
// INTEGER:整数类型,可以存储整数值。
// REAL:浮点数类型,可以存储浮点数值。
// TEXT:文本类型,可以存储字符串值。
// BLOB:二进制类型,可以存储任意二进制数据。
// 此外,还可以使用以下修饰符来定义表中的列:
//
// PRIMARY KEY:主键修饰符,用于指定列作为主键。
// AUTOINCREMENT:自增修饰符,用于指定主键列自动增加。
// NOT NULL:非空修饰符,用于指定列的值不能为空。
// UNIQUE:唯一修饰符,用于指定列的值不能重复。class DatabaseHelper {static Database? _database;//数据库名称static const String _dbName = 'demo.db';//数据库版本,如果表结构修改,需要增加static const int _dbVersion = 2;Future<Database> get database async {if (_database != null) {return _database!;}_database = await _initDatabase();return _database!;}Future<Database> _initDatabase() async {return await openDatabase(_dbName, version: _dbVersion,onCreate: (db, version) async {String studentSQL = '''CREATE TABLE Students (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT NOT NULL,age INTEGER,gpa REAL)''';String userSQL = '''CREATE TABLE User (id INTEGER PRIMARY KEY,name TEXT NOT NULL,age INTEGER)''';await db.execute(userSQL);await db.execute(studentSQL);}, onUpgrade: (db, oldVersion, newVersion) async {if (oldVersion == 1 && newVersion == 2) {//修改表结构await db.execute('ALTER TABLE User ADD sex TEXT');}});}//获取所有表Future<List<Map<String, dynamic>>> getAllTables() async {final Database db = await database;return db.rawQuery("SELECT name FROM sqlite_master WHERE type='table'");}// 测试test() async {DatabaseHelper databaseHelper = DatabaseHelper();List<Map<String, dynamic>> tables = await databaseHelper.getAllTables();tables.forEach((table) {print("当前数据中的表:${table['name']}");});}
}

表创建好了,该增删改查了。

2.3 安装JsonToDart插件

我们先安装一个解析json数据插件:JsonToDart
在这里插入图片描述
Android Studio - File - Settings - Plugins 搜索JsonToDart安装重启Android Studio即可
安装好以后创建一个Bean文件:user_bean.dart 来接收数据

2.4 创建实体类 user_bean.dart

在lib下创建bean文件夹
对着lib/bean文件夹右键 选择 new - JsonToDart 输入json数据即可生成如下文件

import 'dart:convert';UserBean userBeanFromJson(String str) => UserBean.fromJson(json.decode(str));String userBeanToJson(UserBean data) => json.encode(data.toJson());class UserBean {UserBean({this.id,this.name,this.age,});UserBean.fromJson(dynamic json) {id = json['id'];name = json['name'];age = json['age'];}num? id;String? name;num? age;UserBean copyWith({num? id,String? name,num? age,}) =>UserBean(id: id ?? this.id,name: name ?? this.name,age: age ?? this.age,);Map<String, dynamic> toJson() {final map = <String, dynamic>{};map['id'] = id;map['name'] = name;map['age'] = age;return map;}
}

2.5 增删改查:

//增加var db = await DatabaseHelper().database;int id = await db.insert('User', userBean.toJson(),   //插入冲突策略(如果同样的对象被插入两次,则后者替换前者)conflictAlgorithm: ConflictAlgorithm.replace);Log.i("添加成功,id = : $id");//删除//where中的第一个?对应whereArgs数组的第一个var re = await db.delete('Wallet', where: 'id = ?', whereArgs: [1]);Log.i("删除成功 ===  $re");//修改var db = await DatabaseHelper().database;List list = await db.query("User");var wList = list.map((e) => UserBean.fromJson(e)).toList();var w = wList[0];w.name = "feifei";var re = await db.update('User', w.toJson(),where: 'id = ?', whereArgs: [w.id]);Log.i("修改成功 ===  $re");//查询List list = await db.query("User");var wList = list.map((e) => UserBean.fromJson(e)).toList();var w = wList[0];

3.网络请求+数据解析+UI渲染

pubspec.yaml中引入依赖:

  dio: ^5.3.3

创建http.dart 简单封装dio

import 'package:dio/dio.dart';
import 'app_urls.dart';class Http {static Dio? _dio;static Http of({String? baseUrl}) {return Http._initDio(baseUrl: baseUrl);}Http._initDio({String? baseUrl}) {if (_dio == null) {_dio = Dio();Iterable<Interceptor> iterable = [LogInterceptor(requestBody: true, responseBody: true),];_dio?.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {// 在请求被发送之前做一些事情// 设置公共headeroptions.headers.addAll({'au_header': '1'});// 设置公共参数//options.queryParameters.addAll({'token': 'your_token'});return handler.next(options); // 必须调用 next 方法},onResponse: (response, handler) {// 在响应被处理之前做一些事情return handler.next(response); // 必须调用 next 方法},onError: (DioError e, handler) {// 在请求发生错误时做一些事情return handler.next(e); // 必须调用 next 方法},));_dio?.interceptors.addAll(iterable);}var options = BaseOptions(baseUrl: baseUrl ?? AppUrls.BASE_URL,connectTimeout: const Duration(seconds: 5),sendTimeout: const Duration(seconds: 5),receiveTimeout: const Duration(seconds: 5),);_dio?.options = options;}//fzm-platform-idFuture<HttpResponse<dynamic>> get(String path, {Map<String, dynamic>? queryParameters,Options? options,CancelToken? cancelToken,ProgressCallback? onReceiveProgress,}) async {var response = await _dio!.get(path,queryParameters: queryParameters,options: options,cancelToken: cancelToken,onReceiveProgress: onReceiveProgress);return parse(response);}Future<HttpResponse<dynamic>> post(String path, {Object? data,Map<String, dynamic>? queryParameters,Options? options,CancelToken? cancelToken,ProgressCallback? onReceiveProgress,}) async {var response = await _dio!.post(path,data: data,queryParameters: queryParameters,options: options,cancelToken: cancelToken,onReceiveProgress: onReceiveProgress);return parse(response);}
}HttpResponse parse(Response response) {//真正的解析var code = response.data["code"];var data = response.data["data"];var result = response.data["result"];var error = response.data["error"];if (code == 0 || code == null) {//赋值给构造函数return HttpResponse.success(data ?? result);} else {return HttpResponse.failure(error ?? "${code}");}
}// 注册返回:{data: null, code: -1}
class HttpResponse<T> {bool ok = false;T? data;String? error;//this.data是赋值简写HttpResponse.success(this.data) {ok = true;}//完整写法// HttpResponse.success(T? data) {//     this.data = data;//     ok = true;//   }HttpResponse.failure(this.error) {ok = false;}
}

使用dio 请求并解析渲染到UI

  final List<UserBean> _userList = [];Future<void> getExs() async {var response = await Http.of().post("https://");if (response.ok) {List list = response.data;//解析数据List<UserBean> userList = list.map((e) => UserBean.fromJson(e)).toList();setState(() {_userList.addAll(userList);});}}

渲染到ListView中

ListView.builder(itemCount: _userList.length,itemBuilder: (context, index) =>InkWell(onTap: (){Navigator.pushNamed(context, MyRouter.WEB_PAGE,arguments: {"name":_userList[index].name});toast(_userList[index].name??"");},child: Container(child: UserItem(_userList[index]))));
class UserItem extends StatelessWidget {final UserBean userBean;const UserItem(this.userBean, {super.key});@overrideWidget build(BuildContext context) {return Container(padding: EdgeInsets.only(left: 20, right: 20, top: 20),child: Row(children: [Text(userBean.name ?? "")],),);}
}

完。

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

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

相关文章

徐工集团与宁夏天元锰业集团召开战略合作会议

2024年3月3日&#xff0c;徐工集团党委书记、董事长杨东升一行考察宁夏天元锰业集团&#xff0c;并举行战略合作会议。宁夏天元锰业集团董事局主席贾天将及相关高管参加会议。双方围绕绿色低碳、智能化和信息化推进新一轮机械设备“以旧换新”&#xff0c;物流运输和矿山开采设…

VSCode通过SSH连接Docker环境进行开发

文章目录 VSCode 插件Docker 镜像构建镜像部署环境 VSCode 连接本地Docker容器VSCode SSH连接Docker容器VSCode 打开容器内目录文件 VSCode 插件 Remote - SSH Docker 镜像 https://hub.docker.com/_/golang # Golang 镜像 docker pull golang:1.22构建镜像 Dockerfile F…

ThreadPoolExecutor 学习

ThreadPoolExecutor 是开发中最常用的线程池&#xff0c;今天来简单学习一下它的用法以及内部构造。 1、线程池存在的意义&#xff1f; 一般在jvm上&#xff0c;用户线程和操作系统内核线程是1&#xff1a;1的关系&#xff0c;也就是说&#xff0c;每次创建、销毁线程的时候&am…

Python基础:标准库 -- Time 时间的访问和转换

1. 官方文档 time --- 时间的访问和转换 — Python 3.12.2 文档 2. 准备知识 协调世界时 UTC (Coordinated Universal Time) 协调世界时&#xff08;Coordinated Universal Time&#xff0c;UTC&#xff09;&#xff0c;是一种国际标准的时间表示方式。UTC 是以原子钟为基础…

【代码】Python3|无GUI环境中使用Seaborn作图的学习路线及代码(阴影折线图)

我有个需求是需要画图&#xff0c;让GPT帮我生成了一下学习计划。 学习路线依照GPT的来的&#xff0c;使用的Prompt工具是https://github.com/JushBJJ/Mr.-Ranedeer-AI-Tutor。 文章目录 PrerequisiteMain Curriculum1.1 Seaborn介绍Seaborn基础保存图形为文件练习 1.2 单变量数…

产品推荐 - GX-SOPC-5CEFA5-M484 FPGA核心开发板

● 核心板采用8层板精心设计 ● FPGA&#xff1a;采用Intel&#xff08;ALTERA&#xff09; Cyclone V 5CEFA5&#xff0c;Les为77K&#xff0c;内嵌存储器为4460Kb&#xff0c;硬件乘法器为300个&#xff0c;最大等效门数约2300万门&#xff1b;新增DSP Block&#xff08;150…

Unity3D

一、C# 输入输出 二、三维数学

线性dp P1004 【方格取数】题解

代码比较简单的一题&#xff0c;重在思路&#xff08;除非写假了&#xff09; 传送门https://www.luogu.com.cn/problem/P1004 我的最初思路是两次二维dp&#xff0c;即贪心的取&#xff0c;用pre记录前一个位置&#xff0c;只有80pts&#xff0c;要是是在蓝桥拿分就可以跑路…

使用reduce递归获取有多层嵌套的数组中的children

常见的多层嵌套的数组&#xff0c;如下 const items [{id: 1,name: "item1",children: [{id: 11,name: "item11",children: [{id: 111, name: "item111"},{id: 112, name: "item112"}]},{id: 12,name: "item12",children:…

MySQL--优化(SQL语句执行慢,如何分析)

MySQL–优化&#xff08;SQL语句执行慢&#xff0c;如何分析&#xff09; 定位慢查询SQL执行计划索引 存储引擎索引底层数据结构聚簇和非聚簇索引索引创建原则索引失效场景 SQL优化经验 一、如何分析 聚合查询&#xff1a; 对于涉及大量数据的聚合操作&#xff0c;如果可能的…

【c++】STL--List的实现

目录 一. List的数据结构 二. List实现的基本框架 1. list的结点结构类 2. List的迭代器类 正向迭代器 反向迭代器 3. List操作接口的实现 1. 默认成员函数 构造函数 和 析构函数 拷贝构造函数 和 赋值运算符重载 2. 修改相关函数接口 insert 和 erase …

R语言简介、环境与基础语法及注释

R语言简介、环境与基础语法及注释 一、R语言1.R语言简介2.R语言官网3.R语言中国的镜像网站4.R语言下载5.R语言的历史 二、R语言环境1.Windows安装1.1 去 R 语言下载的镜像站点的列表下载1.2 选择版本进行下载1.3 点击运行1.4 一路默认&#xff0c;安装完毕&#xff01; 2.Linux…

【AI视野·今日Robot 机器人论文速览 第八十期】Fri, 1 Mar 2024

AI视野今日CS.Robotics 机器人学论文速览 Fri, 1 Mar 2024 Totally 32 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers Humanoid Locomotion as Next Token Prediction Authors Ilija Radosavovic, Bike Zhang, Baifeng Shi, Jathushan Rajasegaran…

ShardingSphere-SQL 解析 Issue 处理流程

ShardingSphere-SQL 解析 Issue 处理流程 这是之前给社区写的 SQL 解析 Issue 的处理流程&#xff0c;可以帮助社区用户快速参与到 ShardingSphere-SQL 解析任务当中。 ShardingSphere SQL 解析 issue 列表 Issue 背景说明 当前 Issue 使用自定义的爬虫脚本从对应的数据库官…

MySQL-----视图

一 视图 ▶ 介绍 视图view是一个虚拟表&#xff0c;非真实存在&#xff0c;其本质是根据SQL语句获取动态的数据集&#xff0c;并为其命名&#xff0c;用户使用时只需使用视图名称即可获取结果集&#xff0c;并可以将其当作表来使用。 数据库中存放了视图的定义&…

Java程序员修炼之道 之 Logging

1. 一个最基本的例子 使用Logging框架写Log基本上就三个步骤 引入loggerg类和logger工厂类 声明logger 记录日志 下面看一个例子 //1. 引入slf4j接口的Logger和LoggerFactory import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class UserService { //…

C#封装常用的Redis工具类

1.请先安装CSRedisCore 接口&#xff1a; namespace Tools.Redis {public interface IRedisTool{bool SetLongValue(string key, string value);bool SetValue(string key, string value, int outSecond);bool SetValue(string key, string value);bool Exists(string key);b…

企业数字人虚拟形象定制解决方案

随着数字化浪潮的推进&#xff0c;虚拟形象在各个领域都展现出了强大的潜力&#xff0c;美摄科技作为业界领先的数字人虚拟形象定制解决方案提供商&#xff0c;致力于为企业打造独一无二的虚拟形象&#xff0c;助力企业在数字世界中塑造独特的品牌形象。 一、解决方案概览 美…

02-prometheus监控-服务器节点监控node-exporter

一、概述 prometheus&#xff0c;本身是一个【数据收集】和【数据处理】的工具&#xff0c;如果效果要监控一台服务器物理机&#xff0c;有两种方式&#xff0c;一种是在物理机上部署“node-export”来收集数据上报给prometheus&#xff0c;另一种是“自定义监控”&#xff1b;…

SqlServer 默认值约束示例

创建表&#xff0c;创建时指定 money 字段默认值为0.00&#xff1b; create table t_24 ( account varchar(19) not null, id_card char(18) not null, name varchar(20) not null, money decimal(16,2) default 0.00 not null ); 录入2条记录&#xff0c;money字…