一个完整的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.hqwc.cn/news/511933.html

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

相关文章

常用“树”数据结构

哈夫曼树 在许多应用中&#xff0c;树中结点常常被赋予一个表示某种意义的数值&#xff0c;称为该结点的权。从树的根到任意结点的路径长度(经过的边数)与该结点上权值的乘积&#xff0c;称为该结点的带权路径长度。树中所有叶结点的带权路径长度之和称为该树的带权路径长度&am…

hot100 -- 普通数组

目录 &#x1f382;最大子数组和 O(n) 暴力 O(n) 动态规划 &#x1f6a9;合并区间 O(nlogn) 排序 &#x1f33c;轮转数组 O(n) 辅助数组 O(n) 环状替换 O(n) 数组翻转 &#x1f33c;除自身以外数组的乘积 O(n) 前缀和 时间O(n) 空间O(1) &#x1f319;缺失的…

波奇学Linux:信号的产生:异常和软件条件

异常与信号 进程异常的本质是程序收到操作系统信号 eg&#xff1a;除0让进程收到异常信号&#xff0c;kill掉进程&#xff0c;使得进程崩溃 进程收到异常信号不一定会退出&#xff0c;对出程序异常&#xff0c;捕捉信号&#xff0c;进程可能不退出。 操作系统如何知道除0操作…

javaWebssh题库管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh题库管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Mye…

折线图实现柱状阴影背景的demo

这个是一个由官网的基础折线图实现的流程&#xff0c;将涉及到的知识点附上个人浅薄的见解&#xff0c;源码在最后&#xff0c;需要的可自取。 折线图 成果展示代码注解参数backgroundColordataZoomlegendtitlexAxisyAxisgridseries 源码 成果展示 官网的基础折线图&#xff…

Jupyter Notebook的安装和使用(windows环境)

一、jupyter notebook 安装 前提条件&#xff1a;安装python环境 安装python环境步骤&#xff1a; 1.下载官方python解释器 2.安装python 3.命令行窗口敲击命令pip install jupyter 4.安装jupyter之后&#xff0c;直接启动命令jupyter notebook,在默认浏览器中打开jupyte…

【译】WordPress Bricks主题安全漏洞曝光,25,000个安装受影响

WordPress的Bricks主题存在一个严重的安全漏洞,恶意威胁行为者正在积极利用该漏洞在易受攻击的安装上运行任意PHP代码。 该漏洞被跟踪为CVE-2024-25600(CVSS评分:9.8),使未经身份验证的攻击者能够实现远程代码执行。它影响Bricks的所有版本,包括1.9.6版本及更早版本。 该…

今日Arxiv最热NLP大模型论文:北京大学发布“讨论链”,利用LLM协作回答复杂问题

开放式问答&#xff08;Open-ended Question Answering, QA&#xff09;是人工智能领域的一个重要分支&#xff0c;它要求模型能够找到合适的证据&#xff0c;并形成有理有据、全面且有帮助的答案。在实际应用中&#xff0c;模型还需要能够就与问题紧密相关的潜在场景进行扩展讨…

python打包两种方式:setup.py、pyproject.toml;entry_points、project.scripts 可执行的命令行

参考&#xff1a; https://blog.csdn.net/qq_38844437/article/details/126628564 setup.py https://click.palletsprojects.com/en/7.x/setuptools/#setuptools-integration 学习写法&#xff1a;https://github.com/myshell-ai/MeloTTS/blob/main/setup.py yourscript.p…

【LeetCode每日一题】【BFS模版与例题】【二维数组】130被围绕的区域 994 腐烂的橘子

前几天写过一篇BFS比较基础版的遍历 【LeetCode每日一题】【BFS模版与例题】863.二叉树中所有距离为 K 的结点 &#xff0c;可以先看一下再看本文 用 BFS 算法遍历二维数组 遍历二维矩阵&#xff1a;二维矩阵中的一个位置看做一个节点&#xff0c;这个节点的上下左右四个位置…

ROS2中std_msgs/msg/Header 数据含义及使用

ROS2中std_msgs/msg/Headerr 数据含义及使用 ROS官方消息说明数据说明使用ros2标准的Header案例代码解释测试结果 ROS官方消息说明 ROS2中std_msgs消息包含类型 https://docs.ros2.org/latest/api/std_msgs/msg/std_msgs/msg/Header Message std_msgs/msg/Header数据格式&…

mybatis不重复列插入例子详细说明

之前有做过不重复列插入的需求&#xff0c;当时是 在插入时判断 对应的列在数据库中有没有对应的数据 有则返回false 无则插入&#xff0c;但是这加大了数据库的查询负担 也增加了插入的时间&#xff0c;故今天研究一下 使用sql来简化了这一点 使用的知识点是 daul表 insert i…