如何在Flutter Bloc中访问变量,而无需将它们作为参数传递给每个状态?

huangapple go评论106阅读模式
英文:

How can I access variables in Flutter Bloc without passing them as params to every single state?

问题

So I have a Flutter app with Bloc for state management. I want to keep a list of users in Bloc so I can access it from different places in the app. But as it is now I pass this list of users to every state. Can I somehow avoid this boilerplate code?

Here is an example of my Bloc State:

abstract class UsersState {
  final List<User> users;
  final User? user;

  const UsersState({required this.users, required this.user});
}

class UsersInitial extends UsersState {
  UsersInitial() : super(users: [], user: null);
}

class UsersLoadedState extends UsersState {
  const UsersLoadedState({required List<User> users, required User? user})
      : super(users: users, user: user);
}

class UsersPendingState extends UsersState {
  const UsersPendingState({List<User> users = const [], User? user})
      : super(users: users, user: user);
}

class UsersErrorState extends UsersState {
  final String message;
  const UsersErrorState(
      {required List<User> users, required User? user, required this.message})
      : super(users: users, user: user);
}

class FriendAddedState extends UsersState {
  const FriendAddedState({required List<User> users, required User? user})
      : super(users: users, user: user);
}

In this example I don't want to have to pass the list of users to FriendAddedState. And here is how it looks in Bloc:

        emit(FriendAddPending(users: users, user: user));
        final result = await usecases.addFriend(event.friendId);
        result.fold((error) {
          emit(UsersErrorState(
              users: users, user: user, message: error.message));
        }, (success) {
          user = success;
          emit(FriendAddedState(users: users, user: user));
        });
      } 
英文:

So I have a Flutter app with Bloc for state mangement. I want to keep a list of users in Bloc so I can access it from different places in the app. But as it is now I pass this list of users to every state. Can I somehow avoid this boilerplate code?

Here is an example of my Bloc State:

@immutable
abstract class UsersState {
  final List&lt;User&gt; users;
  final User? user;

  const UsersState({required this.users, required this.user});
}

class UsersInitial extends UsersState {
  UsersInitial() : super(users: [], user: null);
}

class UsersLoadedState extends UsersState {
  const UsersLoadedState({required List&lt;User&gt; users, required User? user})
      : super(users: users, user: user);
}

class UsersPendingState extends UsersState {
  const UsersPendingState({List&lt;User&gt; users = const [], User? user})
      : super(users: users, user: user);
}


class UsersErrorState extends UsersState {
  final String message;
  const UsersErrorState(
      {required List&lt;User&gt; users, required User? user, required this.message})
      : super(users: users, user: user);
}

class FriendAddedState extends UsersState {
  const FriendAddedState({required List&lt;User&gt; users, required User? user})
      : super(users: users, user: user);
}

In this example I don't want to have to pass list of users to FriendAddedState.
And here is how it looks in Bloc:

 else if (event is AddFriend) {
        emit(FriendAddPending(users: users, user: user));
        final result = await usecases.addFriend(event.friendId);
        result.fold((error) {
          emit(UsersErrorState(
              users: users, user: user, message: error.message));
        }, (success) {
          user = success;
          emit(FriendAddedState(users: users, user: user));
        });
      } 

答案1

得分: 0

你不必在UserState中定义usersuser,如果你不需要它们出现在所有的 bloc 状态中。你可以在UsersLoadedStateFriendAddedState中定义它们,就像这样:

@immutable
abstract class UsersState {
  const UsersState();
}

class UsersInitial extends UsersState {
  const UsersInitial();
}

class UsersLoadedState extends UsersState {
  const UsersLoadedState({
    required this.users,
    required this.user,
  });

  final List<User> users;
  final User? user;
}

class UsersPendingState extends UsersState {
  const UsersPendingState();
}

class UsersErrorState extends UsersState {
  final String message;

  const UsersErrorState({required this.message});
}

class FriendAddedState extends UsersState {
  const FriendAddedState({
    required this.users,
    required this.user,
  });

  final List<User> users;
  final User? user;
}

[建议] 如果你想在 bloc 的每个状态中访问用户,你可以使用一个单独的类来定义你的 bloc 状态,以及一个枚举来定义其状态:

@immutable
class UsersState {
  final List<User> users;
  final User? user;
  final String? message;
  final UserStatus status;

  const UsersState({
    required this.status,
    required this.users,
    this.user,
    this.message,
  });

  const UsersState.initial()
      : status = UserStatus.initial,
        users = const [],
        user = null,
        message = null;

  UsersState copyWith(
    List<User>? users,
    User? user,
    String? message,
    UserStatus? status,
  ) {
    return UsersState(
      status: status ?? this.status,
      users: users ?? this.users,
      message: message ?? this.message,
      user: user ?? this.user,
    );
  }
}

enum UserStatus {
  initial,
  loaded,
  pending,
  error,
  friendAdded,
}

然后在你的 bloc 类中,在任何你想要发出新状态的地方,使用state.copyWith()

英文:

You don't have to define users and user in UserState if you don't need them in all the bloc states. You could just define them in UsersLoadedState FriendAddedState like this:


@immutable
abstract class UsersState {
  const UsersState();
}

class UsersInitial extends UsersState {
  const UsersInitial();
}

class UsersLoadedState extends UsersState {
  const UsersLoadedState({
    required this.users,
    required this.user,
  });

  final List&lt;User&gt; users;
  final User? user;
}

class UsersPendingState extends UsersState {
  const UsersPendingState();
}

class UsersErrorState extends UsersState {
  final String message;

  const UsersErrorState({required this.message});
}

class FriendAddedState extends UsersState {
  const FriendAddedState({
    required this.users,
    required this.user,
  });

  final List&lt;User&gt; users;
  final User? user;
}

[Recommended] if you want to access user in every state of bloc, you can use a single class for your bloc state and an enum to define its state:

@immutable
class UsersState {
  final List&lt;User&gt; users;
  final User? user;
  final String? message;
  final UserStatus status;

  const UsersState({
    required this.status,
    required this.users,
    this.user,
    this.message,
  });

  const UsersState.initial()
      : status = UserStatus.initial,
        users = const [],
        user = null,
        message = null;

  UsersState copyWith(
    List&lt;User&gt;? users,
    User? user,
    String? message,
    UserStatus? status,
  ) {
    return UsersState(
      status: status ?? this.status,
      users: users ?? this.users,
      message: message ?? this.message,
      user: user ?? this.user,
    );
  }
}

enum UserStatus {
  initial,
  loaded,
  pending,
  error,
  friendAdded,
}

then in your bloc class, anywhere you wanted to emit new state, use state.copyWith()!

答案2

得分: -1

你可以使用:
context.read();
或者
BlocProvider.of(context);
希望这有所帮助。

英文:

You could use:
context.read&lt;YourBlocClass&gt;();<br>
or
BlocProvider.of&lt;YourBlocClass&gt;(context);<br>
Hope this helps.

答案3

得分: -1

你可以尝试使用两个不同的块,一个用于状态,一个用于用户列表。

另一种选择是只使用一个状态类,其中包含一个枚举表示所有可能的状态。这样在每次状态更改时就不需要重新初始化类。类似这样:

enum UserState { Initial, Loaded, Pending.. }

class UsersState {
  UserState? state;
  List<User> users;
  User? user;

  const UsersState({required this.users, required this.user});
}
英文:

You could try to use a two different blocs, one for the state, one for the list of users.

An alternative can be to have just one state class with an enum for all the possible states.
This way you don't reinitialize the class every state change. Something like:

enum UserState {Initial, Loaded, Pending..}

class UsersState {
  UserState? state;
  List&lt;User&gt; users;
  User? user;

  const UsersState({required this.users, required this.user});
}

答案4

得分: -1

以下是翻译好的部分:

Without null safety (没有空安全)

@immutable
abstract class UsersState {
  final List<User>? users;
  final User? user;

  const UsersState({required this.users, this.user});
}

class UsersInitial extends UsersState {
  UsersInitial() : super(users: [], user: null);
}

class UsersLoadedState extends UsersState {
  const UsersLoadedState({required List<User> users, required User? user})
      : super(users: users, user: user);
}

class UsersPendingState extends UsersState {
  const UsersPendingState({List<User> users = const [], User? user})
      : super(users: users, user: user);
}

class UsersErrorState extends UsersState {
  final String message;
  const UsersErrorState(
      {required List<User> users, required User? user, required this.message})
      : super(users: users, user: user);
}

class FriendAddedState extends UsersState {
  const FriendAddedState({required User? user})
      : super(user: user);
}

With null safety (带有空安全)

@immutable
abstract class UsersState {
  final List<User>? users;
  final User? user;

  const UsersState({required this.users, this.user = null});
}

class UsersInitial extends UsersState {
  UsersInitial() : super(users: [], user: null);
}

class UsersLoadedState extends UsersState {
  const UsersLoadedState({required List<User> users, required User? user})
      : super(users: users, user: user);
}

class UsersPendingState extends UsersState {
  const UsersPendingState({List<User> users = const [], User? user})
      : super(users: users, user: user);
}

class UsersErrorState extends UsersState {
  final String message;
  const UsersErrorState(
      {required List<User> users, required User? user, required this.message})
      : super(users: users, user: user);
}

class FriendAddedState extends UsersState {
  const FriendAddedState({required User? user})
      : super(user: user);
}
英文:

You can make users optional so that they are not required in every state.

Without null safety

@immutable
abstract class UsersState {
  final List&lt;User&gt;? users;
  final User? user;

  const UsersState({required this.users, this.user});
}

class UsersInitial extends UsersState {
  UsersInitial() : super(users: [], user: null);
}

class UsersLoadedState extends UsersState {
  const UsersLoadedState({required List&lt;User&gt; users, required User? user})
      : super(users: users, user: user);
}

class UsersPendingState extends UsersState {
  const UsersPendingState({List&lt;User&gt; users = const [], User? user})
      : super(users: users, user: user);
}


class UsersErrorState extends UsersState {
  final String message;
  const UsersErrorState(
      {required List&lt;User&gt; users, required User? user, required this.message})
      : super(users: users, user: user);
}

class FriendAddedState extends UsersState {
  const FriendAddedState({required User? user})
      : super(user: user);
}

With null safety

@immutable
abstract class UsersState {
  final List&lt;User&gt;? users;
  final User? user;

  const UsersState({required this.users, this.user=[]});
}

class UsersInitial extends UsersState {
  UsersInitial() : super(users: [], user: null);
}

class UsersLoadedState extends UsersState {
  const UsersLoadedState({required List&lt;User&gt; users, required User? user})
      : super(users: users, user: user);
}

class UsersPendingState extends UsersState {
  const UsersPendingState({List&lt;User&gt; users = const [], User? user})
      : super(users: users, user: user);
}


class UsersErrorState extends UsersState {
  final String message;
  const UsersErrorState(
      {required List&lt;User&gt; users, required User? user, required this.message})
      : super(users: users, user: user);
}

class FriendAddedState extends UsersState {
  const FriendAddedState({required User? user})
      : super(user: user);
}

huangapple
  • 本文由 发表于 2023年4月4日 15:34:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/75926656.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定