Flutter 异步编程原理(中)

简介: Flutter 异步编程原理(中)

FutureBuilder 的使用

很多时候我们会依赖一些异步数据来动态更新UI,比如在打开一个页面时我们需要先从互联网上获取数据,在获取数据的过程中我们显式一个加载框,等获取到数据时我们再渲染页面;又比如我们想展示Stream(比如文件流、互联网数据接收流)的进度。


FutureBuilder({
  this.future, // FutureBuilder依赖的Future,通常是一个异步耗时任务
  this.initialData, // 初始数据,用户设置默认数据
  @required this.builder, // Widget构建器:该构建器会在Future执行的不同阶段被多次调用
})


builder 构造器参数结构

Function (BuildContext context, AsyncSnapshot snapshot)


示例:

import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
  Future<String> mockNetworkData() async {
    return Future.delayed(Duration(seconds: 2), () => "这是网络请求的数据。。。");
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: FutureBuilder<String>(
          future: mockNetworkData(),
          builder: (BuildContext context, AsyncSnapshot snapshot) {
            // 请求已结束
            if (snapshot.connectionState == ConnectionState.done) {
              if (snapshot.hasError) {
                // 请求失败,显示错误
                return Text("Error: ${snapshot.error}");
              } else {
                // 请求成功,显示数据
                return Text("Contents: ${snapshot.data}");
              }
            } else {
              // 请求未结束,显示loading
              return CircularProgressIndicator();
            }
          },
        ),
      ),
    // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

演示效果:


image.png

image.png


async/await

在 Dart1.9 中加入了 async 和 await 关键字,有了这两个关键字,我们可以更简洁的编写异步代码,而不需要调用 Future 相关的 API。


使用特点

  • 被修饰的方法会将一个 Future 对象作为返回值;
  • 该方法会同步执行其中的方法的代码直到第一个 await 关键字,然后它暂停该方法其他部分的执行;
  • 一旦由 await 关键字引用的 Future 任务执行完成,await 的下一行代码将立即执行。
// 导入io库,调用sleep函数
import 'dart:io';
// 模拟耗时操作,调用sleep函数睡眠2秒
doTask() async{
  await sleep(const Duration(seconds:2));
  return "Ok";
}
// 定义一个函数用于包装
test() async {
  var r = await doTask();
  print(r);
}
void main(){
  print("main start");
  test();
  print("main end");
}


结果:

main start
main end
Ok


Stream 与 StreamBuilder


Stream 也是用于接收异步事件数据,和 Future 不同的是,它可以接收多个异步操作的结果(成功或失败)。 也就是说,在执行异步任务时,可以通过多次触发成功或失败事件来传递结果数据或错误异常。 Stream 常用于会多次读取数据的异步任务场景,如网络内容下载、文件读写等。


Stream 的使用

void main(){
  print("main start");
  Stream.fromFutures([
    // 1秒后返回结果
    Future.delayed(new Duration(seconds: 1), () {
      return "hello 1";
    }),
    // 抛出一个异常
    Future.delayed(new Duration(seconds: 2),(){
      throw AssertionError("Error");
    }),
    // 3秒后返回结果
    Future.delayed(new Duration(seconds: 3), () {
      return "hello 3";
    })
  ]).listen((data){
    print(data);
  }, onError: (e){
    print(e.message);
  },onDone: (){
  });
  print("main end");
}


结果:

main start
main end
hello 1
Error
hello 3


StreamBuilder 的使用

StreamBuilder正是用于配合Stream来展示流上事件(数据)变化的UI组件。 下面看一下StreamBuilder的默认构造函数:

StreamBuilder({
  Key key,
  this.initialData,
  Stream<T> stream,
  @required this.builder,
})


可以看到和 FutureBuilder 的构造函数只有一点不同:前者需要一个 future,而后者需要一个 stream。 示例:


Stream<int> counter() {
  return Stream.periodic(Duration(seconds: 1), (i) {
    return i;
  });
}
Widget buildStream (BuildContext context) {
  return StreamBuilder<int>(
    stream: counter(), //
    //initialData: ,// a Stream<int> or null
    builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
      if (snapshot.hasError)
        return Text('Error: ${snapshot.error}');
      switch (snapshot.connectionState) {
        case ConnectionState.none:
          return Text('没有Stream');
        case ConnectionState.waiting:
          return Text('等待数据...');
        case ConnectionState.active:
          return Text('active: ${snapshot.data}');
        case ConnectionState.done:
          return Text('Stream已关闭');
      }
      return null; // unreachable
    },
  );
}
return Scaffold(
  appBar: AppBar(
    title: Text(widget.title),
  ),
  body:Center(
    child:  buildStream(context),
  )
);

效果:


image.png

image.png


isolate


Dart 是基于单线程模型的语言。但是在开发当中我们经常会进行耗时操作比如网络请求,这种耗时操作会堵塞我们的代码,所以在 Dart 也有并发机制,名叫 isolate。 APP 的启动入口 main 函数就是一个类似 Android 主线程的一个主 isolate。和 Java 的 Thread 不同的是,Dart 中的 isolate 无法共享内存,类似于 Android 中的多进程。


isolate 与普通线程的区别isolate 神似 Thread,但实际上两者有本质的区别。操作系统内的线程之间是可以有共享内存的,而 isolate 不能。


image.png


isolate 工作原理

isolate 创建主要步骤:

  • 初始化isolate数据结构
  • 初始化堆内存(Heap)
  • 进入新创建的isolate,使用跟isolate一对一的线程运行isolate
  • 配置Port
  • 配置消息处理机制(Message Handler)
  • 配置Debugger,如果有必要的话
  • 将isolate注册到全局监控器(Monitor)


image.png


Dart 本身抽象了 isolate 和 thread,实际上底层还是使用操作系统的提供的 OSThread,Dart isolate 跟 Flutter Runner 是相互独立的,他们通过任务调度机制相互协作。

目录
相关文章
|
1月前
|
开发者 容器
Flutter&鸿蒙next 布局架构原理详解
本文详细介绍了 Flutter 中的主要布局方式,包括 Row、Column、Stack、Container、ListView 和 GridView 等布局组件的架构原理及使用场景。通过了解这些布局 Widget 的基本概念、关键属性和布局原理,开发者可以更高效地构建复杂的用户界面。此外,文章还提供了布局优化技巧,帮助提升应用性能。
103 4
|
1月前
|
存储 Dart 前端开发
flutter鸿蒙版本mvvm架构思想原理
在Flutter中实现MVVM架构,旨在将UI与业务逻辑分离,提升代码可维护性和可读性。本文介绍了MVVM的整体架构,包括Model、View和ViewModel的职责,以及各文件的详细实现。通过`main.dart`、`CounterViewModel.dart`、`MyHomePage.dart`和`Model.dart`的具体代码,展示了如何使用Provider进行状态管理,实现数据绑定和响应式设计。MVVM架构的分离关注点、数据绑定和可维护性特点,使得开发更加高效和整洁。
163 3
|
2月前
动画控制器在 Flutter 中的工作原理
【10月更文挑战第18天】总的来说,动画控制器 `AnimationController` 在 Flutter 中起着关键的作用,它通过控制动画的数值、速度、节奏和状态,实现了丰富多彩的动画效果。理解它的工作原理对于我们在 Flutter 中创建各种精彩的动画是非常重要的。
|
6月前
|
存储 开发框架 JavaScript
深入探讨Flutter中动态UI构建的原理、方法以及数据驱动视图的实现技巧
【6月更文挑战第11天】Flutter是高效的跨平台移动开发框架,以其热重载、高性能渲染和丰富组件库著称。本文探讨了Flutter中动态UI构建原理与数据驱动视图的实现。动态UI基于Widget树模型,状态变化触发UI更新。状态管理是关键,Flutter提供StatefulWidget、Provider、Redux等方式。使用ListView等可滚动组件和StreamBuilder等流式组件实现数据驱动视图的自动更新。响应式布局确保UI在不同设备上的适应性。Flutter为开发者构建动态、用户友好的界面提供了强大支持。
113 2
|
2月前
|
容器
Flutter&鸿蒙next 布局架构原理详解
Flutter&鸿蒙next 布局架构原理详解
|
2月前
|
机器学习/深度学习 开发框架 Dart
Flutter asynchronous 异步编程技巧
本文深入探讨了Flutter中的异步编程技巧,包括Future、Microtask及并发处理的最佳实践。文章详细讲解了Future.wait、FutureBuilder和Microtask的应用,帮助开发者提升应用性能。通过实例演示了如何利用Future.wait实现并发执行,FutureBuilder简化UI构建,以及Microtask的高优先级执行特性。适合希望优化Flutter应用异步性能的开发者阅读。
|
4月前
|
Dart 前端开发 JavaScript
Flutter&Dart-异步编程Future、Stream极速入门
Flutter&Dart-异步编程Future、Stream极速入门
89 4
Flutter&Dart-异步编程Future、Stream极速入门
|
5月前
|
Dart JavaScript Java
flutter 架构、渲染原理、家族
flutter 架构、渲染原理、家族
97 3
|
5月前
|
Dart
flutter 之 Dart 异步编程【详解】
flutter 之 Dart 异步编程【详解】
50 0
|
7月前
|
Android开发
Flutter完整开发实战详解(六、 深入Widget原理),2024百度Android岗面试真题收录解析
Flutter完整开发实战详解(六、 深入Widget原理),2024百度Android岗面试真题收录解析