Flutter BLoC/Cubit STATE 类最佳实践

问题描述 投票:0回答:3

我刚开始使用 Bloc 和 Cubit,因此我正在尝试找出一些专门针对 State 组件的最佳实践。我有一个简单的待办事项应用程序,其中待办事项可以处于多种不同的状态:

part of 'todos_cubit.dart';

abstract class TodosState extends Equatable {
  const TodosState();

  @override
  List<Object> get props => [];
}

class TodosLoading extends TodosState {}

class TodosLoaded extends TodosState {
  final List<Todo> todos;

  TodosLoaded(this.todos);

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;

    return other is TodosLoaded && listEquals(other.todos, todos);
  }

  @override
  int get hashCode => todos.hashCode;
}

class TodosEmpty extends TodosState {}

class TodosError extends TodosState {
  final String error;

  TodosError(this.error);

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;

    return other is TodosError && other.error == error;
  }

  @override
  int get hashCode => error.hashCode;
}

我的问题是,我应该将

List<Todo> todos
保留在
TodosLoaded
子类中还是应该将其移动到基类中?我的想法是,通过将其移动到基类,它会使我的
TodosEmpty
状态变得多余,因为我可以简单地检查 UI 中的待办事项列表是否为空。如果是这样的话,我是否也应该将
String error
移至基类?

我确信每种方法都有优点和缺点,只是希望能向对 Bloc 有更多经验的人提出想法。

flutter dart bloc cubit
3个回答
3
投票

尝试使用Cubit,它大大简化了代码。

我可能会在 cubit 类中创建一个函数

addToDo(todoItem)
removeToDo(todoItem)
来更新列表并发出更改。列表变量将以肘为单位,您将使用
context.read<TodoCubit>().todoList
从小组件中引用此列表。

您将使用如下功能:

context.read<TodoCubit>().addToDo(todoItem)

我已经编写了 Cubit 实现最佳方法的教程 Flutter |使用 Cubit (Bloc) 进行 Firebase 身份验证 — 教程 1(共 2)

我认为这篇文章会对您有很大帮助。快来看看🤓


0
投票

对于检查此线程的人来说,在待办事项列表中显示

TodosEmpty
TodosLoaded
等状态是非常好的。尽管如此,我会使用 freezed 包并简化它,就像我在我的应用程序中所做的那样:

“books_list_cubit.dart”的一部分;

@freezed
class BooksListPageState with _$BooksListPageState {
  const factory BooksListPageState.loading() = BooksListPageLoading;

  const factory BooksListPageState.empty() = BooksListPageEmpty;

  const factory BooksListPageState.success(List<Book> books) = BooksListPageSuccess;
}

有关此内容的更多信息,请参阅我的 Flutter 肘部 + 钩子 + Hive DB 教程。


0
投票

准备您的项目,例如: 库/ ├── 肘/ │ ├── api_cubit.dart │ ├── api_state.dart ├── 经理/ │ └── api_manager.dart ├── 型号/ │ └── user_model.dart ├── 画面/ │ └── home_screen.dart └── main.dart user_model.dart

class User {
  final int id;
  final String name;
  final String email;

  User({required this.id, required this.name, required this.email});

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      id: json['id'],
      name: json['name'],
      email: json['email'],
    );
  }
}

api_manager.dart //创建一个类来处理API调用

导入'package:dio/dio.dart'; 导入'../models/user_model.dart';

类 ApiManager { 最终 Dio _dio = Dio();

未来 fetchUsers() 异步 { 尝试 { 最终响应=await_dio.get('https://jsonplaceholder.typicode.com/users'); return (response.data as List).map((user) => User.fromJson(user)).toList(); } 捕获 (e) { throw Exception('获取用户失败'); } } }

api_cubit.dart,定义Cubit来管理状态

    import 'package:flutter_bloc/flutter_bloc.dart';
    import '../manager/api_manager.dart';
    import '../models/user_model.dart';
    import 'api_state.dart';
    
    class ApiCubit extends Cubit<ApiState> {
      final ApiManager apiManager;
    
      ApiCubit({required this.apiManager}) : super(ApiInitial());
    
      Future<void> fetchUsers() async {
        emit(ApiLoading());
        try {
          final users = await apiManager.fetchUsers();
          emit(ApiLoaded(users: users));
        } catch (e) {
          emit(ApiError(message: e.toString()));
        }
      }
    }

api_state.dart, define the states for the Cubit

import '../models/user_model.dart';

abstract class ApiState {}

class ApiInitial extends ApiState {}

class ApiLoading extends ApiState {}

class ApiLoaded extends ApiState {
  final List<User> users;

  ApiLoaded({required this.users});
}

class ApiError extends ApiState {
  final String message;

  ApiError({required this.message});
}

构建 UI 以显示获取的数据

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../cubit/api_cubit.dart';
import '../cubit/api_state.dart';
import '../manager/api_manager.dart';

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => ApiCubit(apiManager: ApiManager())..fetchUsers(),
      child: Scaffold(
        appBar: AppBar(title: Text('Users')),
        body: BlocBuilder<ApiCubit, ApiState>(
          builder: (context, state) {
            if (state is ApiLoading) {
              return Center(child: CircularProgressIndicator());
            } else if (state is ApiLoaded) {
              return ListView.builder(
                itemCount: state.users.length,
                itemBuilder: (context, index) {
                  final user = state.users[index];
                  return ListTile(
                    title: Text(user.name),
                    subtitle: Text(user.email),
                  );
                },
              );
            } else if (state is ApiError) {
              return Center(child: Text(state.message));
            }
            return Center(child: Text('Press the button to fetch users.'));
          },
        ),
      ),
    );
  }
}

您可以将获取的数据存储在本地(例如,使用像shared_preferences这样的包)并在进行新的API调用之前从缓存加载它。

© www.soinside.com 2019 - 2024. All rights reserved.