一个完整的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.
  @override
  Widget 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) {
          // 在请求被发送之前做一些事情
          // 设置公共header
          options.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-id

  Future<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});

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.only(left: 20, right: 20, top: 20),
      child: Row(
        children: [Text(userBean.name ?? "")],
      ),
    );
  }
}

完。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

STM32基础--初识 STM32

什么是 STM32 对于STM32&#xff0c;从字面意思上来理解&#xff0c;ST是意法半导体&#xff0c;M是Microelectronics的缩写&#xff0c;其中32表示的是32位&#xff0c;那么整合起来理解就是&#xff1a;STM32就是指的ST公司开发的32位微控制器。在如今的32位控制器中&#x…

mq基础类设计

消息队列就是把阻塞队列这样的数据结构单独提取成一个程序独立进行部署。——>实现生产者消费者模型。 但是阻塞队列是在一个进程内部进行的&#xff1b; 消息队列是在进程与进程之间进行实现的&#xff0c; 解耦合&#xff1a;就是在分布式系统中&#xff0c;A服务器调用B…

Window系统搭建feishu-chatgpt企业AI机器人并实现无公网ip远程连接

文章目录 前言环境列表1.飞书设置2.克隆feishu-chatgpt项目3.配置config.yaml文件4.运行feishu-chatgpt项目5.安装cpolar内网穿透6.固定公网地址7.机器人权限配置8.创建版本9.创建测试企业10. 机器人测试 前言 在飞书中创建chatGPT机器人并且对话&#xff0c;在下面操作步骤中…

偶现bug如何分析和处理?

测试中比较郁闷的一件事就是遇到偶现bug。测个10次~20次才难得出来一次&#xff0c;甚至有时几天才会出现一次&#xff0c;真的去复现的时候又不记得自己执行了哪些步骤。所以遇到这样的问题都是比较头疼的。 举个例子&#xff1a; 打开一个论坛&#xff0c;有一个在线人数的信…

在Mac上安装nginx+rtmp 本地服务器

需要使用终端命令&#xff0c;如果没有Homebrew&#xff0c;要安装Homebrew,执行&#xff1a; ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 一、安装Nginx 1、先clone Nginx项目到本地&#xff1a; brew tap de…

云计算,用价格让利换创新空间?

文 | 智能相对论 作者 | 李源 ECS&#xff08;云服务器&#xff09;最高降36%、OSS&#xff08;对象存储&#xff09;最高降55%、RDS&#xff08;云数据库&#xff09;最高降40%…… 阿里云惊人的降幅&#xff0c;一次性把国内云计算厂商的价格战推到了白热化阶段。 这次能…

【C语言】linux内核napi_gro_receive

一、注释 // napi_gro_receive是网络设备接口的一个函数&#xff0c;它被NAPI&#xff08;New API&#xff09;网络轮询机制使用&#xff0c;用于接收和处理接收到的数据包。 // 这个函数通过通用接收分组&#xff08;GRO&#xff0c;Generic Receive Offload&#xff09;技术…

java数据结构与算法刷题-----LeetCode687. 最长同值路径

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 1. 深度优先&#xff0c;用下面的儿子判断2. 深度优先&#xff0…

UE4 Niagara 关卡3.4官方案例解析

Texture sampling is only supported on the GPU at the moment.(纹理采样目前仅在GPU上受支持) 效果&#xff1a;textures can be referenced within GPU particle systems。this demo maps a texture to a grid of particles&#xff08;纹理可以在GPU粒子系统中被引用这个演…

【3GPP】【核心网】【5G】5G核心网协议解析(二)(超详细)

5G UE 附着过程 UE AMF ----------------- 注册请求(Registration Request) ----------------------> <--------------- 鉴权请求(Authentication Request) ------…

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

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

BetterDisplay Pro for Mac v2.0.11激活版:屏幕显示优化专家

BetterDisplay Pro是一款由waydabber开发的Mac平台上的显示器校准软件&#xff0c;可以帮助用户调整显示器的颜色和亮度&#xff0c;以获得更加真实、清晰和舒适的视觉体验。 软件下载&#xff1a;BetterDisplay Pro for Mac v2.0.11激活版下载 &#x1f50d; 精准校准&#xf…

[HackMyVM]靶场 Quick3

kali:192.168.56.104 主机发现 arp-scan -l # arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:d2:e0:49, IPv4: 192.168.56.104 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.56.1 0a:00:27:00:00:05 (U…

【触想智能】工业一体机刷卡应用知识分享

工业一体机刷卡技术是一种高效、稳定、安全的身份认证方式&#xff0c;具有广泛的应用场景和优势。在工业自动化控制、生产过程监测等领域&#xff0c;它已成为必不可少的设备之一。 一、工业一体机刷卡的原理:工业一体机刷卡的原理和普通的刷卡设备类似&#xff0c;都是通过读…

3.1_2024ctf青少年比赛部分web题

php后门 根据x-powered-by知道php的版本 该版本存在漏洞&#xff1a; PHP 8.1.0-dev 开发版本后门 根据报错信息&#xff0c;进行提示&#xff0c;前 GET / HTTP/1.1 Host: challenge.qsnctf.com:31639 User-Agentt:12345678system(cat /flag);var_dump(2*3);zerodium12345678…

QChart柱状图

//柱状图// 创建柱状图数据QBarSet *set0 new QBarSet("");*set0 << 1601 << 974 << 655 << 362;QBarSeries *series new QBarSeries();series->append(set0);set0->setColor(QColor("#F5834B"));// 创建柱状图QChart *ch…

高校校园点餐系统|基于B/S结构+ Mysql+Java+JSP技术的高校校园点餐系统平台设计与实现(源码+数据库+文档+PPT)

目录 摘 要 数据库设计 用户信息实体图 食堂信息实体图 留言板信息实体图 数据库表设计 系统详细设计 前台首页功能模块 管理员功能模块 食堂功能模块 用户功能模块 论文参考 文末获取源码联系 摘 要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff…

STM 32 HAL库 UART 调试的问题

问题1&#xff1a;STM32G0 系列 DMA中断接收&#xff0c;应用层无法接收到数据 分析&#xff1a; Debug发现&#xff0c;最终没有进入串口中断函数 。 于是&#xff0c;检查Stm32CubeMX 的工程配置 两个串口的全局中断没有使能。 解决&#xff1a;勾选上图中红框部分&#x…

docker 常用命令大全(基础、镜像、容器、数据卷)

文章目录 1.docker基础命令2.docker镜像命令2.1 镜像名称2.2 镜像命令2.3 案例1--拉取、查看镜像2.4 案例2--保存、导入镜像 3.docker容器命令3.1 容器命令3.2 案例--创建并运行一个容器3.3 案例--进入容器&#xff0c;修改文件3.4 小结 4.数据卷4.1 什么是数据卷4.2 数据卷操作…

【Android】位置修改相关

获取位置服务总开关状态 //获取LOCATION_MODE值&#xff0c;但adb状态下无法获取 //0为关闭&#xff0c;1 gps、2 network、3 高精度等 int state Settings.Secure.getInt(mContext.getContentResolver(),Settings.Secure.LOCATION_MODE,Settings.Secure.LOCATION_MODE_HIGH_…