Cấu trúc tổ chức project Flutter sử dụng Bloc

BLoC (Business Logic Component) là một mô hình lập trình được sử dụng để quản lý logic xử lý dữ liệu trong Flutter. Nó là một phần của các mô hình lập trình như MVC (Model-View-Controller) hoặc MVVM (Model-View-ViewModel).
BLoC cung cấp một cách để tách logic xử lý dữ liệu từ giao diện người dùng, giúp cho mã trở nên dễ quản lý và bảo trì hơn. Nó làm việc theo cơ chế event/state, với các event được gửi đến BLoC để xử lý, và các state được cập nhật sau đó được chuyển đến giao diện người dùng.
Trong Flutter, BLoC có thể được sử dụng với các thư viện hỗ trợ như flutter_bloc hoặc bloc. Bạn có thể tạo các BLoC để quản lý logic cho các màn hình, hoặc cho các widget con của màn hình. Bạn cũng có thể sử dụng nó để quản lý dữ liệu trên toàn bộ ứng dụng.

Dưới đây là cấu trúc folder tham khảo trong project sử dụng bloc:

- lib
  - models (for data models)
  - widgets (for UI widgets)
  - blocs (for BLoCs)
    - bloc_file.dart (for individual BLoC)
  - services (for business logic and communication with APIs, databases, etc)
  - screens (for full-screen UI)
  - main.dart (for starting the app)

Trong bài này mình lấy ví dụ về hiển thị thông tin user:

Cấu trúc folder:

lib
  - models
    - user.dart
  - widgets
    - user_card.dart
  - blocs
    - user_bloc.dart
  - services
    - user_service.dart
  - screens
    - user_screen.dart
  - main.dart

Model user:

// models/user.dart
class User {
  final String name;
  final String email;
  User({this.name, this.email});
}

Widget UserCard hiển thị thông tin name và email:

// widgets/user_card.dart
import 'package:flutter/material.dart';
import '../models/user.dart';

class UserCard extends StatelessWidget {
  final User user;

  UserCard({Key key, this.user}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          children: [
            Text(user.name),
            Text(user.email),
          ],
        ),
      ),
    );
  }
}

Bloc User quản lý state:

// blocs/user_bloc.dart
import 'dart:async';
import 'package:bloc/bloc.dart';
import '../models/user.dart';
import '../services/user_service.dart';

enum UserEvent { fetch }

class UserBloc extends Bloc<UserEvent, User> {
  final UserService _userService;

  UserBloc({UserService userService})
      : assert(userService != null),
        _userService = userService;

  @override
  User get initialState => User();

  @override
  Stream<User> mapEventToState(UserEvent event) async* {
    switch (event) {
      case UserEvent.fetch:
        yield* _mapFetchToState();
        break;
    }
  }

  Stream<User> _mapFetchToState() async* {
    try {
      final user = await _userService.fetchUser();
      yield user;
    } catch (_) {
      yield User();
    }
  }
}

Service kết nối đến API hoặc DB lấy thông tin user:

// services/user_service.dart
import '../models/user.dart';

class UserService {
  Future<User> fetchUser() async {
    // implementation to fetch user data from API, database, etc.
    return User(name: "John Doe", email: "johndoe@example.com");
  }
}

Screen hiển thị thông tin:

// screens/user_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../blocs/user_bloc.dart';
import '../widgets/user_card.dart';

class UserScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("User")),
      body: BlocBuilder<UserBloc, User>(
        builder: (context, state) {
          if (state.name == null) {
            return Center(child: CircularProgressIndicator());
          }
          return UserCard(user: state);
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          BlocProvider.of<UserBloc>(context).add(UserEvent.fetch);
        },
        child: Icon(Icons.refresh),
      ),
    );
  }
}

// main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import './blocs/user_bloc.dart';
import './services/user_service.dart';
import './screens/user_screen.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter BLoC Example',
      home: BlocProvider<UserBloc>(
        create: (context) => UserBloc(userService: UserService()),
        child: UserScreen(),
      ),
    );
  }
}
Leave a Comment