Skip to content

Bloc1

Using the BLoC pattern

使用 BLoC 模式時,一切都是Event Strean。BLoC(代表業務 Logic 元件)是任何數據源和將使用數據的使用者介面之間的一層。
BLoC 從源接收數據流,根據業務邏輯的要求對其進行處理,並將數據流返回給其訂閱者。
Alt text
使用 BLoC 的主要原因是將應用的業務邏輯與小組件的呈現方式分開,當應用變得更加複雜並需要在多個不同位置共享狀態時,它特別有用。

Code

//main.dart
import 'package:flutter/material.dart';
import 'countdown_bloc.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'BLoC',
      theme: ThemeData(
        primarySwatch: Colors.deepPurple,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: StreamHomePage(),
    );
  }
}

class StreamHomePage extends StatefulWidget {
  @override
  _StreamHomePageState createState() => _StreamHomePageState();
}

class _StreamHomePageState extends State<StreamHomePage> {
  TimerBLoC? timerBloc;
  int? seconds;
  @override
  void initState() {
    timerBloc = TimerBLoC();
    seconds = timerBloc?.seconds;
    timerBloc?.countDown();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('BLoC'),
      ),
      body: Container(
          child: StreamBuilder(
        stream: timerBloc!.secondsStream,
        initialData: seconds,
        builder: (context, snapshot) {
          if (snapshot.hasError) {
            print('Error');
          }
          if (snapshot.hasData) {
            return Center(
                child: Text(
              snapshot.data.toString(),
              style: TextStyle(fontSize: 30),
            ));
          } else {
            return Center();
          }
        },
      )),
    );
  }
}

程式碼解釋

這段程式碼是用 Dart 語言和 Flutter 框架寫的,主要是建立一個 Flutter 應用程式,並使用 BLoC (Business Logic Component) 架構來管理應用程式的狀態。

首先,程式碼從 main() 函數開始執行,這是 Dart 程式的入口點。在 main() 函數中,我們呼叫 runApp() 函數並傳入 MyApp 物件,這是啟動 Flutter 應用程式的標準方式。

MyApp 是一個繼承自 StatelessWidget 的類別,這表示它是一個不會改變狀態的 widget。在 build() 方法中,我們返回一個 MaterialApp widget,並設定了應用程式的主題和首頁。

首頁是 StreamHomePage,這是一個繼承自 StatefulWidget 的類別,表示它的狀態可能會改變。當 Flutter 需要建立 StreamHomePage widget 時,會呼叫其 createState() 方法,該方法返回一個 _StreamHomePageState 物件。

_StreamHomePageStateStreamHomePage 的狀態類別。在這個類別中,我們在 initState() 方法中初始化了一個 TimerBLoC 物件和一個 seconds 變數,並開始倒數計時。然後在 build() 方法中,我們使用 StreamBuilder widget 來建立 UI,並根據 timerBlocsecondsStream 來更新 UI。

StreamBuilder widget 會監聽給定的 stream,並根據 stream 的最新事件來重建自己。在這個例子中,每當 secondsStream 發送新的事件(即秒數改變)時,StreamBuilder 就會重建,並更新顯示的秒數。


//countdown.dart
import 'dart:async';

class TimerBLoC {
  int seconds = 60;
  StreamController _secondsStreamController = StreamController();
  Stream get secondsStream =>
      _secondsStreamController.stream.asBroadcastStream();
  StreamSink get secondsSink => _secondsStreamController.sink;

  Future decreaseSeconds() async {
    await Future.delayed(const Duration(seconds: 1));
    seconds--;
    secondsSink.add(seconds);
  }

  countDown() async {
    for (var i = seconds; i > 0; i--) {
      await decreaseSeconds();
      returnSeconds(seconds);
    }
  }

  int returnSeconds(seconds) {
    return seconds;
  }

  void dispose() {
    _secondsStreamController.close();
  }
}

程式碼解釋

這段程式碼定義了一個名為 TimerBLoC 的類別,該類別用於實現倒數計時的業務邏輯。在這個類別中,我們使用了 Dart 的 StreamController 來創建一個可以發送和接收數據的 stream。

首先,我們定義了一個名為 seconds 的變數,用於存儲倒數計時的秒數。然後,我們創建了一個 StreamController 物件 _secondsStreamController,並提供了兩個 getter 方法 secondsStreamsecondsSink,分別用於獲取該 controller 的 stream 和 sink。

decreaseSeconds() 方法中,我們使用 Future.delayed() 函數來實現延遲一秒的功能,然後將 seconds 減一,並將新的秒數添加到 secondsSink 中,這將觸發 secondsStream 的事件。

countDown() 方法是一個異步方法,它使用一個 for 迴圈來逐秒減少 seconds 的值,並在每次迴圈中呼叫 decreaseSeconds() 方法。這個方法將會持續執行,直到 seconds 的值為零。

returnSeconds() 方法是一個簡單的 getter 方法,返回當前的 seconds 值。

最後,我們提供了一個 dispose() 方法,用於在不再需要 TimerBLoC 物件時關閉 _secondsStreamController,以釋放資源。


創建一個用作 BLoC 的類別。
在這個類別中聲明需要在應用程式中更新的資料。

  1. 設定 StreamControllers。
  2. 創建用於 streams 和 sinks 的 getter 方法。
  3. 添加 BLoC 的邏輯。
  4. 在構造函數中設定資料。
  5. 監聽變化。
  6. 設置一個處理方法。
  7. 從UI中,創建一個 BLoC 的實例。
  8. 使用 StreamBuilder 來建立將使用 BLoC 資料的小部件。
  9. 如果需要,將事件添加到 sink 中以通知資料的任何變化。

Last update : 13 novembre 2024
Created : 13 novembre 2024

Comments

Comments