【Flutter】功能型組件之異步UI更新


前言

很多時候會依賴一些異步數據來動態更新UI,比如在打開一個頁面時我們需要先從互聯網上獲取數據,在獲取數據的過程中我們顯示一個加載框,等獲取到數據時我們再渲染頁面;又比如想展示Stream(比如文件流、互聯網數據接收流)的進度。當然,通過StatefulWidget完全可以實現上述這些功能。但由於在實際開發中依賴異步數據更新UI的這種場景非常常見,因此Flutter專門提供了FutureBuilder和StreamBuilder兩個組件來快速實現這種功能。

接口描述

FutureBuilder會依賴一個Future,它會根據所依賴的Future的狀態來動態構建自身。描述如下:

FutureBuilder({
  // FutureBuilder依賴的Future,通常是一個異步耗時任務
  this.future,
  // 初始數據,用戶設置默認數據
  this.initialData,
  // Widget構建器,該構建器會在Future執行的不同階段被多次調用
  // 構建器簽名為:Function(BuildContext context, AsyncSnapshot snapshot)
  // snapshot會包含當前異步任務的狀態信息及結果信息,比如可以通過snapshot.connectionState獲取異步任務的狀態信息,通過snapshot.hasError判斷任務時候有錯誤等
  @required this.builder,
})

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

代碼示例

// 異步UI更新(FutureBuilder\StreamBuilder)


import 'dart:math';

import 'package:flutter/material.dart';

// 實現一個路由,當該路由打開時我們從網上獲取數據,獲取數據時彈一個加載框;獲取結束時,如果成功則顯示獲取到的數據,如果失敗則顯示錯誤。
// 不真正去網絡請求數據,而是模擬一下這個過程,隔3秒后返回一個字符串
Future<String> mockNetworkData() async{
  return Future.delayed(Duration(seconds: 2), () => "我是從互聯網上獲取的數據!");
}

class FutureBuilderTest extends StatelessWidget{
  @override
  Widget build(BuildContext context){
    return 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();
          }
        },
      ),
    );
  }
}


// 創建一個計時器的示例:每隔1秒,計數加1。這里,使用Stream來實現每隔一秒生成一個數字。
Stream<int> counter(){
  return Stream.periodic(Duration(seconds: 1), (i){
    return i;
  });
}

class StreamBuilderTest extends StatelessWidget{
  @override
  Widget build(BuildContext context){
    return StreamBuilder<int>(
      stream: counter(),
      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:
            // TODO: Handle this case.
            return Text("active:${snapshot.data}");
          case ConnectionState.done:
            // TODO: Handle this case.
            return Text("Stream已關閉");
        }
        return null;
      },
    );
  }
}

總結

Dart中Stream 也是用於接收異步事件數據,和Future 不同的是,它可以接收多個異步操作的結果,它常用於會多次讀取數據的異步任務場景,如網絡內容下載、文件讀寫等。StreamBuilder正是用於配合Stream來展示流上事件(數據)變化的UI組件。在實戰中,凡是UI會依賴多個異步數據而發生變化的場景都可以使用StreamBuilder。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM