[关闭]
@TryLoveCatch 2020-06-04T16:10:11.000000Z 字数 14209 阅读 1555

Flutter之Dart

flutter dart


不会Dart,还搞什么Flutter?
1.4 Dart语言简介

const与final的区别

Dart中const与final的区别

它们的区别在于,const比final更加严格。

  1. int Func() {
  2. // 代码
  3. }
  4. final int m1 = 60;
  5. final int m2 = Func(); // 正确
  6. const int n1 = 42;
  7. const int n2 = Func(); // 错误

在上面的例子中,虽然m2的值是不变的,但如果不把代码运行起来,你无法知道m2是多少。

assert

  1. assert(条件, 可选信息)
  1. int number = 200;
  2. assert(number > 100);// 正常
  3. assert(number < 100);// 报错
  4. assert(urlString.startsWith('https'),
  5. 'URL ($urlString) should start with "https".');

Assert不会影响生产环境中代码的执行,仅仅在Flutter的调试模式时生效。(如果你是用 Android Studio 的 bug 图标运行,或者在命令行执行 flutter run,则默认会使用 debug 模式。)

可选参数

可选命名参数

定义

定义函数时,使用{param1, param2, …}的形式来指定命名参数:

  1. coffeeFlavor ({bool sugar , bool sugar}) {
  2. }

使用

调用方法的时候,可以使用 paramName: value 的形式来指定参数的名称,这样就可以根据paramName得知参数的含义,提高代码的可读性。

  1. coffeeFlavor(sugar true sugar false );

可选位置参数

定义

把函数的参数放到 [] 中就变成可选位置参数了:

  1. String go(String to, [String who]) {
  2. var result = 'go to the $to';
  3. if (who != null) {
  4. result = '$result with $who';
  5. }
  6. return result;
  7. }

使用

  1. go('beijing');
  2. go('beijing', 'me');

默认参数

可以使用 = 来定义可选参数的默认值, 默认值必须是编译时常量。如果没有提供默认值,则默认值为 null。

  1. String go(String to, [String who= 'me']) {
  2. var result = 'go to the $to';
  3. if (who != null) {
  4. result = '$result with $who';
  5. }
  6. return result;
  7. }
  8. String result= go ('beijing');// beijing with me

匿名函数

没有名字的匿名方法,格式如下所示:

  1. ([[Type] param1[, …]]) {
  2. codeBlock;
  3. };

定义了一个参数为i(该参数没有指定类型)的匿名函数。list中的每个元素都会调用这个函数打印出来:

  1. var list = ['张无忌', '风清扬', '张三丰', '独孤求败', '萧峰'];
  2. list.forEach((i) {
  3. print(list.indexOf(i).toString() + ': ' + i);
  4. });

函数作为参数

这个在集合操作里面比较常见:

  1. E firstWhere(bool test(E element), {E orElse()}) {
  2. for (E element in this) {
  3. if (test(element)) return element;
  4. }
  5. if (orElse != null) return orElse();
  6. throw IterableElementError.noElement();
  7. }
  8. void forEach(void f(E element)) {
  9. for (E element in this) f(element);
  10. }

上面两个例子的bool test(E element)就都是函数作为参数

调用可以有两种方式:

  1. var list = ['张无忌', '风清扬', '张三丰', '独孤求败', '萧峰'];
  2. void print(var test) {
  3. print(test);
  4. }
  5. /// 注意print,没有括号,不是调用
  6. list.forEach(print);
  7. /// 匿名函数
  8. list.forEach((i) => print(i));

for循环

标准的 for 循环:

  1. var message = new StringBuffer("张无忌");
  2. for (var i = 0; i < 3; i++) {
  3. message.write('!');
  4. }

List和Set等实现了Iterable接口的类还支持for-in形式的遍历:

  1. var hero = ['张无忌', '风清扬', '张三丰', '独孤求败', '萧峰'];
  2. for (var h in hero) {
  3. print(h);
  4. }

异常处理

  1. try {
  2. //...
  3. } on Exception1 {
  4. //...
  5. } on Exception2 catch (e) {
  6. print('exception: $e');
  7. } catch (e) {
  8. print('Something really unknown: $e');
  9. } finally {
  10. //...
  11. }

多继承

Dart是一个面向对象编程语言,支持基于Mixin的继承机制。Mixin可以理解为多继承,在with关键字的后面为一个或者多个类。

  1. class Person{
  2. run(){
  3. print('跑');
  4. }
  5. }
  6. class Wushu{
  7. use(){
  8. print('乾坤大挪移');
  9. }
  10. }
  11. class Zhangwuji extends Person with Wushu{
  12. int age;
  13. Zhangwuji(int age){
  14. this.age=age;
  15. }
  16. }
  17. void main() {
  18. var zhangwuji=new Zhangwuji(30);
  19. zhangwuji.run();
  20. zhangwuji.use();
  21. }

引入库

  1. import 'dart:io';
  2. import 'package:mylib/mylib.dart';
  3. import 'package:utils/utils.dart';
  4. import '../lib/my.dart';

指定库前缀

如果导入的两个库具有冲突的名字, 可以使用库的前缀来进行区分。例如,如果library1和library2 都有一个名字为Element的类,可以这样使用:

  1. import 'package:lib1/lib1.dart';
  2. import 'package:lib2/lib2.dart' as lib2;
  3. // ...
  4. Element element1 = new Element(); //使用lib1中的Element
  5. lib2.Element element2 = new lib2.Element(); //使用lib2中的Element

导入库的一部分

如果只使用库的一部分功能,则可以选择需要导入的部分内容。其中show代表只导入指定的部分,hide代表除了指定的部分都导入。

  1. // 只导入foo
  2. import 'package:lib1/lib1.dart' show foo;
  3. // 除了foo,其他部分都导入
  4. import 'package:lib2/lib2.dart' hide foo;

延迟加载库

延迟加载意味着应用程序可以在需要的时候再加载库,使用延迟加载库的场景主要有以下几点:

要延迟加载一个库,需要先使用 deferred as来导入:

  1. import 'package:deferred/hello.dart' deferred as hello;

当需要使用的时候,调用loadLibrary() 函数来加载库:

  1. greet() async {
  2. await hello.loadLibrary();
  3. hello.printGreeting();
  4. }

异步

Flutter/Dart中的异步

简单说下,Dart的事件循环机制:

  • 循环中有两个队列。一个是微任务队列(MicroTask queue),一个是事件队列(Event queue)。
  • 事件队列包含外部事件,例如I/O, Timer,绘制事件等等。
  • 微任务队列则包含有Dart内部的微任务,主要是通过scheduleMicrotask来调度。

Dart的事件循环的运行遵循以下规则:

  • 首先处理所有微任务队列里的微任务。
  • 处理完所有微任务以后。从事件队列里取1个事件进行处理。
  • 回到微任务队列继续循环。

也就是说:

注意第一步里的所有,也就是说在处理事件队列之前,Dart要先把所有的微任务处理完。如果某一时刻微任务队列里有8个微任务,事件队列有2个事件,Dart也会先把这8个微任务全部处理完再从事件队列中取出1个事件处理,之后又会回到微任务队列去看有没有未执行的微任务。

原始方法

调用scheduleMicrotask来让代码以微任务的方式异步执行

  1. scheduleMicrotask((){
  2. print('a microtask');
  3. });

调用Timer.run来让代码以Event的方式异步执行

  1. Timer.run((){
  2. print('a event');
  3. });

仅仅使用回调函数来做异步的话很容易陷入“回调地狱(Callback hell)”,为了避免这样的问题,JS引入了Promise。同样的, Dart引入了Future。

Future

要使用Future的话需要引入dart.async

  1. import 'dart:async';
  1. Future(() => print('立刻在Event queue中运行的Future'));
  1. Future.delayed(const Duration(seconds:1), () => print('1秒后在Event queue中运行的Future'));
  1. Future.microtask(() => print('在Microtask queue里运行的Future'));
  1. Future.sync(() => print('同步运行的Future'));

这里要注意一下:

  • Future.sync()的同步运行指的是构造Future的时候传入的函数是同步运行的
  • Future.sync()通过then串进来的回调函数是调度到微任务队列异步执行的。
  1. Future(()=> throw 'we have a problem')
  2. .then((_)=> print('callback1'))
  3. .then((_)=> print('callback2'))
  4. .catchError((error)=>print('$error'))
  5. .whenComplete(()=> print('whenComplete'));

这里也需要注意一下:

  • then串起来的回调函数会按照链接的顺序依次执行
  • then串起来的回调函数有可能同步也有可能异步
  • catchError可以捕获task和then的异常
  • whenComplete一定会被执行,无论Future是正常执行完毕还是抛出异常

针对上买呢的第二条,我们再来说一点:

  1. 你通过then串起来的那些回调函数在Future完成的时候会被立即执 行,也就是说它们是同步执行,而不是被调度异步执行。
  2. 如果Future在调用then串起回调函数之前已经完成,
    那么这些回调函数会被调度到微任务队列异步执行。这个就是Future.sync()
  3. 通过Future()和Future.delayed()实例化的Future不会同步执行,它们会被调度到事件队列异步执行。
  4. 通过Future.value()实例化的Future会被调度到微任务队列异步完成,类似于第2条。
  5. 通过Future.sync()实例化的Future会同步执行其入参函数,然后(除非这个入参函数返回一个Future)调度到微任务队列来完成自己,类似于第2条。

Future相对于调度回调函数来说,缓减了回调地狱的问题。但是如果Future要串起来的的东西比较多的话,代码还是会可读性比较差。特别是各种Future嵌套起来,是比较烧脑的。

async/await

async和await是什么?它们是Dart语言的关键字,可以让你用同步代码的形式写出异步代码。

看一个例子:

  1. foo() async {
  2. print('foo E');
  3. String value = await bar();
  4. print('foo X $value');
  5. }
  6. bar() async {
  7. print("bar E");
  8. return "hello";
  9. }
  10. main() {
  11. print('main E');
  12. foo();
  13. print("main X");
  14. }

执行结果:

  1. main E
  2. foo E
  3. bar E
  4. main X
  5. foo X hello

我们主要来看这个:

  1. foo() async {
  2. print('foo E');
  3. String value = await bar();
  4. print('foo X $value');
  5. }

这个会被分成两部分:

  1. foo() async {
  2. print('foo E');
  3. Future future = bar()
  4. ---------------------------
  5. String value = await future;
  6. print('foo X $value');
  7. }

分割线上面的会先执行,await后面的必须是一个Future,然后,分割线下面的就会以then的方式链入这个Future被异步调度执行。

相当于:

  1. foo() {
  2. print('foo E');
  3. return Future.sync(bar).then((value) => print('foo X $value'));
  4. }
  • async标注的函数其返回值类型是Future
  • await后面必须是Future对象
  • await并不像字面意义上程序运行到这里就停下来啥也不干等待Future完成。而是立刻结束当前函数的执行并返回一个Future。函数内剩余代码通过调度异步执行。
  • await只能在async函数中出现。
  • async函数中可以出现多个await,每遇见一个就返回一个Future, 实际结果类似于用then串起来的回调。
  • async函数也可以没有await, 在函数体同步执行完毕以后返回一个Future,相当于第一条

另外,使用async和await还有一个好处是我们可以用和同步代码相同的try/catch机制来做异常处理。

  1. foo() async {
  2. try {
  3. print('foo E');
  4. var value = await bar();
  5. print('foo X $value');
  6. } catch (e) {
  7. // 同步执行代码中的异常和异步执行代码的异常都会被捕获
  8. } finally {
  9. }
  10. }

类变成方法

如果Dart中的类实现了call()函数,那么这个类可以当做方法来调用。

  1. class JointFunction {
  2. call(String a, String b, String c, String d) => '$a $b $c $d';
  3. }
  4. main() {
  5. var jf = new JointFunction();
  6. var out = jf("放","手","去","做");
  7. print('$out');
  8. }

创建实例

在Java中创建实例可以用new,在Dart中你可以选择用new,也可以选择不用:

  1. Element element = Element();

下划线私有

在 Dart 语言中使用下划线前缀标识符,会 强制其变成私有。

构造函数

Dart构造函数介绍
Dart学习笔记(五):类
通过类的构造函数给实例添加变量:

  1. main(List<String> args) {
  2. Dog d = new Dog('Duffy', 2);
  3. print(d.name);
  4. }
  5. class Dog {
  6. String name;
  7. int age;
  8. Dog(String name, Stirng age) {
  9. this.name = name;
  10. this.age = age;
  11. }
  12. }

语法糖构造函数

  1. main(List<String> args) {
  2. Dog d = new Dog('Duffy', 2);
  3. print(d.name);
  4. }
  5. class Dog {
  6. String name;
  7. int age;
  8. // 这里~~~~~~~~
  9. Dog(this.name, this.age);
  10. }

第一个参数,对应到name
第二个参数对应age

命名构造函数

  1. main(List<String> args) {
  2. Dog d = new Dog.newBorn();
  3. print(d.name);
  4. }
  5. class Dog {
  6. String name;
  7. int age;
  8. Dog(this.name, this.age);
  9. // 这里~~~~~~~
  10. Dog.newBorn() {
  11. name = 'Doggy';
  12. age = 0;
  13. }
  14. }

我们在flutter的plugin里面会发现很多类似的用法:

  1. class GoogleMapController {
  2. GoogleMapController._(
  3. this.channel,
  4. CameraPosition initialCameraPosition,
  5. this._googleMapState,
  6. ) : assert(channel != null) {
  7. channel.setMethodCallHandler(_handleMethodCall);
  8. }
  9. ...
  10. }

类似于这种._,这个私有的命名构造函数。
_既表示是私有,又表示命名,是命名构造函数。

常量构造函数

  1. class ImmutablePoint {
  2. final num x, y;
  3. const ImmutablePoint(this.x, this.y);
  4. }
  1. var a = const ImmutablePoint(1, 1);
  2. var b = const ImmutablePoint(1, 1);
  3. identical(a, b); // true
  4. var a = ImmutablePoint(1, 1);
  5. var b = ImmutablePoint(1, 1);
  6. identical(a, b); // false
  7. var a = const ImmutablePoint(1, 1);
  8. var b = const ImmutablePoint(1, 2);
  9. identical(a, b); // false

identical

identical,测试两个对象是否是同一个对象(indentity test)
==是我们自己实现的一个方法,是否==取决于你的实现方式

  1. @override
  2. bool operator ==(Object other) {
  3. if (identical(this, other)) {
  4. return true;
  5. }
  6. if (runtimeType != other.runtimeType) {
  7. return false;
  8. }
  9. return other is ImmutablePoint
  10. && other.a == a
  11. && other.b == b;
  12. }

runtimeType可以获得一个示例的类型,该属性返回一个Type对象

  1. main() {
  2. int a = 1;
  3. print('type of a is ${a.runtimeType}');// 输出:type of a is int
  4. }

一般来说:

继承

构造函数

Pug类继承了Dog类,并且在Pug的构造函数里用SUPER关键字调用了Dog类的构造函数

  1. main(List<String> args) {
  2. Pug p = new Pug('Duffy', 5);
  3. print(p.name);
  4. }
  5. class Dog {
  6. String name;
  7. int age;
  8. Dog(this.name, this.age);
  9. Dog.newBorn() {
  10. name = 'Doggy';
  11. age = 0;
  12. }
  13. }
  14. // 这里~~~~~~~~~
  15. class Pug extends Dog {
  16. Pug(String name, int age): super(name, age);
  17. }

在一个类里还可以调用其他的构造函数,通过在(:)冒号后调用this关键字

  1. main(List<String> args) {
  2. Pug p = new Pug.small('Duffy');
  3. print(p.name);
  4. }
  5. class Dog {
  6. String name;
  7. int age;
  8. Dog(this.name, this.age);
  9. Dog.newBorn() {
  10. name = 'Doggy';
  11. age = 0;
  12. }
  13. }
  14. // 这里~~~~~~~~~
  15. class Pug extends Dog {
  16. Pug(String name, int age): super(name, age);
  17. Pug.small(Stirng name): this(name, 1);
  18. Pug.large(Stirng name): this(name, 3);
  19. }

方法

方法重写

  1. main(List<String> args) {
  2. Pug p = new Pug.small('Duffy');
  3. p.bark();
  4. }
  5. class Dog {
  6. String name;
  7. int age;
  8. Dog(this.name, this.age);
  9. Dog.newBorn() {
  10. name = 'Doggy';
  11. age = 0;
  12. }
  13. bark() {
  14. print('Bow Wow');
  15. }
  16. }
  17. class Pug extends Dog {
  18. Pug(String name, int age): super(name, age);
  19. Pug.small(Stirng name): this(name, 1);
  20. Pug.large(Stirng name): this(name, 3);
  21. // 这里~~~~~~~~~
  22. @override
  23. bark() {
  24. print('Meow!');
  25. }
  26. }

getter setter

默认的情况下类里定义的任何变量都是可以访问的,如dog.name,变量的值也可以直接读写。但是有时候不希望直接读写而是通过getter setter。dart里 是通过get set 关键字实现的:

  1. main(List<String> args) {
  2. Dog d = new Dog('Duffy', 5);
  3. d.respectedName = 'Mr.Duffy';
  4. print(d.respectedName);
  5. }
  6. class Dog {
  7. String name;
  8. int age;
  9. Dog(this.name, this.age);
  10. // 这里~~~~~~~~~
  11. String get respectedName {
  12. return 'Mr.$name';
  13. }
  14. // 这里~~~~~~~~~
  15. set respectedName(String newName) {
  16. name = newName;
  17. }
  18. Dog.newBorn() {
  19. name = 'Doggy';
  20. age = 0;
  21. }
  22. bark() {
  23. print('Bow Wow');
  24. }
  25. }

上面的代码 name 属性依然是可读写的
默认类里的任何属性都是public的,也是是公开的,可以直接访问,如果想保护变量,使变量变成私有的private,只要在变量名称前加"_"即可

抽象类

类前增加了 abstract 关键字

  1. abstract class AbstractDog {
  2. void bark();
  3. void _hiddenMethod();
  4. }

静态方法

在字段或方法前增加static关键字就变成了静态

  1. main(List<String> args) {
  2. Dog.bark();
  3. }
  4. class Dog {
  5. String name;
  6. int age;
  7. Dog(this.name, this.age);
  8. // 这里~~~~~~~~~
  9. static bark() {
  10. print('Bow Wow');
  11. }
  12. }

枚举Enum

  1. main(List<String> args) {
  2. Dog d = new Dog('Duffy', 12, CurrentState.sleeping);
  3. print(d.state == CurrentState.sleeping); //Prints 'true'
  4. }
  5. // 这里~~~~~~~~~
  6. enum CurrentState {
  7. sleeping,
  8. barking,
  9. eating,
  10. walking
  11. }
  12. class Dog {
  13. String name;
  14. int age;
  15. CurrentState state;
  16. Dog(this.name, this.age, this.state);
  17. static bark() {
  18. print('Bow Wow');
  19. }
  20. }

泛型

dart支持泛型,如有一个类,管理一个数据,希望这个数据是任何类型。

  1. main(List<String> args) {
  2. DataHolder<String> dataHolder = new DataHolder('Some data');
  3. print(dataHolder.getData());
  4. dataHolder.setData('New Data');
  5. print(dataHolder.getData());
  6. }
  7. // 这里~~~~~~~~~
  8. class DataHolder<T> {
  9. T data;
  10. DataHolder(this.data);
  11. getData() {
  12. return data;
  13. }
  14. setData(data) {
  15. this.data = data;
  16. }
  17. }

==

Dart学习笔记(五):类

identical()

判断两个引用是否指向同一个对象,是否是同一个内存地址

  1. class Person {
  2. String ssn;
  3. String name;
  4. Person(this.ssn, this.name);
  5. // Define that two persons are equal if their SSNs are equal
  6. bool operator ==(other) {
  7. return (other is Person && other.ssn == ssn);
  8. }
  9. }
  10. main() {
  11. var bob = new Person('111', 'Bob');
  12. var robert = new Person('111', 'Robert');
  13. print(bob == robert); // true
  14. print(identical(bob, robert)); // false, because these are two different instances
  15. }

另外一个例子,工厂构造函数:

  1. class Logger {
  2. final String name;
  3. bool mute = false;
  4. // 缓存实例
  5. static final Map<String, Logger> _cache = <String, Logger>{};
  6. factory Logger(String name) {
  7. if (_cache.containsKey(name)) {
  8. return _cache[name];
  9. } else {
  10. final logger = new Logger._internal(name);
  11. _cache[name] = logger;
  12. return logger;
  13. }
  14. }
  15. Logger._internal(this.name);
  16. void log(String msg) {
  17. if (!mute) {
  18. print(msg);
  19. }
  20. }
  21. }
  22. main() {
  23. var logger1 = new Logger('UI');
  24. var logger2 = new Logger('UI');
  25. identical(logger1, logger2); // true
  26. }

logger1和logger2,指向的是同一个对象

runtimeType

Object类的runtimeType属性,来判断对象的类型,返回一个Type对象:

  1. main() {
  2. int a = 1;
  3. print('type of a is ${a.runtimeType}');
  4. }
  5. // 输出:type of a is int

集合

Iterable

dart Iterable、Stream
Dart中Iterable、Stream的糖语法

double

判断NaN

dart里面没有提供类似java中Double的isNan的方法,所以需要我们自己处理,不能直接使用== double.nan这种方式,方法有两种:

方法一

使用compareTo()

  1. if (mDouble.compareTo(double.nan) == 0) {
  2. }
  1. Examples:
  2. * ```
  3. * print(1.compareTo(2)); // => -1
  4. * print(2.compareTo(1)); // => 1
  5. * print(1.compareTo(1)); // => 0
  6. *
  7. * // The following comparisons yield different results than the
  8. * // corresponding comparison operators.
  9. * print((-0.0).compareTo(0.0)); // => -1
  10. * print(double.nan.compareTo(double.nan)); // => 0
  11. * print(double.infinity.compareTo(double.nan)); // => -1
  12. *
  13. * // -0.0, and NaN comparison operators have rules imposed by the IEEE
  14. * // standard.
  15. * print(-0.0 == 0.0); // => true
  16. * print(double.nan == double.nan); // => false
  17. * print(double.infinity < double.nan); // => false
  18. * print(double.nan < double.infinity); // => false
  19. * print(double.nan == double.infinity); // => false

方法二

  1. /// 判断double 是否为nan
  2. static bool isNan(double value) {
  3. return (value != value);
  4. }
  5. /// 判断double 是否是infinity
  6. static bool isInfinite(double value) {
  7. return (value == double.infinity) || (value == double.negativeInfinity);
  8. }

语法糖

?.

条件成员访问,左边的操作数如果为null,就返回null;否则,就跟.操作符一致

  1. var bar = foo?.bar; // 如果 foo 为 null 则返回 null,否则返回 bar 成员

??

expr1 ?? expr2
如果expr1为非空,则返回其值;否则,计算并返回expr2的值。

  1. b ??= value; // 如果b为null将value赋给b,否则b值不变
  2. // 等价于
  3. if (b == null) {
  4. b = value;
  5. }

..

级联操作符,允许您对同一对象执行一系列操作

  1. querySelector('#button') // Get an object.
  2. ..text = 'Confirm' // Use its members.
  3. ..classes.add('important')
  4. ..onClick.listen((e) => window.alert('Confirmed!'));
  5. // 等价于
  6. var button = querySelector('#button');
  7. button.text = 'Confirm';
  8. button.classes.add('important');
  9. button.onClick.listen((e) => window.alert('Confirmed!'));

as

as 类型转换

  1. (emp as Person).firstName = 'Bob';

is

is 当对象是相应类型时返回 true

  1. if (emp is Person) { // 类型检查
  2. emp.firstName = 'Bob';
  3. }

=>

这种写法只适用函数体中仅有一个表达式的函数,并且返回值为这个表达式的计算结果
=> expr 等同于 { return expr; }

  1. void printNumber(num number) => print(number);

等价于

  1. void printNumber(num number){
  2. print(number);
  3. }

匿名函数也可以这样使用,比如我们上面说到匿名函数的例子:

  1. var list = ['张无忌', '风清扬', '张三丰', '独孤求败', '萧峰'];
  2. list.forEach((i) {
  3. print(list.indexOf(i).toString() + ': ' + i);
  4. });

可以改写为:

  1. var list = ['张无忌', '风清扬', '张三丰', '独孤求败', '萧峰'];
  2. list.forEach((i) => print(list.indexOf(i).toString() + ': ' + i));

拾遗

壹 JSON解析遇到的问题

问题一

native传递json给dart侧,如下:

  1. Map tMap = new HashMap(1);
  2. JSONObject tJsonObject = xxxx;
  3. if (tJsonObject != null) {
  4. tMap.put("info", tJsonObject.toString());
  5. mChannelMethod.invokeMethod("update", tMap);
  6. }

dart接收如下:

  1. dynamic info = call.arguments['info'];
  2. if (info != null) {
  3. try {
  4. Info tInfo = Info.fromJson(info);
  5. } catch(e) {
  6. Logger.getInstance().d(_TAG, '$e', 'info');
  7. }
  8. }

在Info.fromJson(tJson);这一行报错,报错如下:

  1. type 'String' is not a subtype of type 'int' of 'index'

解决:

  1. import 'dart:convert';
  2. dynamic info = call.arguments['info'];
  3. if (info != null) {
  4. try {
  5. var tJson = json.decode(info);
  6. Info tInfo = Info.fromJson(tJson);
  7. } catch(e) {
  8. Logger.getInstance().d(_TAG, '$e', 'info');
  9. }
  10. }

这个是因为传过来的info是String类型的,所以需要解析一下才能使用

问题二

native传递Bitmap给dart侧,然后通过JSON传递List

接收的代码:

  1. Uint8List.fromList(json['directionIcon'])

然后报错,如下:

  1. type 'List<dynamic>' is not a subtype of type 'List<int>'

修改

  1. Uint8List.fromList(json['directionIcon'].cast<int>())
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注