Flutter技术与实战(3)

基于flutter3+getx仿抖音企业级开发+app直播 基于flutter3+getx仿抖音企业级开发+app直播,近年来各大公司对Flutter技能的要求越来越高,有些专门提供培训并设立岗位,但掌握Flutter高阶技能的人才寥寥无几,市面上干货Flutter高阶课程少之又少 阅读详情

Dart语言基础

基础语法与类型变量
Dart初体验
printInteger(int a) {
  print('Hello world, this is $a.'); 
}

main() {
  var number = 2019; 
  printInteger(number); 
}
——————————————————————————————————————————————————————————————————————————————
Hello world, this is 2019. 
Dart的变量与类型
  • 在 Dart 中,我们可以用 var 或者具体的类型来声明一个变量。当使用 var 定义变量时,表示类型是交由编译器推断决定的,当然你也可以用静态类型去定义变量,更清楚地跟编译器表达你的意图,这样编辑器和编译器就能使用这些静态类型,向你提供代码补全或编译警告的提示了。
  • 在默认情况下,未初始化的变量的值都是 null,因此我们不用担心无法判定一个传递过来的、未定义变量到底是 undefined,还是烫烫烫而写一堆冗长的判断语句了。
  • Dart 是类型安全的语言,并且所有类型都是对象类型,都继承自顶层类型 Object,因此一切变量的值都是类的实例(即对象),甚至数字、布尔值、函数和 null 也都是继承自 Object 的对象。
  • Dart 内置了一些基本类型,如 num、bool、String、List 和 Map,在不引入其他库的情况下可以使用它们去声明变量。
num、bool与String
  • Dart 的数值类型 num,只有两种子类:即 64 位 int 和符合 IEEE 754 标准的 64 位 double。前者代表整数类型,而后者则是浮点数的抽象。
  • 有其他高级运算方法的需求 num 无法满足,你可以试用一下 dart:math 库。这个库提供了诸如三角函数、指数、对数、平方根等高级函数。
int x = 1;
int hex = 0xEEADBEEF;
double y = 1.1;
double exponents = 1.13e5;
int roundY = y.round();
  • 为了表示布尔值,Dart 使用了一种名为 bool 的类型。在 Dart 里,只有两个对象具有 bool 类型:true 和 false,它们都是编译时常量。
  • Dart 是类型安全的,因此我们不能使用 if(nonbooleanValue) 或 assert(nonbooleanValue) 之类的在 JavaScript 可以正常工作的代码,而应该显式地检查值。
// 检查是否为0,在 Dart 中需要显示地与 0 做比较
var number = 0;
assert(number == 0);
// assert(number); 错误
  • Dart 的 String 由 UTF-16 的字符串组成。和 JavaScript 一样,构造字符串字面量时既能使用单引号也能使用双引号,还能在字符串中嵌入变量或表达式:你可以使用 ${express} 把一个表达式的值放进字符串。而如果是一个标识符,你可以省略{}。
var s = 'cat';
var s1 = 'this is a uppercased string: ${s.toUpperCase()}';
  • 常见字符串的拼接,Dart 则通过内置运算符“+”实现。
var s2 = 'Hello' + ' ' + 'World!' ;
  • 对于多行字符串的构建,你可以通过三个单引号或三个双引号的方式声明,这与 Python 是一致的。
var s3 = """This is a
multi-line string.""";
List与Map
  • 其他编程语言中常见的数组和字典类型,在 Dart 中的对应实现是 List 和 Map,统称为集合类型。它们的声明和使用很简单,和 JavaScript 中的用法类似。
var arr1 = ["Tom", "Andy", "Jack"];
var arr2 = List.of([1,2,3]);
arr2.add(499);
arr2.forEach((v) => print('${v}'));
  
var map1 = {"name": "Tom", 'sex': 'male'}; 
var map2 = new Map();
map2['name'] = 'Tom';
map2['sex'] = 'male';
map2.forEach((k,v) => print('${k}: ${v}')); 
  • 容器里的元素也需要有类型,比如上述代码中 arr2 的类型是 List,map2 的类型则为 Map。Dart 会自动根据上下文进行类型推断,所以你后续往容器内添加的元素也必须遵照这一类型。
  • 如果编译器自动推断的类型不符合预期,我们当然可以在声明时显式地把类型标记出来,不仅可以让代码提示更友好一些,更重要的是可以让静态分析器帮忙检查字面量中的错误,解除类型不匹配带来的安全隐患或是 Bug。
  • 如果往 arr2 集合中添加一个浮点数 arr2.add(1.1),尽管语义上合法,但编译器会提示类型不匹配,从而导致编译失败。
  • 和 Java 语言类似,在初始化集合实例对象时,你可以为它的类型添加约束,也可以用于后续判断集合类型。
var arr1 = <String>['Tom', 'Andy', 'Jack'];
var arr2 = new List<int>.of([1,2,3]);
arr2.add(499);
arr2.forEach((v) => print('${v}'));
print(arr2 is List<int>); // true

var map1 = <String, String>{'name': 'Tom','sex': 'male',};
var map2 = new Map<String, String>();
map2['name'] = 'Tom';
map2['sex'] = 'male';
map2.forEach((k,v) => print('${k}: ${v}')); 
print(map2 is Map<String, String>); // true
常量定义
  • 如果你想定义不可变的变量,则需要在定义变量前加上 final 或 const 关键字。
    • const,表示变量在编译期间即能确定的值;
    • final 则不太一样,用它定义的变量可以在运行时确定值,而一旦确定后就不可再变。
final name = 'Andy';
const count = 3;

var x = 70;  
var y = 30;
final z = x / y;
  • const 适用于定义编译常量(字面量固定值)的场景,而 final 适用于定义运行时常量的场景。
流程控制语法
  • 对于流程控制语法:如 if-else、for、while、do-while、break/continue、switch-case、assert,由于与其他编程语言类似。
  • 官方文档:https://api.dart.dev/stable/2.2.0/index.html
函数、类与运算符
函数
  • 函数是一段用来独立地完成某个功能的代码。在 Dart 中,所有类型都是对象类型,函数也是对象,它的类型叫作 Function。这意味着函数也可以被定义为变量,甚至可以被定义为参数传递给另一个函数。
bool isZero(int number) { //判断整数是否为0
  return number == 0; 
}

void printInfo(int number,Function check) { //用check函数来判断整数是否为0
  print("$number is Zero: ${check(number)}");
}

Function f = isZero;
int x = 10;
int y = 0;
printInfo(x,f);  // 输出 10 is Zero: false
printInfo(y,f);  // 输出 0 is Zero: true
  • 如果函数体只有一行表达式,就比如上面示例中的 isZero 和 printInfo 函数,我们还可以像 JavaScript 语言那样用箭头函数来简化这个函数。
bool isZero(int number) => number == 0;

void printInfo(int number,Function check) => print("$number is Zero: ${check(number)}");
  • 有时,一个函数中可能需要传递多个参数。那么,如何让这类函数的参数声明变得更加优雅、可维护,同时降低调用者的使用成本呢?
  • C++ 与 Java 的做法是,提供函数的重载,即提供同名但参数不同的函数。但 Dart 认为重载会导致混乱,因此从设计之初就不支持重载,而是提供了可选命名参数和可选参数。具体方式是,在声明函数时:
    • 给参数增加{},以 paramName: value 的方式指定调用参数,也就是可选命名参数;
    • 给参数增加[],则意味着这些参数是可以忽略的,也就是可选参数。
  • 在使用这两种方式定义函数时,我们还可以在参数未传递时设置默认值。
//要达到可选命名参数的用法,那就在定义函数的时候给参数加上 {}
void enable1Flags({bool bold, bool hidden}) => print("$bold , $hidden");

//定义可选命名参数时增加默认值
void enable2Flags({bool bold = true, bool hidden = false}) => print("$bold ,$hidden");

//可忽略的参数在函数定义时用[]符号指定
void enable3Flags(bool bold, [bool hidden]) => print("$bold ,$hidden");

//定义可忽略参数时增加默认值
void enable4Flags(bool bold, [bool hidden = false]) => print("$bold ,$hidden");

//可选命名参数函数调用
enable1Flags(bold: true, hidden: false); //true, false
enable1Flags(bold: true); //true, null
enable2Flags(bold: false); //false, false

//可忽略参数函数调用
enable3Flags(true, false); //true, false
enable3Flags(true,); //true, null
enable4Flags(true); //true, false
enable4Flags(true,true); // true, true
类
  • 类是特定类型的数据和方法的集合,也是创建对象的模板。与其他语言一样,Dart 为类概念提供了内置支持。
类的定义和初始化
  • Dart 是面向对象的语言,每个对象都是一个类的实例,都继承自顶层类型 Object。在 Dart 中,实例变量与实例方法、类变量与类方法的声明与 Java 类似。
  • 值得一提的是,Dart 中并没有 public、protected、private 这些关键字,我们只要在声明变量与方法时,在前面加上“”即可作为 private 方法使用。如果不加“”,则默认为 public。不过,“_”的限制范围并不是类访问级别的,而是库访问级别。
class Point {
  num x, y;
  static num factor = 0;
  //语法糖,等同于在函数体内:this.x = x;this.y = y;
  Point(this.x,this.y);
  void printInfo() => print('($x, $y)');
  static void printZValue() => print('$factor');
}

var p = new Point(100,200); // new 关键字可以省略
p.printInfo();  // 输出(100, 200);
Point.factor = 10;
Point.printZValue(); // 输出10
  • 类的实例化需要根据参数提供多种初始化方式。除了可选命名参数和可选参数之外,Dart 还提供了命名构造函数的方式,

  • 与 C++ 类似,Dart 支持初始化列表。在构造函数的函数体真正执行之前,你还有机会给实例变量赋值,甚至重定向至另一个构造函数。

  • Point 类中有两个构造函数 Point.bottom 与 Point,其中:Point.bottom 将其成员变量的初始化重定向到了 Point 中,而 Point 则在初始化列表中为 z 赋上了默认值 0。

class Point {
  num x, y, z;
  Point(this.x, this.y) : z = 0; // 初始化变量z
  Point.bottom(num x) : this(x, 0); // 重定向构造函数
  void printInfo() => print('($x,$y,$z)');
}

var p = Point.bottom(100);
p.printInfo(); // 输出(100,0,0)
复用
  • 在面向对象的编程语言中,将其他类的变量与方法纳入本类中进行复用的方式一般有两种:继承父类和接口实现。
    • 继承父类意味着,子类由父类派生,会自动获取父类的成员变量和方法实现,子类可以根据需要覆写构造函数及父类方法;
    • 接口实现则意味着,子类获取到的仅仅是接口的成员变量符号和方法符号,需要重新实现成员变量,以及方法的声明和初始化,否则编译器会报错。
class Point {
  num x = 0, y = 0;
  void printInfo() => print('($x,$y)');
}

//Vector继承自Point
class Vector extends Point{
  num z = 0;
  @override
  void printInfo() => print('($x,$y,$z)'); //覆写了printInfo实现
}

//Coordinate是对Point的接口实现
class Coordinate implements Point {
  num x = 0, y = 0; //成员变量需要重新声明
  void printInfo() => print('($x,$y)'); //成员函数需要重新声明实现
}

var xxx = Vector(); 
xxx
  ..x = 1
  ..y = 2
  ..z = 3; //级联运算符,等同于xxx.x=1; xxx.y=2;xxx.z=3;
xxx.printInfo(); //输出(1,2,3)

var yyy = Coordinate();
yyy
  ..x = 1
  ..y = 2; //级联运算符,等同于yyy.x=1; yyy.y=2;
yyy.printInfo(); //输出(1,2)
print (yyy is Point); //true
print(yyy is Coordinate); //true
  • 除了继承和接口实现之外,Dart 还提供了另一种机制来实现类的复用,即“混入”(Mixin)。

  • 混入鼓励代码重用,可以被视为具有实现方法的接口。这样一来,不仅可以解决 Dart 缺少对多重继承的支持问题,还能够避免由于多重继承可能导致的歧义(菱形问题)。

    备注:继承歧义,也叫菱形问题,是支持多继承的编程语言中一个相当棘手的问题。当 B 类和 C 类继承自 A 类,而 D 类继承自 B 类和 C 类时会产生歧义。如果 A 中有一个方法在 B 和 C 中已经覆写,而 D 没有覆写它,那么 D 继承的方法的版本是 B 类,还是 C 类的呢?

  • 要使用混入,只需要 with 关键字即可。

class Coordinate with Point {
}

var yyy = Coordinate();
print (yyy is Point); //true
print(yyy is Coordinate); //true
  • 通过混入,一个类里可以以非继承的方式使用其他类中的变量与方法。
运算符
  • Dart 和绝大部分编程语言的运算符一样,所以你可以用熟悉的方式去执行程序代码运算。不过,Dart 多了几个额外的运算符,用于简化处理变量实例缺失(即 null)的情况。
    • ?. 运算符:假设 Point 类有 printInfo() 方法,p 是 Point 的一个可能为 null 的实例。那么,p 调用成员方法的安全代码,可以简化为 p?.printInfo() ,表示 p 为 null 的时候跳过,避免抛出异常。
    • ??= 运算符:如果 a 为 null,则给 a 赋值 value,否则跳过。这种用默认值兜底的赋值语句在 Dart 中我们可以用 a ??= value 表示。
    • ?? 运算符:如果 a 不为 null,返回 a 的值,否则返回 b。在 Java 或者 C++ 中,我们需要通过三元表达式 (a != null)? a : b 来实现这种情况。而在 Dart 中,这类代码可以简化为 a ?? b。
  • 在 Dart 中,一切都是对象,就连运算符也是对象成员函数的一部分。
    • 对于系统的运算符,一般情况下只支持基本数据类型和标准库中提供的类型。而对于用户自定义的类,如果想支持基本操作,比如比较大小、相加相减等,则需要用户自己来定义关于这个运算符的具体实现。
  • Dart 提供了类似 C++ 的运算符覆写机制,使得我们不仅可以覆写方法,还可以覆写或者自定义运算符。
class Vector {
  num x, y;
  Vector(this.x, this.y);
  // 自定义相加运算符,实现向量相加
  Vector operator +(Vector v) =>  Vector(x + v.x, y + v.y);
  // 覆写相等运算符,判断向量相等
  bool operator == (dynamic v) => x == v.x && y == v.y;
}

final x = Vector(3, 3);
final y = Vector(2, 2);
final z = Vector(1, 1);
print(x == (y + z)); //  输出true

  • operator 是 Dart 的关键字,与运算符一起使用,表示一个类成员运算符函数。在理解时,我们应该把 operator 和运算符作为整体,看作是一个成员函数名。
综合案例
  • 源码地址:https://github.com/cyndibaby905/flutter_core_demo
案例介绍
  • 用 Dart 写一段购物车程序,但先不使用 Dart 独有的特性。然后,我们再以这段程序为起点,逐步加入 Dart 语言特性,将其改造为一个符合 Dart 设计思想的程序。
//定义商品Item类
class Item {
  double price;
  String name;
  Item(name, price) {
    this.name = name;
    this.price = price;
  }
}

//定义购物车类
class ShoppingCart {
  String name;
  DateTime date;
  String code;
  List<Item> bookings;

  price() {
    double sum = 0.0;
    for(var i in bookings) {
      sum += i.price;
    }
    return sum;
  }

  ShoppingCart(name, code) {
    this.name = name;
    this.code = code;
    this.date = DateTime.now();
  }

  getInfo() {
    return '购物车信息:' +
          '\n-----------------------------' +
          '\n用户名: ' + name+ 
          '\n优惠码: ' + code + 
          '\n总价: ' + price().toString() +
          '\n日期: ' + date.toString() +
          '\n-----------------------------';
  }
}

void main() {
  ShoppingCart sc = ShoppingCart('张三', '123456');
  sc.bookings = [Item('苹果',10.0), Item('鸭梨',20.0)];
  print(sc.getInfo());
}
————————————————————————————————————————————————————————————
购物车信息:
-----------------------------
用户名: 张三
优惠码: 123456
总价: 30.0
日期: 2019-06-01 17:17:57.004645
-----------------------------
类抽象改造
  • 在其他编程语言中,在构造函数的函数体内,将初始化参数赋值给实例变量的方式非常常见。而在 Dart 里,我们可以利用语法糖以及初始化列表,来简化这样的赋值过程,从而直接省去构造函数的函数体。
class Item {
  double price;
  String name;
  Item(this.name, this.price);
}

class ShoppingCart {
  String name;
  DateTime date;
  String code;
  List<Item> bookings;
  price() {...}
  //删掉了构造函数函数体
  ShoppingCart(this.name, this.code) : date = DateTime.now();
...
}
  • 考虑到 两个类name 属性与 price 属性(方法)的名称与类型完全一致,在信息表达上的作用也几乎一致,因此我可以在这两个类的基础上,再抽象出一个新的基类 Meta,用于存放 price 属性与 name 属性。
class Meta {
  double price;
  String name;
  Meta(this.name, this.price);
}
class Item extends Meta{
  Item(name, price) : super(name, price);
}

class ShoppingCart extends Meta{
  DateTime date;
  String code;
  List<Item> bookings;
  
  double get price {...}
  ShoppingCart(name, this.code) : date = DateTime.now(),super(name,0);
  getInfo() {...}
}
方法改造
  • price属性的get方法
double get price {
  double sum = 0.0;
  for(var i in bookings) {
    sum += i.price;
  }
  return sum;
} 
  • 在 Dart 中,这样的求和运算我们只需重载 Item 类的“+”运算符,并通过对列表对象进行归纳合并操作即可实现。
class Item extends Meta{
  ...
  //重载了+运算符,合并商品为套餐商品
  Item operator+(Item item) => Item(name + item.name, price + item.price); 
}

class ShoppingCart extends Meta{
  ...
  //把迭代求和改写为归纳合并
  double get price => bookings.reduce((value, element) => value + element).price;
  ...
  getInfo() {...}
}
  • 在 getInfo 方法中,我们将 ShoppingCart 类的基本信息通过字符串拼接的方式,进行格式化组合,这在其他编程语言中非常常见。而在 Dart 中,我们可以通过对字符串插入变量或表达式,并使用多行字符串声明的方式,来完全抛弃不优雅的字符串拼接,实现字符串格式化组合。
getInfo () => '''
购物车信息:
-----------------------------
  用户名: $name
  优惠码: $code
  总价: $price
  Date: $date
-----------------------------
''';
对象初始化方式的优化
  • 在main函数中初始化。
ShoppingCart sc = ShoppingCart('张三', '123456') ;
  • 首先,在对 ShoppingCart 的构造函数进行了大量简写后,我们希望能够提供给调用者更明确的初始化方法调用方式,让调用者以“参数名: 参数键值对”的方式指定调用参数,让调用者明确传递的初始化参数的意义。在 Dart 中,这样的需求,我们在声明函数时,可以通过给参数增加{}实现。
  • 其次,对一个购物车对象来说,一定会有一个有用户名,但不一定有优惠码的用户。因此,对于购物车对象的初始化,我们还需要提供一个不含优惠码的初始化方法,并且需要确定多个初始化方法与父类的初始化方法之间的正确调用顺序。
  • 由于优惠码可以为空,我们还需要对 getInfo 方法进行兼容处理。在这里,我用到了 a??b 运算符,这个运算符能够大量简化在其他语言中三元表达式 (a != null)? a : b 的写法。
class ShoppingCart extends Meta{
  ...
  //默认初始化方法,转发到withCode里
  ShoppingCart({name}) : this.withCode(name:name, code:null);
  //withCode初始化方法,使用语法糖和初始化列表进行赋值,并调用父类初始化方法
  ShoppingCart.withCode({name, this.code}) : date = DateTime.now(), super(name,0);

  //??运算符表示为code不为null,则用原值,否则使用默认值"没有"
  getInfo () => '''
购物车信息:
-----------------------------
  用户名: $name
  优惠码: ${code??"没有"}
  总价: $price
  Date: $date
-----------------------------
''';
}

void main() {
  ShoppingCart sc = ShoppingCart.withCode(name:'张三', code:'123456');
  sc.bookings = [Item('苹果',10.0), Item('鸭梨',20.0)];
  print(sc.getInfo());

  ShoppingCart sc2 = ShoppingCart(name:'李四');
  sc2.bookings = [Item('香蕉',15.0), Item('西瓜',40.0)];
  print(sc2.getInfo());
}
-----------------------------------------------------------------------
购物车信息:
-----------------------------
  用户名: 张三
  优惠码: 123456
  总价: 30.0
  Date: 2019-06-01 19:59:30.443817
-----------------------------

购物车信息:
-----------------------------
  用户名: 李四
  优惠码: 没有
  总价: 55.0
  Date: 2019-06-01 19:59:30.451747
-----------------------------
  • 关于购物车信息的打印,我们是通过在 main 函数中获取到购物车对象的信息后,使用全局的 print 函数打印的,我们希望把打印信息的行为封装到 ShoppingCart 类中。而对于打印信息的行为而言,这是一个非常通用的功能,不止 ShoppingCart 类需要,Item 对象也可能需要。
  • 因此,我们需要把打印信息的能力单独封装成一个单独的类 PrintHelper。但,ShoppingCart 类本身已经继承自 Meta 类,考虑到 Dart 并不支持多继承,我们怎样才能实现 PrintHelper 类的复用呢?只要在使用时加上 with 关键字即可。
abstract class PrintHelper {
  printInfo() => print(getInfo());
  getInfo();
}

class ShoppingCart extends Meta with PrintHelper{
...
}
  • 经过 Mixin 的改造,我们终于把所有购物车的行为都封装到 ShoppingCart 内部了。而对于调用方而言,还可以使用级联运算符“…”,在同一个对象上连续调用多个函数以及访问成员变量。使用级联操作符可以避免创建临时变量,让代码看起来更流畅。
void main() {
  ShoppingCart.withCode(name:'张三', code:'123456')
  ..bookings = [Item('苹果',10.0), Item('鸭梨',20.0)]
  ..printInfo();

  ShoppingCart(name:'李四')
  ..bookings = [Item('香蕉',15.0), Item('西瓜',40.0)]
  ..printInfo();
}
完整代码
class Meta {
  double price;
  String name;
  //成员变量初始化语法糖
  Meta(this.name, this.price);
}

class Item extends Meta{
  Item(name, price) : super(name, price);
  //重载+运算符,将商品对象合并为套餐商品
  Item operator+(Item item) => Item(name + item.name, price + item.price); 
}

abstract class PrintHelper {
  printInfo() => print(getInfo());
  getInfo();
}

//with表示以非继承的方式复用了另一个类的成员变量及函数
class ShoppingCart extends Meta with PrintHelper{
  DateTime date;
  String code;
  List<Item> bookings;
  //以归纳合并方式求和
  double get price => bookings.reduce((value, element) => value + element).price;
  //默认初始化函数,转发至withCode函数
  ShoppingCart({name}) : this.withCode(name:name, code:null);
  //withCode初始化方法,使用语法糖和初始化列表进行赋值,并调用父类初始化方法
  ShoppingCart.withCode({name, this.code}) : date = DateTime.now(), super(name,0);

  //??运算符表示为code不为null,则用原值,否则使用默认值"没有"
  @override
  getInfo() => '''
购物车信息:
-----------------------------
  用户名: $name
  优惠码: ${code??"没有"}
  总价: $price
  Date: $date
-----------------------------
''';
}

void main() {
  ShoppingCart.withCode(name:'张三', code:'123456')
  ..bookings = [Item('苹果',10.0), Item('鸭梨',20.0)]
  ..printInfo();

  ShoppingCart(name:'李四')
  ..bookings = [Item('香蕉',15.0), Item('西瓜',40.0)]
  ..printInfo();
}
开源Flutter3.19仿抖音实战(开发自己的抖音APP) 开源Flutter3.19仿抖音实战(开发自己的抖音APP),最近有空的时候用flutter3做了一个抖音的项目,方便大家学习,提供源码,有操作思路。原创开发基于flutter3.19.5+dart3.3.3+getx等技术开发仿抖音app实战项目。实现了类似抖音整屏丝滑式上下滑动视频、左右滑动切换页面模块 阅读详情

相关推荐

自创Flutter3.19仿哔哩哔哩源码,结果很满意

总结:回顾全书内容,总结关键点。展望:讨论Flutter的未来发展方向和新技术趋势。常言道,学而不思则罔,思而不学则殆。在学习flutter时也应该多多思考,积极消化自己不会的知识,这也能强化我们的技术水平,帮助我们更好适应快节奏的开发进程,成为一名更有竞争力的Android开发者!由于文件比较大,这里只是将部分截图出来,如果你觉得这些内容对你有帮助:【扫描下方卡片即可免费领取!!!flutter中文网。

flutter开发app的博客 1161

Flutter 验证字符是否为空

在日常开发中,可能存在必须检查给定字符串是null还是empty的情况。那么我们如何去验证呢?这里我将记录一个我自己封装的验证方法。

半身风雪 3619

移动端跨平台开发技术对比与选型指南

跨平台开发技术通过共享代码库显著提升移动应用开发效率,其核心原理是在不同操作系统上构建统一的抽象层。React Native采用JavaScript桥接原生组件的方式,支持热更新和渐进式迁移;Flutter则通过自建渲染引擎实现高性能UI渲染。这些技术大幅降低了企业同时维护iOS和Android应用的成本,特别适合需要快速迭代的电商、社交类应用。随着React Native新架构和Flutter 3.0的发布,跨平台方案在性能与功能上已接近原生开发。在实际项目中,技术选型需综合考虑团队技能栈、产品性能需求和

weixin_30587927的博客 416

Flutter 里的语法糖解析,知其所然方能潇洒舞剑,10天用Flutter撸了个高仿携程App

如下图所示,「起因是昨天在群里看到一个很基础的问题」,问: “这段代码为什么不能对 user 进行判空?” 。 其实这个问题很简单: 1、在 Dart 的 **「Sound Null Safety」* 下声明了非空的对象是不需要判空;(你想判断也行,会有警告⚠️) 2、使用了 late 关键字声明的对象,如果在没有初始化的时候直接访问,就会报错; 所以这个问题其实很简单,只需要改成 User? user 就可以简单解决,「但是为什么本来不可以为空的对象,加了 late 就可以不马上初始化呢

m0_66264569的博客 1104

基于Flutter 3.19 仿小红书商业级app(高手之路)

基于Flutter 3.19 仿小红书商业级app(高手之路),最近有空的时候用flutter3做了一个小红书的项目,方便大家学习,提供源码,有操作思路。原创开发基于flutter3.19.5+dart3.3.3+getx等技术开发仿小红书app实战项目。

flutter开发app的博客 2656

Flutter面试核心考察点与实战解析

Flutter作为Google推出的跨平台UI框架,其核心架构基于Widget树、Element树和RenderObject树的三层设计。开发者需要深入理解其响应式编程模型,掌握Dart语言的异步处理与空安全特性。在工程实践中,状态管理方案选型(如Provider、BLoC)和性能优化(如列表渲染、内存管理)直接影响应用质量。特别是在电商等高交互场景中,合理处理文本溢出、优化页面跳转等细节能显著提升用户体验。通过分析Widget体系原理和混合开发实践,本文详解Flutter面试中的12个高频技术问题及其解决

weixin_30846347的博客 225

Flutter 系列之空安全

一.走进空安全 什么是空安全 从Flutter 2开始,Flutter便在配置中默认启用了空安全,通过将空检查合并到类型系统中,可以在开发过程中捕获这些错误,从而防止再生产环境导致的崩溃。 引入空安全的好处 可以将原本运行时的控制引用错误变为编辑时的分析错误 增强程序的健壮性,有效避免由Null 而导致的崩溃 跟随Dart 和Flutter 的发展趋势,为程序的后续迭代不留坑 空安全的最小必备知识 空安全百度原则 引入空安全前后Dart 类型系统的变化 可空(?)类型的使用 延迟初始化(late)

Android SVG之pathData 2348

Cluster Computing投稿

在overleaf中新建picins.sty文件,该文件是导入的包在.tex文件中添加以下内容\usepackage{picins}%实现作者简介%下边这块有几个人复制几段\vspace{0\baselineskip} %这一行控制作者间隔,可视情况改数字!!!!!!!!

这里是萤石ym的学习路途,努力搬砖! 5533

Flutter学习3 - Dart 空安全

主要介绍 Dart 空安全

weixin_41733225的博客 1066

51单片机学习(5)-----蜂鸣器的介绍与使用

蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计 算机、 打印机、 复印机、 报警器、 电子玩具、 汽车电子设备、 电话机、 定 时器等电子产品中作发声器件。蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。1.半导体三极管也称为晶体三极管,可以说它是电子电路中最重要的器件。三极管顾名思义具有三个电极。二极管是由一个PN结构成的,而三极管由两个PN结构成,共用的一个电极成为三极管的基极(用字母b表示)。其他的两个电极成为集电极(用字母c表示)和发射极(用字母e表示)。

2302_80260350的博客 1万+

ATE测试基础——直流参数测试

芯片测试在发展过程中诞生了许多术语,初次接触的人大部分都会被绕晕。因此为方便广大读者理解,在开始介绍测试项之前,需要对测试领域的名词进行解释。还有部分较为抽象的内容,需要略作展开。DUT——Device Under Test,正在被测试的器件Pin——器件引脚,信号引脚分为输入,输出,三态和双向四类,负责与外界进行信息交互;电源引脚分为电源和地两类,结构与信号引脚不同,负责给器件内部运行和外部输出提供电平。输入:在外部信号和器件内部逻辑之间起缓冲作用的信号输入通道;

你骄傲地飞远的博客 1万+

flutter 服务器返回数据判断是否为空

可以用result!= null && result.isNotEmpty作判断,如果为空就显示缺省图,还可以用数据长度来判断,result.length!2.之后就是那一整块数据里面的各个小数据,都要判断一下,如果为null就用a?1.那一整块数据是否为null,还是返回[]......

weixin_44911775的博客 1978

ADS入门学习笔记——射频振荡器的设计

振荡器是射频系统中的基本部件之一,可以将直流功率转换为射频功率,在特定的频率点建立起稳定的正弦振荡,成为所需的射频信号源。

weixin_42126696的博客 8945

2025终极指南:Flutter Material 3默认启用的底层技术与实战解析

Flutter Material 3作为2025年移动应用开发的新范式,彻底改变了UI设计的方式。Material 3默认启用机制让开发者能够快速构建现代化的应用程序,同时提供更加丰富的色彩系统和组件样式。本文将深入解析Material 3的核心特性、底层技术实现以及实战应用技巧。 ## 🚀 Material 3核心特性概览 Material 3带来了全新的设计语言,包括动态色彩系统、更新的

gitblog_00743的博客 435

【IC】Redhawk-SC输入件配置

Redhawk sc

u011808788的博客 1776

30天入门 SAP BTP 开发系列之七:动手在 SAP BTP 上开发第一个 ABAP 程序

本教程从理论转向实践,指导如何在SAP BTP上创建首个ABAP程序。首先通过Booster向导在Trial账号中配置ABAP环境,需确保已启用Cloud Foundry并创建Space。成功创建ABAP实例后,使用ABAP Development Tool连接环境:下载服务密钥文件,导入工具获取连接URL,即可建立项目开始编码。教程提供了从环境搭建到开发工具配置的完整流程,帮助ABAP开发者快速上手BTP云开发。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1673

flutter技术入门与实战!我的头条面试经历分享,3面直接拿到offer

金九银十过后各大网络平台都是各种面经分享,包括已收offer,或面试失败的都有,相信大部分人都拿到了自己心仪的大厂offer,不过也有没有少数没能进到自己内心向往的大厂而懊恼的,那么到底如何才能进大厂,该准备些什么才能进大厂? 此时字节总监有话说,针对面试字节跳动,大佬总结了一些面试点,相信在其它面试中也能带来不少的帮助,今天小编把它整理好了,希望可以帮到更多的小伙伴。 阿里巴巴 面试问题还记得一些,一部分已经忘记了,为了防止再忘记,所以写出来。 1:你是如何理解Android操作系统的。 2:是否熟悉fr

chayel123的博客 312

YOLO26涨点改进 | NeurIPS2025最佳论文!注意力改进篇| 引入Gated Attention门控注意力模块、太牛了!直接拯救了大模型的发展,助力目标检测、图像分割、图像分类有效涨点

本文提出了一种基于门控注意力机制(GatedAttention)的YOLO26模型改进方法。该方法在标准softmax注意力机制中引入头部特定的sigmoid门控,通过增强注意力机制使模型更聚焦于关键信息。实验表明,该模块能显著提升模型性能,特别是在复杂背景和密集目标场景中,同时减少无关区域关注并提高检测精度。门控机制引入的非线性和稀疏性不仅提升了推理效率,还改善了训练稳定性,使模型能采用更大学习率并增强扩展性。此外,该方法有效缓解了"注意力下沉"现象,增强了模型对长距离目标的感知能力。

Ai缝合怪、助力小伙伴高效发论文 652

flutter技术入门与实战!Android学习笔记在互联网上火了,3面直接拿到offer

1、项目介绍 Flutter是目前比较流行的跨平台开发技术,凭借其出色的性能获得很多前端技术爱好者的关注,比如阿里闲鱼,美团,腾讯等大公司都有投入相关案例生产使用。 基于Flutter+Dart+chewie+photo_view+image_picker等技术开发的跨平台仿微信app聊天界面应用,实现了消息/表情发送、图片预览、长按菜单、红包/小视频/朋友圈等功能。 面试大纲 1.java基础、面向对象、集合、线程使用; 2.Android 机型适配、SDK适配、内存优化、内存溢出、内存泄漏;3.MVC

左夜天 191

【ZYNQ】VDMA 的使用

VDMA, Video Direct Memory Access 是 Xilinx 官方提供的高速内存存取 IP,采用 AXI4-Stream 与 AXI4 协议实现存储映射接口(Memory Map)与非存储映射接口(Non-Memory Map)接口的转换,主要用于视频数据缓存,同时提供帧缓存与帧同步控制功能。本文主要介绍 AXI VDMA 的配置与使用方法。

洋洋Young的博客 1576

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

flutter都出到3.X了,flutter会成为一片蓝海吗?

先说个人的看法和结论:在现如今众多的前端技术方案中,选择学习 Flutter 是一个明智的选择。10.1 自定义组件方法简介10.2 组合现有组件10.3 组合实例:TurnBox10.4 CustomPaint 与 Canvas10.5 自绘实例:圆形背景渐变进度条10.6 自绘组件:CustomCheckbox10.7 自绘组件: DoneWidget10.8 水印实例: 文本绘制与离屏渲染。

datian1234的博客 375

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Flutter中文网创始人网红书《Flutter实战》重磅更新!【留言送书】

大家好,我是若川。之前送过N次书,可以点此查看回馈粉丝,现在又和机械工业出版社划华章图书合作再次争取了几本书,具体送书规则看文末。转眼间从《Flutter实战》第1版电子版发布到现在已近两年,两年中,第1版实体书出版并成为Flutter技术类畅销书之一,其电子版官网UV用户数超过60万,日访问量长期稳定在3500人左右。当然,取得如此成绩最主要的一个原因是这两年 Flutter 技术热度持续提高,...

u012384510的博客 452

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Flutter开发教程合集

weixin_53721706的博客 426

Flutter跨平台开发全解析:从原理到实战的深度指南

Flutter凭借其独特的自绘引擎、高效的渲染管道和丰富的组件库,正在重新定义跨平台开发的标准。Flutter的三层架构与渲染原理声明式UI编程范式与状态管理方案性能优化的12个核心技巧完整的电商应用开发实战随着Flutter 3.0的发布,其对Web和桌面端的支持更加完善,未来将覆盖更多开发场景。建议开发者持续关注Flutter官方文档和社区动态,掌握最新技术特性,在跨平台开发领域保持竞争力。参考文献Flutter官方文档Dart语言规范Flutter性能优化最佳实践。

2302_80693444的博客 1054

Flutter面试全攻略:从原理到实战的深度技术能力评估

在跨平台移动开发领域,掌握核心原理与工程实践是构建高质量应用的关键。Flutter作为Google推出的UI工具包,其高性能渲染引擎和响应式框架设计,为开发者提供了高效的开发体验。理解其底层机制,如Widget树、Element树与RenderObject树的协同工作原理,以及Dart语言的异步编程模型,是进行性能优化和架构设计的基础。这些技术能力直接决定了应用的流畅度、稳定性和可维护性。在实际开发中,状态管理方案的选择、网络请求的健壮性处理、混合开发的通信机制,以及针对线上问题的监控与排查,构成了工程实践

weixin_33404102的博客 350

‌Flutter 3.0 跨平台开发:自定义渲染与性能调优

Flutter 的渲染流程基于 Widget → Element → RenderObject 三棵树。自定义渲染主要通过以下方式实现:CustomPaint 组件 使用 实现自定义绘制逻辑: RenderObject 直接操作 继承 实现底层渲染控制: Shader 特效 利用片段着色器实现高级效果(需导入 ): 问题:500+ 粒子导致帧率降至 30fps 解决方案: 结果:帧率稳定至 60fps,内存占用降低 4

2501_93893723的博客 943
上一篇: Flutter技术与实战(2)
下一篇: Flutter技术与实战(4)
八归少年
八归少年 新星创作者: 操作系统技术领域 新星创作者: 操作系统技术领域
博客等级 码龄9年 9011粉丝 63原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

八归少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值