大佬谈关于Flutter空安全的一些使用经验和理解

本文介绍了Flutter 2.0的空安全特性,包括空安全的概念、Dart中的关键字?、required、late和!的用法。作者强调空安全在开发阶段就预防了NullPointer Exception错误,通过关键字实现更明确的类型声明,提升了代码的可读性和安全性。文章还讨论了空安全的局限性,如多线程环境下的潜在风险。最后,作者认为空安全强制了更好的设计规范并提高了代码质量。
摘要由CSDN通过智能技术生成

前言

Flutter 2.0的使用已经有一段时间了,在某平台看到一位大佬分享的关于Flutter空安全的一些使用经验和理解,我看完也觉得很有共鸣。
原文链接:https://juejin.cn/post/6986455348026540068

Dart空安全

空安全是什么?

在空安全下,运行时的NullPointer Exception错误被提前到了开发阶段。
即:
void main() { // 在空安全下, 开发阶段就会报错,而非运行时 String name; debugPrint(name); } 复制代码
类型上也有了变化,这里贴两张官方的类型关系图深入理解空安全 :
非空安全时代:
在这里插入图片描述

空安全时代

在这里插入图片描述

可以看到,Null这个类型变成了一个单独的类,而非所有类的子类,换言之:

void main() {
   
    String a = null;
}


非空安全下:
    因为Null是所有类型的子类,基于多态性的原理,这种书写方式是正确的。
    

在空安全下:
    Null独立了出去,那么当你再像上面那样书写时,就会报错了,因为这本质上发生了类型转换的错误.


复制代码

空安全有什么?

新增了关键字,并对原有关键字的含义做了拓展 :

?            -> 可空,              如: int a?;
!            -> 非空               如: int b = a!;
late         -> 延迟初始化          如:  late int a;
required     -> 可选参数的不可空    如: {
   required int a}
复制代码

而含义的对象就是开发工具了,下面逐一对它们进行介绍。

关键字: ?

我们在开发过程中,相当多的参数变量并不一定为必传,因此我们可以用 ? 来标注其为可空。

///通过问号,我们可以告知编辑器(及使用者),style是可空的(有点像可选参数)
Widget buildTextWidget(String text, TextStyle? style) {
   
    return Text(text, style: style);
}

调用时:

void main() {
   
    buildTextWidget('hello world !',null
好的,以下是一个使用 Sqflite 的 Flutter 代码样例,使用安全: ```dart import 'package:sqflite/sqflite.dart'; import 'package:path/path.dart'; class DatabaseHelper { static const _databaseName = 'my_database.db'; static const _databaseVersion = 1; static Database? _database; // 私有构造函数 DatabaseHelper._(); static final DatabaseHelper instance = DatabaseHelper._(); Future<Database> get database async { if (_database != null) return _database!; _database = await _initDatabase(); return _database!; } Future<Database> _initDatabase() async { final dbPath = await getDatabasesPath(); final path = join(dbPath, _databaseName); return await openDatabase( path, version: _databaseVersion, onCreate: _onCreate, ); } Future<void> _onCreate(Database db, int version) async { await db.execute(''' CREATE TABLE my_table ( id INTEGER PRIMARY KEY, name TEXT NOT NULL, age INTEGER NOT NULL ) '''); } Future<int> insert(Map<String, Object?> row) async { final db = await instance.database; return await db.insert('my_table', row, conflictAlgorithm: ConflictAlgorithm.replace); } Future<List<Map<String, Object?>>> queryAllRows() async { final db = await instance.database; return await db.query('my_table'); } Future<int> update(Map<String, Object?> row) async { final db = await instance.database; final id = row['id']; return await db.update('my_table', row, where: 'id = ?', whereArgs: [id]); } Future<int> delete(int id) async { final db = await instance.database; return await db.delete('my_table', where: 'id = ?', whereArgs: [id]); } } ``` 这个样例代码定义了一个 `DatabaseHelper` 类,提供了对 SQLite 数据库的基本操作,并且使用安全特性。 在这个代码中,我们使用了 `late` 修饰符来延迟初始化 `_database` 变量,同时使用了 `?` 来标记这个变量是可的。在 `get database` 方法中,我们使用了 `!` 来断言 `_database` 不为。 在这个代码中,我们还使用了非断言操作符 `!`,来确保变量不为。同时,我们也使用值合并操作符 `??`,来提供默认值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值