hocvietcode.com
  • Trang chủ
  • Học lập trình
    • Lập trình C/C++
    • Lập trình HTML
    • Lập trình Javascript
      • Javascript cơ bản
      • ReactJS framework
      • AngularJS framework
      • Typescript cơ bản
      • Angular
    • Lập trình Mobile
      • Lập Trình Dart Cơ Bản
        • Dart Flutter Framework
    • Cơ sở dữ liệu
      • MySQL – MariaDB
      • Micrsoft SQL Server
      • Extensible Markup Language (XML)
      • JSON
    • Lập trình PHP
      • Lập trình PHP cơ bản
      • Laravel Framework
    • Lập trình Java
      • Java Cơ bản
    • Cấu trúc dữ liệu và giải thuật
    • Lập Trình C# Cơ Bản
    • Machine Learning
  • WORDPRESS
    • WordPress cơ bản
    • WordPress nâng cao
    • Chia sẻ WordPress
  • Kiến thức hệ thống
    • Microsoft Azure
    • Docker
    • Linux
  • Chia sẻ IT
    • Tin học văn phòng
      • Microsoft Word
      • Microsoft Excel
    • Marketing
      • Google Adwords
      • Facebook Ads
      • Kiến thức khác
    • Chia sẻ phần mềm
    • Review công nghệ
    • Công cụ – tiện ích
      • Kiểm tra bàn phím online
      • Kiểm tra webcam online
Đăng nhập
  • Đăng nhập / Đăng ký

Please enter key search to display results.

Home
  • Dart Flutter Framework
FutureBuilder và StreamBuilder trong Flutter

FutureBuilder và StreamBuilder trong Flutter

  • 11-06-2024
  • Toanngo92
  • 0 Comments

Mục lục

  • FutureBuilder trong Flutter
    • FutureBuilder Widget trong Flutter
    • Các Trạng thái trong FutureBuilder
  • Tạo ứng dụng để Thể hiện FutureBuilder trong Flutter
  • StreamBuilder trong Flutter
    • Widget StreamBuilder trong Flutter
    • Hàm Generator
    • Tạo Ứng Dụng để Thể Hiện StreamBuilder trong Flutter
  • Sự khác biệt giữa FutureBuilder và StreamBuilder

FutureBuilder trong Flutter

Có một khái niệm gọi là lập trình bất đồng bộ, nơi mà hàm không thể tạo ra kết quả ngay lập tức. Nó cần một thời gian để lấy hoặc xử lý và trả về dữ liệu. Một hàm bình thường sẽ xử lý đầu vào và tạo ra đầu ra của bất kỳ loại nào. Trong khi đó, các hàm bất đồng bộ này sẽ xử lý và tạo ra đầu ra của loại Future, về cơ bản chứa đầu ra của bất kỳ loại nào.

Dưới đây là một số ví dụ để giúp bạn hiểu rõ hơn.

Một hàm thực hiện phép cộng giữa hai số sẽ thực thi ngay lập tức.

Nó sẽ hoạt động và trả về kết quả ngay lập tức. Đây là một hàm đồng bộ.

Tuy nhiên, hãy xem xét việc mở một ứng dụng mạng xã hội như Instagram. Khi ứng dụng mở, nó sẽ tải dữ liệu, bạn có thể thấy một chỉ báo tải đang được hiển thị, cho biết các bài đăng trên Newsfeed đang được lấy. Khi dữ liệu đã được lấy, trang chính sẽ được điền vào với các bài đăng và câu chuyện. Đây là một ví dụ về một hàm bất đồng bộ.

Một số ví dụ khác là tìm kiếm Google, lấy dữ liệu từ cơ sở dữ liệu, tải lên tập tin từ thiết bị, và như vậy.

FutureBuilder Widget trong Flutter

Flutter có một widget gọi là FutureBuilder giúp hiển thị dữ liệu Future một cách dễ dàng.

Cú pháp của lớp FutureBuilder:

FutureBuilder<T>(
  key: key,
  future: future,
  initialData: initialData,
  builder: (BuildContext context, AsyncSnapshot<T> snapshot) {
    // Trả về widget dựa trên snapshot
  },
)

Các đối số quan trọng cần xem xét từ mã là:

  1. Future<T>? future: Đây là nơi bạn chỉ định hàm Future trả về một giá trị của kiểu T (int, String, bất cứ thứ gì).
  2. builder: Đây là nơi bạn xây dựng dữ liệu để hiển thị. Hai đối số Context và snapshot được truyền vào đây. Snapshot là một loại có sẵn trong Flutter thông qua đó bạn có thể xử lý dữ liệu.

Một hàm bất đồng bộ có thể không luôn trả về dữ liệu. Có khả năng nó có thể trả về một lỗi, mất nhiều thời gian để tải, và như vậy. Đây là nơi một snapshot giúp chúng ta.

Các Trạng thái trong FutureBuilder

Như đã thấy trước đó, một hàm bất đồng bộ cần thời gian để trả về dữ liệu, vì vậy cần chỉ ra cho người dùng biết liệu nó đang tải, đã được lấy hay có lỗi gì đó. Trong Flutter, có các trạng thái để biểu thị những điều này và được gọi là ConnectionStates. Các ConnectionStates khác nhau trong Flutter như sau:

  1. ConnectionState.waiting: Kết nối với tính toán bất đồng bộ và đang chờ đợi, tương tác hoặc nói cách khác. Dữ liệu đang được lấy và quá trình chưa hoàn thành.
  2. ConnectionState.done: Kết nối với tính toán bất đồng bộ đã được kết thúc hoặc nói cách khác là dữ liệu đã được lấy hoặc trả về một lỗi, nhưng kết nối đã đóng.
  3. ConnectionState.active: Kết nối với một tính toán bất đồng bộ đang hoạt động. Kết nối đã được thiết lập. Điều này lý tưởng cho streams.
  4. ConnectionState.none: Hiện không kết nối với bất kỳ tính toán bất đồng bộ nào, nghĩa là không có hàm Future hoặc stream nào có sẵn để kết nối.

Tạo ứng dụng để Thể hiện FutureBuilder trong Flutter

Để hiểu rõ hơn về tất cả các khái niệm, hãy tạo một ứng dụng Flutter với một hàm Future sẽ trả về thời gian hiện tại sau một đợi chờ hai giây. Đoạn mã bên dưới hiển thị mã khởi đầu cho cách FutureBuilder có thể được sử dụng cho tình huống này.

import 'package:flutter/material.dart';

class FutureBuilderExample extends StatefulWidget {
  const FutureBuilderExample({Key? key}) : super(key: key);

  @override
  State<FutureBuilderExample> createState() => _FutureBuilderExampleState();
}

class _FutureBuilderExampleState extends State<FutureBuilderExample> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Future Builder Example"),
      ),
      body: Container(),
    );
  }
}

Đoạn mã tiếp theo cho thấy cách tạo hàm Future.

Future<String> fetchTime() async {
  await Future.delayed(const Duration(seconds: 2));

  var date = DateTime.now();

  return "${date.hour}:${date.minute.toString().padLeft(2, '0')}:${(date.second).toString().padLeft(2, '0')}";
}

Hàm fetchTime() được sử dụng trong đoạn mã trên sẽ trả về thời gian hiện tại theo cách bất đồng bộ.

  • Vì đây là một hàm bất đồng bộ, từ khóa async và Future<String> được sử dụng, trong đó String chỉ loại dữ liệu trả về.
  • Vì việc thực thi sẽ bị trì hoãn trong hai giây, phương thức Future.delayed được sử dụng.
    • Từ khóa await được sử dụng trước Future.delayed để thông báo cho hàm chờ cho đến khi thực thi hoàn tất. Do đó, hàm sẽ tiếp tục chỉ sau khi thực thi hoàn tất.
  • Tiếp theo, DateTime.now() được sử dụng để lấy ngày và giờ hiện tại và được gán cho biến date.
  • Cuối cùng, giá trị của date được định dạng một cách đẹp mắt để người dùng có thể hiểu được. Bạn có thể định dạng nó theo bất kỳ cách nào bạn muốn.

Tiếp theo là FutureBuilder:

Đoạn mã bên dưới cho thấy cách định nghĩa FutureBuilder trong widget Center

body: Center(
  child: FutureBuilder(
    future: fetchTime(),
    builder: (context, snapshot) {},
  ),
),

Trong mã, fetchTime() trả về một String và chỉ định điều đó trong widget như FutureBuilder<String>.

Xem xét nhiều kịch bản khi xử lý dữ liệu bất đồng bộ. Đoạn mã bên dưới demonstrates kịch bản xử lý dữ liệu bất đồng bộ và Connect ionStates bên trong widget FutureBuilder.

body: Center(
  child: FutureBuilder<String>(
    future: fetchTime(),
    builder: (context, snapshot) {
      if (snapshot.connectionState == ConnectionState.waiting) {
        return CircularProgressIndicator();
      }
      if (snapshot.hasError) {
        return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text(
              'Error',
              style: TextStyle(fontWeight: FontWeight.w500, fontSize: 16),
            ),
            Text(
              snapshot.error.toString(),
              style: const TextStyle(
                color: Colors.red,
                fontWeight: FontWeight.w600,
                fontSize: 20,
              ),
            ),
          ],
        );
      }
      if (snapshot.hasData) {
        return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text(
              'Time Now',
              style: TextStyle(fontWeight: FontWeight.w500, fontSize: 16),
            ),
            Text(
              snapshot.data.toString(),
              style: const TextStyle(
                color: Colors.black,
                fontWeight: FontWeight.w600,
                fontSize: 20,
              ),
            ),
          ],
        );
      }
      return Text('state: ${snapshot.connectionState}');
    },
  ),
),

Trong đoạn mã trên, bên trong phương thức builder của widget FutureBuilder,
connectionState được xác minh trước bằng snapshot.connectionState ConnectionState.waiting để kiểm tra xem phương thức fetchTime() đã trả về kết quả hay vẫn đang tải. Nếu nó vẫn đang tải, thì một widget CircularProgressIndicator() có thể được trả về để thông báo cho người dùng biết rằng dữ liệu đang được tải.

Tiếp theo, kiểm tra xem dữ liệu trả về có bất kỳ lỗi nào không bằng cách sử dụng snapshot.hasError. Nếu có lỗi, sau đó hiển thị lỗi bằng cách sử dụng widget Text.

Nếu dữ liệu đã được tải và không có lỗi nào xảy ra, thì dữ liệu hiện có được xác minh bằng cách sử dụng snapshot.hasData. Dữ liệu, là một chuỗi trong trường hợp này, có thể được lấy bằng cách sử dụng snapshot.data và được hiển thị bên trong một widget Text.

Theo mặc định, FutureBuilder phải trả về một cái gì đó. Vì vậy, hãy sử dụng một số widget để điền vào không gian đó ngay cả khi tất cả các điều kiện có thể xảy ra đã được xử lý. Ở đây, một widget Text được sử dụng để trả về connectionState.

Hình bên dưới mô tả kết quả đầu ra.

StreamBuilder trong Flutter

Các luồng (streams) tương tự như Future. Các luồng cũng là dữ liệu bất đồng bộ, nhưng dưới dạng một chuỗi các sự kiện. Một Future sẽ kết thúc sau khi tạo ra kết quả. Trong khi đó, một luồng là một kết nối đã được thiết lập và dữ liệu sẽ được nhận khi luồng đang hoạt động.

Một ví dụ tốt là một ứng dụng trò chuyện nơi cả người gửi và người nhận sẽ nhận dữ liệu miễn là các thành viên đang hoạt động. Một số ví dụ khác bao gồm video streaming, phát nhạc và vị trí trực tiếp.

Widget StreamBuilder trong Flutter

StreamBuilder trong Flutter giúp lấy và hiển thị các luồng dữ liệu. Tương tự như FutureBuilder, thay vì đối số future, có một đối số stream.

Cú pháp cho StreamBuilder được đưa ra như sau:

Hàm Generator

Một hàm Generator cho phép người dùng tạo ra một giá trị trong chuỗi. Đơn giản, người dùng có thể tạo ra một tập hợp các đối tượng có thể được truy cập theo thứ tự. Hai từ khóa chính được sử dụng trong hàm Generator là async* và yield.

  • asynce*: Luôn trả về một luồng và cung cấp một số cú pháp tiện lợi để phát ra một giá trị thông qua từ khóa yield.
  • yield: Thêm một giá trị vào luồng kết quả của hàm async* xung quanh. Nó giống như một hàm return nhưng không kết thúc hàm.

Để hiểu với một ví dụ, hãy xem xét đoạn mã bên dưới trong đó hàm fetchTimer() là một đối tượng Timer sẽ đếm từ 10 xuống 0 và kết thúc.

int i = 10;
Stream<String> fetchTimer() async* {
  while (i > 0) {
    await Future.delayed(Duration(seconds: 1));
    yield i.toString();
    i--;
  }
}
  • Mã mẫu 5 có một hàm fetchTimer() sẽ đếm từ 10 xuống 0 và kết thúc.
  • Một biến số nguyên được khởi tạo với giá trị 10 bên ngoài hàm fetchTimer().
  • fetchTimer() là một hàm luồng trả về một chuỗi các giá trị không đồng bộ. Do đó, các từ khóa async* và Stream<String> được sử dụng, trong đó String là kiểu trả về.
  • Bên trong hàm, sử dụng vòng lặp while để kiểm tra xem biến i có lớn hơn không hay không. Nó tiếp tục lặp cho đến khi điều kiện trở thành sai.
  • Bên trong vòng lặp, tạo một đợi hai giây bằng cách sử dụng phương thức Future.delayed và từ khóa async.
  • Sau đó, giảm giá trị của i đi một.
  • Cuối cùng, giá trị của i được trả về dưới dạng String bằng từ khóa yield.

Tạo Ứng Dụng để Thể Hiện StreamBuilder trong Flutter

Sử dụng hàm generic như một ví dụ ở đây.

Trong đó, tạo một ứng dụng hẹn giờ 10 giây, bắt đầu sau một giây và kết thúc sau 10 đếm giảm xuống 0. Sau đó, hiển thị một thông báo “Hết giờ”.

Đoạn mã cho thấy cách tạo một widget mới gọi là StreamBuilderExample. Bắt đầu bằng cách tạo StreamBuilder và bọc nó trong widget Center.

body: Center(
  child: StreamBuilder<String>(
    stream: fetchTimer(),
    builder: (context, snapshot) {
      // something
    },
  ),
),

Hàm fetchTimer() được khai báo là luồng. Sau đó, bắt đầu xây dựng UI.

builder: (context, snapshot) {
  if (snapshot.connectionState == ConnectionState.waiting) {
    return CircularProgressIndicator();
  }
  if (snapshot.hasError) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        const Text(
          'Lỗi',
          style: TextStyle(fontWeight: FontWeight.w500, fontSize: 16),
        ),
        Text(
          snapshot.error.toString(),
          style: const TextStyle(
            color: Colors.red,
            fontWeight: FontWeight.w600,
            fontSize: 20,
          ),
        ),
      ],
    );
  }
  if (snapshot.connectionState == ConnectionState.active) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        const Text(
          'Hết giờ trong:',
          style: TextStyle(fontWeight: FontWeight.w500, fontSize: 16),
        ),
        Text(
          snapshot.data.toString(),
          style: const TextStyle(
            color: Colors.black,
            fontWeight: FontWeight.w600,
            fontSize: 20,
          ),
        ),
      ],
    );
  }
  if (snapshot.connectionState == ConnectionState.done) {
    return Text(
      'Hết giờ! \n${snapshot.connectionState}',
      textAlign: TextAlign.center,
      style: const TextStyle(
        color: Colors.black,
        fontWeight: FontWeight.w500,
        fontSize: 20,
      ),
    );
  }
  return Container();
},

Khi thực thi mã, đầu tiên, kiểm tra xem dữ liệu có đang tải hay không. Sử dụng ConnectionState.waiting để kiểm tra dữ liệu đang tải, và sử dụng CircularProgressIndicator() để thông báo cho người dùng.

Tiếp theo, kiểm tra lỗi bằng cách sử dụng phương thức snapshot.hasError bên trong một điều kiện if. Nếu có bất kỳ lỗi nào, hiển thị lỗi trong Text widget. Sau đó, sử dụng các trạng thái kết nối khác và hiển thị dữ liệu theo từng trạng thái.

ConnectionState.active có nghĩa là kết nối đã được thiết lập và dữ liệu đang được gửi đến. Hiển thị thời gian trong một Text widget.

ConnectionState.done có nghĩa là kết nối đã đóng và không còn nhận dữ liệu nữa. Hiển thị thông báo “Hết giờ”. Tham khảo hình bên dưới để xem kết quả của ứng dụng Thời gian được tạo bằng StreamBuilder.

Sự khác biệt giữa FutureBuilder và StreamBuilder

FeatureFutureBuilderStreamBuilder
Sử dụngFutureBuilder được sử dụng cho một lần trả vềStreamBuilder được sử dụng để lấy dữ liệu nhiều lần. Ví dụ như lắng nghe sự thay đổi dữ liệu
Khi có dữ liệuKhi FutureBuilder lấy kết quả, nó kết thúc. Widget sẽ không cập nhật nếu dữ liệu thay đổi và kết nối sẽ kết thúcStreamBuilder sẽ tái tạo UI mỗi khi dữ liệu thay đổi cho đến khi kết nối còn hoạt động
Từ khóa chínhFuture, asyncStream, async*, yield
Ví dụ sử dụngYêu cầu HTTP, tải file từ thiết bị, chụp ảnh từ camera, lấy thông tin thiết bị như vị trí và pinVí dụ như vị trí thời gian thực, phát video/nhạc, lắng nghe WebSocket

Bài viết liên quan:

REST API trong Flutter
Khái niệm cơ bản về cơ sở dữ liệu với Sqllite và Cơ sở dữ liệu Firebase
Tạo kiểu và Tạo ứng dụng đáp ứng trong Flutter
Điều Hướng, Định Tuyến và Bộ Điều Khiển trong Flutter
Quản lý trạng thái và Chèn phụ thuộc trong Flutter
Quản lý trạng thái và Chèn phụ thuộc trong Flutter
Xây dựng ứng dụng Flutter bằng cách sử dụng các Multi Child Layout Widgets
Xây dựng Ứng dụng Flutter Sử dụng Single Child Layout Widgets
Xây dựng Ứng dụng Flutter Sử dụng Widget Độc lập Nền tảng
Xây dựng ứng dụng Flutter bằng nền tảng Widget cụ thể
Applications và Widgets trong Flutter
Giới thiệu về Flutter

THÊM BÌNH LUẬN Cancel reply

Dịch vụ thiết kế Wesbite

NỘI DUNG MỚI CẬP NHẬT

2. PHÂN TÍCH VÀ ĐẶC TẢ HỆ THỐNG

3. THIẾT KẾ HỆ THỐNG

1. TỔNG QUAN KIẾN THỨC THỰC HÀNH TRIỂN KHAI DỰ ÁN CÔNG NGHỆ THÔNG TIN

Hướng dẫn tự cài đặt n8n comunity trên CyberPanel, trỏ tên miền

Mẫu prompt tạo mô tả chi tiết bối cảnh

Giới thiệu

hocvietcode.com là website chia sẻ và cập nhật tin tức công nghệ, chia sẻ kiến thức, kỹ năng. Chúng tôi rất cảm ơn và mong muốn nhận được nhiều phản hồi để có thể phục vụ quý bạn đọc tốt hơn !

Liên hệ quảng cáo: [email protected]

Kết nối với HỌC VIẾT CODE

© hocvietcode.com - Tech888 Co .Ltd since 2019

Đăng nhập

Trở thành một phần của cộng đồng của chúng tôi!
Registration complete. Please check your email.
Đăng nhập bằng google
Đăng kýBạn quên mật khẩu?

Create an account

Welcome! Register for an account
The user name or email address is not correct.
Registration confirmation will be emailed to you.
Log in Lost your password?

Reset password

Recover your password
Password reset email has been sent.
The email could not be sent. Possible reason: your host may have disabled the mail function.
A password will be e-mailed to you.
Log in Register
×