当前位置: 首页 > article >正文

关于Flutter空安全升级方案整理

前言

Flutter 从 2.0 版本开始支持空安全(Null Safety)。dart 版本为:

 environment:
  sdk: ">=2.12.0 < 3.0.0"

升级到空安全后,由于语法的变动,基本上整个工程,代码都爆红,这对项目来说简直是灾难性的打击,不升级的话只是缓兵之计,因为随着时间的推移,flutter将不再维护非空安全的版本,同时一些三方库也将无法使用,因此空安全升级变成了一个不得不做的事情,项目越复杂需要的时间也就越持久,考虑到对项目的稳定性,和开发周期。选择一个合适自己项目的迁移方案非常重要。下面自己会讲下自己对空安全迁移的理解和实施方案,目前成功迁移几个项目,还是比较有经验的。

语法变动

空安全升级后dart语法是存在很大的变化的,但是理念很简单即:万物皆可为空,和以往不同,现在任意创建一个对象都需要判断对象是否为空,这样在使用的时候,便明确知道这个对象是否可能为空,可以避免很多空指针的情况。
Dart 空安全的关键语法
1.不可空类型
在启用空安全的 Dart 中,默认情况下所有类型都是不可空的。这意味着一个变量声明后,不能为 null。例如:

int x = 42; // x 不能为 null

如果尝试将 null 赋值给不可空类型,编译器将会报错。

2.可空类型
如果一个变量可以是 null,则必须在类型后加上 ?。例如:

int? y = null; // y 可以是整数或 null

这种语法清晰地表明 y 是可空的,开发者在使用时必须考虑它可能为 null 的情况。

3.非空断言操作符 !
当你确定一个可空变量不为 null 时,可以使用 ! 操作符进行非空断言。例如:

int? a = 5;
int b = a!; // 断言 a 不为 null,安全地将其赋值给 b

使用 ! 操作符时要小心,因为如果断言错误(即变量实际上为 null),程序会抛出异常。因此对于不确定的变量尽量不要强制!

4.空合并操作符 ??
空合并操作符提供了一种为可空变量指定默认值的便捷方式。例如:

String? name;
String displayName = name ?? 'Guest'; // 如果 name 为 null,则使用 'Guest'

这种操作符在开发中是非常常用的,我们经常会通过??来给一些可为空的对象创建兜底值

5.late 变量
有时候我们明确知道这个对象一定是不会为null的但是再创建的时候拿不到值,便可以通过late 来延迟初始化这个对象

late String description;

void initialize() {
  description = 'Dart is fun!';
}

使用 late 声明的变量在首次使用前必须被初始化,否则将导致运行时错误。

空安全迁移

Flutter 官方提供了空安全迁移方案:使用dart migrate工具可以借助该工具
在开始迁移之前,请确保做好以下准备工作:
升级 Dart SDK:确保你使用的 Dart SDK 版本是 2.12 或更高版本。可以通过 dart --version 检查当前的 Dart 版本。
更新依赖:确保项目中的所有依赖包都支持空安全。可以使用以下命令查看哪些包需要更新:

dart pub outdated --mode=null-safety

在这里插入图片描述

可以根据输出的日志将不支持空安全的版本升级或者替换
以上都完成后,便可以使用 dart migrate 来进行代码的替换了

dart migrate工具会为你构建迁移后的代码建议,并启动一个交互式的迁移网页界面。

View the migration suggestions by visiting:

  http://127.0.0.1:60278/Users/you/project/mypkg.console-simple?authToken=Xfz0jvpyeMI%3D

在这里插入图片描述
以上便可以通过dart migrate进行简单的迁移
手动迁移
真实的开发场景哪有这么理想,因此使用dart migrate对很多大型项目并不是很使用,并且使用dart migrate会大量的添加** !** 导致项目一堆异常,无法真正的运行起来。
另外也没有那么多时间,让项目进度停下来做空安全迁移。
因为我们做的方案是:创建一个支持空安全语法的module

//需要安卓和iOS模块
flutter create --template=plugin --org com.xxxx.xxx --platforms android --platforms ios --project-name aaa bbb
flutter create --template=plugin --org com.xxxx.xxxxx  --project-name aaaa bbbb

将创建好的工程以module的形式,依赖到主项目中,此方法不会打破项目的连续性,可以边迁移,边做需求开发。需要注意的是:
需要将主项目(非空安全)和子module(空安全)以相对路径的方式进行依赖因此需要修改pubspec.yaml 中的依赖方式

UT和覆盖率需要以下面的方式进行run

flutter test --no-sound-null-safety

在整体空安全都迁移完成后,再将项目移会去,这样边可以,一部分同时进行正常的需求开发,一部分同时进行空安全整改,最大化的提高工作效率。

当然在迁移过程中会涉及到import的问题,这里自己写了脚本,用于批量修改导包

#!/bin/sh

echo "修改工程导包"

# 修改对应的一级文件夹
CHANGEFILE="xxxx"


# 修改以package开头的导包
package_name="package:xxxxx\/$CHANGEFILE\/"
new_string=""
old_string="\.\.\/"
search_string="\.\.\/$CHANGEFILE"
old_import="$CHANGEFILE\/"
# 从主项目迁移到空安全路径修改导包路径名称
new_import="package:mobile_cn_null_safety\/$CHANGEFILE\/"

find . -name "*.dart"|while read fname; do

 echo "The string is found on line(s): $fname"
#package 开头导包
 if grep -q "$package_name" "$fname"; then
    # 使用grep查找字符串所在行
    package_line_number=$(grep -n "${package_name}" "$fname" | cut -d: -f1)
    # 遍历行号
    for each1 in $package_line_number
     do
       if [ -n "$each1" ];then
         sed -i  '' "${each1}s/${package_name}/${new_import}/g" "$fname"
       fi
     done

 fi


# 相对路径导包
  if grep -q "$search_string" "$fname"; then
      # 使用grep查找字符串所在行
      line_number=$(grep -n "${search_string}" "$fname" | cut -d: -f1)
      for each in $line_number
       do
         if [ -n "$each" ];then
           sed -i  '' "${each}s/${old_string}//g" "$fname"
           sed -i  '' "${each}s/${old_import}/${new_import}/g" "$fname"
         fi
       done

  fi
done

以上差不多便是全部内容。


http://www.kler.cn/a/391804.html

相关文章:

  • 【云计算解决方案面试整理】1-2云计算基础概念及云计算技术原理
  • 【Webpack实用指南】如何拆分CSS资源(2)
  • win32 / WTL 开发多线程应用,子线程传递大对象给UI线程(主窗口)的方法
  • 事件循环 -- 资源总结(浏览器进程模型、事件循环机制、练习题)
  • 重构代码之内联临时变量
  • Mit6.S081-实验环境搭建
  • 基于Spring Boot的瑜伽馆管理系统设计与实现,LW+源码+讲解
  • Javascript 笔记(二):闭包(2)与map知识点
  • 如何对PHP的API接口权限认证
  • ubuntu串口权限修改
  • PO 证书链
  • Vue.js动态组件使用
  • 179页PPT企业架构规划设计方案
  • 假期增加2天!matplotlib绘制2025年一整年日历
  • Ai创作新风标!仅需三步,利用ai工具免费制作抖音爆款的动物融合视频(含完整的步骤)
  • 深入理解接口测试:实用指南与最佳实践5.0(二)
  • Java基础-Java多线程机制
  • 【activiti工作流源码集成】springboot+activiti+mysql+vue+redis工作流审批流集成整合业务绑定表单流程图会签驳回
  • Vim9 语法高亮syntax 在指定的缓冲区和窗口执行命令
  • Java 中的 Predicate:让判断逻辑更清晰灵活
  • 把越南语翻译成中文一般用什么翻译工具?《越南语翻译通》App或许能满足你的技术痛点需求!
  • OpenHarmony4.1蓝牙芯片如何适配?触觉智能RK3568主板SBC3568演示
  • 【大语言模型】ACL2024论文-09 无监督信息精细化训练用于增强大型语言模型的检索增强生成
  • 从美国大选,看软件安全风险与挑战
  • 利用阿里云下载 WebRTC 源码
  • Golang 编码(url,base64,hex,md5,sha-1)