Trong Flutter và Dart, streams là một khái niệm quan trọng để xử lý dữ liệu bất đồng bộ. Streams cho phép bạn làm việc với các sự kiện hoặc dữ liệu được phát sinh theo thời gian, giúp bạn quản lý và xử lý thông tin một cách hiệu quả. Bài viết này sẽ giải thích chi tiết về streams, cách hoạt động của chúng, và cách sử dụng chúng trong Flutter/Dart.

1. Định Nghĩa Stream

Stream là một chuỗi các sự kiện hoặc dữ liệu được phát sinh theo thời gian. Bạn có thể nghĩ về streams như một dòng nước: dữ liệu chảy vào từ một nguồn nào đó và bạn có thể nhận và xử lý dữ liệu đó khi nó đến.

a. Các loại Stream

Trong Dart, có hai loại streams chính:

  • Single-subscription Stream: Chỉ cho phép một listener (người nghe) lắng nghe. Khi một listener đăng ký nhận dữ liệu từ stream, không có listener nào khác có thể lắng nghe cùng một stream đó cho đến khi listener đầu tiên hủy đăng ký.
  • Broadcast Stream: Cho phép nhiều listener cùng lắng nghe dữ liệu từ một stream. Điều này hữu ích khi bạn muốn nhiều phần của ứng dụng có thể nhận được cùng một sự kiện hoặc dữ liệu.

2. Cách Hoạt Động của Stream

Streams trong Dart hoạt động theo cách mà bạn có thể nhận được dữ liệu theo thời gian thực. Dưới đây là các bước cơ bản trong quá trình hoạt động của streams:

  1. Tạo Stream: Bạn có thể tạo một stream từ một nguồn dữ liệu như timer, I/O, hoặc một sự kiện người dùng.
  2. Đăng ký Listener: Một listener đăng ký với stream để nhận dữ liệu.
  3. Nhận Dữ Liệu: Khi dữ liệu mới có sẵn, stream sẽ phát dữ liệu đến listener đã đăng ký.
  4. Hủy Đăng Ký: Khi không còn cần nhận dữ liệu nữa, listener có thể hủy đăng ký.

b. Ví dụ minh họa cách hoạt động của Stream

import 'dart:async';

void main() {
  // Tạo một StreamController
  final controller = StreamController<int>();

  // Đăng ký listener để nhận dữ liệu từ stream
  controller.stream.listen((data) {
    print('Received data: $data');
  });

  // Phát dữ liệu vào stream
  for (var i = 1; i <= 5; i++) {
    controller.add(i);
  }

  // Đóng stream khi không còn dữ liệu
  controller.close();
}

Trong ví dụ trên, một StreamController được tạo ra để quản lý dữ liệu. Listener sẽ nhận dữ liệu khi nó được phát vào stream.

3. Sử Dụng Stream Trong Flutter

Streams thường được sử dụng trong Flutter để xử lý các sự kiện, như nhận dữ liệu từ server hoặc từ cảm biến. Ví dụ, bạn có thể sử dụng streams để:

  • Nhận dữ liệu từ một API liên tục (như cập nhật thời tiết theo thời gian thực).
  • Xử lý các sự kiện từ người dùng (như cuộn trang, nhấp chuột, v.v.).
  • Giao tiếp giữa các widget trong ứng dụng.

a. Ví dụ sử dụng Stream trong Flutter

Dưới đây là một ví dụ về cách sử dụng streams để cập nhật UI trong Flutter.

import 'dart:async';
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: StreamBuilderExample(),
    );
  }
}

class StreamBuilderExample extends StatefulWidget {
  @override
  _StreamBuilderExampleState createState() => _StreamBuilderExampleState();
}

class _StreamBuilderExampleState extends State<StreamBuilderExample> {
  late StreamController<int> _controller;

  @override
  void initState() {
    super.initState();
    _controller = StreamController<int>();
    _startTimer();
  }

  void _startTimer() {
    Timer.periodic(Duration(seconds: 1), (timer) {
      _controller.add(timer.tick);
      if (timer.tick >= 10) {
        _controller.close();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('StreamBuilder Example'),
      ),
      body: Center(
        child: StreamBuilder<int>(
          stream: _controller.stream,
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.active) {
              return Text('Tick: ${snapshot.data}');
            } else {
              return Text('Stream closed');
            }
          },
        ),
      ),
    );
  }

  @override
  void dispose() {
    _controller.close();
    super.dispose();
  }
}

Trong ví dụ trên, StreamBuilder được sử dụng để xây dựng một widget dựa trên dữ liệu nhận được từ stream. Khi timer tick, giá trị được phát vào stream và UI sẽ tự động cập nhật với giá trị mới.

4. Kết Luận

Streams trong Flutter/Dart là một công cụ mạnh mẽ giúp bạn quản lý dữ liệu bất đồng bộ và các sự kiện phát sinh theo thời gian. Chúng cung cấp một cách tiếp cận linh hoạt và hiệu quả để xử lý thông tin trong ứng dụng. Qua bài viết này, bạn đã hiểu rõ về streams, cách hoạt động của chúng và cách sử dụng chúng trong Flutter. Với khả năng làm việc với streams, bạn có thể xây dựng các ứng dụng mạnh mẽ và có khả năng mở rộng hơn.