如何将 setState 转换为 BLoC?

How to convert setState to BLoC?

在我的应用程序中,我使用底部海军栏在屏幕底部显示带有屏幕的选项卡。要在选项卡之间切换,我使用 setState。现在我需要重做块中的所有 setState。我无法理解如何做到这一点。帮助解决这个问题。 下面附上我的屏幕代码。

void main() {
  BlocOverrides.runZoned(
    () {
      runApp(const MyApp());
    },
    blocObserver: MainBlocObserver(),
  );
}

class HomeScreen extends StatefulWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  int _currentIndex = 0;

  @override
  Widget build(BuildContext context) {
        ...
        child: PageView(
          controller: _pageController,
          onPageChanged: _onPageChanged,
          children: [
            SearchScreen(),
            EventListScreen(),
            Container(color: Colors.green),
            Container(color: Colors.blue),
          ],
        ),
      ),
      bottomNavigationBar: BottomNavyBar(
        containerHeight: 60,
        selectedIndex: _currentIndex,
        onItemSelected: _onItemSelected,
        items: [
         ...
        ],
      ),
    );
  }

  //change page
  void _onPageChanged(index) {
    setState(() => _currentIndex = index);
  }

  //select page item
  void _onItemSelected(index) {
    setState(() => _currentIndex = index);
    _pageController.jumpToPage(index);
  }
}

class MainBlocObserver extends BlocObserver {

}

事实上你可以在 Cubit 中完成,它与 Bloc 相同并且更简单一点,但我在 Bloc有事件,希望我的解释能帮到你:

首先,您将各自的文件创建到 Bloc,在我的例子中,我按以下方式调用它们:

底部海军集团:

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';

part 'bottom_navy_event.dart';
part 'bottom_navy_state.dart';

class BottomNavyBloc extends Bloc<BottomNavyEvent, BottomNavyState> {
  BottomNavyBloc() : super(const BottomNavyState()) {
    on<ChangePageEvent>(
      (event, emit) => emit(state.copyWith(index: event.index)),
    );
  }
}

这将是您的 Bloc 的主体,因此它只等待 ChangePageEvent 的调用,它将用于接收和发送主 index 并能够在 UI.

中更改它

底部海军事件:

part of 'bottom_navy_bloc.dart';

abstract class BottomNavyEvent extends Equatable {
  const BottomNavyEvent();

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

class ChangePageEvent extends BottomNavyEvent {
  final int index; // declaration

  const ChangePageEvent({
    required this.index, // we recive the index of the navigation
  });

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

这样你就可以创建 ChangePageEvent 事件 class,请注意我们还使用了 Equatable 包来为我们提供服务以更简单的方式比较状态。

底部海军州:

part of 'bottom_navy_bloc.dart';

class BottomNavyState extends Equatable {
  final int index;

  const BottomNavyState({
    this.index = 0,
  });

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

  BottomNavyState copyWith({
    int? index,
  }) {
    return BottomNavyState(
      index: index ?? this.index,
    );
  }
}

还有另一种形式可以调用你的状态,不过我发现它更有用和简单,因为当我们想要占用它们时,所有变量都在手边。

请注意,与 events 相比,state 将用于获取您发送的索引,换句话说, UI 是监听状态变化的那个(在本例中是索引),但是为了改变状态,有必要通过 event[=75= 发送一个值]

主要内容:

void main() {
  BlocOverrides.runZoned(
    () {
      runApp(const MyApp());
    },
    blocObserver: MainBlocObserver(),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => BottomNavyBloc(), // first you have to provide it and create it in your MaterialApp 
      child: MaterialApp(
        title: 'Booking',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: const HomeScreen(),
      ),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final PageController controller = PageController();

    return Scaffold(
      body: BlocListener<BottomNavyBloc, BottomNavyState>( // use it to listen if the state changes in this case the index
        listener: (context, state) {
          controller.jumpToPage(state.index);
        },
        child: PageView(
          controller: controller,
          onPageChanged: (int index) {
            BlocProvider.of<BottomNavyBloc>(context).add(ChangePageEvent(
              index: index,
            )); // calling the event and sending the current index
          },
          children: [
            Container(color: Colors.green),
            Container(color: Colors.blue),
            Container(color: Colors.red),
            Container(color: Colors.yellow),
          ],
        ),
      ),
      bottomNavigationBar: BlocBuilder<BottomNavyBloc, BottomNavyState>( // Builder is for change or re-build the UI, Listener listens only the things "intern" or for not re-building
        builder: (context, state) {
          return BottomNavyBar(
            containerHeight: 60,
            selectedIndex: state.index, // getting the current index from the state
            onItemSelected: (int index) {
              BlocProvider.of<BottomNavyBloc>(context).add(ChangePageEvent(
                index: index,
              )); // calling again the event
            },
            items: [
              BottomNavyBarItem(
                icon: const Icon(Icons.apps),
                title: const Text('Home'),
                activeColor: Colors.red,
              ),
              BottomNavyBarItem(
                  icon: const Icon(Icons.people),
                  title: const Text('Users'),
                  activeColor: Colors.purpleAccent),
              BottomNavyBarItem(
                  icon: const Icon(Icons.message),
                  title: const Text('Messages'),
                  activeColor: Colors.pink),
              BottomNavyBarItem(
                  icon: const Icon(Icons.settings),
                  title: const Text('Settings'),
                  activeColor: Colors.blue),
            ],
          );
        },
      ),
    );
  }
}

class MainBlocObserver extends BlocObserver {}

------------------------肘

和Bloc一样,只是更简单,因为你不调用任何事件,如果你是这种小逻辑,我建议使用Cubit,我留给你。

下海军腕尺:

import 'package:bloc/bloc.dart';

part 'bottom_navy_state.dart';

class BottomNavyCubit extends Cubit<BottomNavyState> {
  BottomNavyCubit() : super(const BottomNavyState(index: 0));

  void changePage(int newIndex) => emit(BottomNavyState(index: newIndex)); // we don't use an event here, just a function
}

底部海军州:

part of 'bottom_navy_cubit.dart';

class BottomNavyState {
  final int index;

  const BottomNavyState({required this.index});
}

主要内容:

void main() {
  BlocOverrides.runZoned(
    () {
      runApp(const MyApp());
    },
    blocObserver: MainBlocObserver(),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => BottomNavyCubit(), // creation of the cubit
      child: MaterialApp(
        title: 'Booking',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: const HomeScreen(),
      ),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final PageController controller = PageController();

    final BottomNavyCubit cubit = BlocProvider.of<BottomNavyCubit>(context); // instance of the cubit to call the function

    return Scaffold(
      body: BlocListener<BottomNavyCubit, BottomNavyState>(
        listener: (context, state) {
          controller.jumpToPage(state.index); // listening the state changin
        },
        child: PageView(
          controller: controller,
          onPageChanged: (int index) {
            cubit.changePage(index); // calls the function
          },
          children: [
            Container(color: Colors.green),
            Container(color: Colors.blue),
            Container(color: Colors.red),
            Container(color: Colors.yellow),
          ],
        ),
      ),
      bottomNavigationBar: BlocBuilder<BottomNavyCubit, BottomNavyState>(
        builder: (context, state) {
          return BottomNavyBar(
            containerHeight: 60,
            selectedIndex: state.index, // getting the state
            onItemSelected: (int index) {
              cubit.changePage(index); // calling the function
            },
            items: [
              BottomNavyBarItem(
                icon: const Icon(Icons.apps),
                title: const Text('Home'),
                activeColor: Colors.red,
              ),
              BottomNavyBarItem(
                  icon: const Icon(Icons.people),
                  title: const Text('Users'),
                  activeColor: Colors.purpleAccent),
              BottomNavyBarItem(
                  icon: const Icon(Icons.message),
                  title: const Text('Messages'),
                  activeColor: Colors.pink),
              BottomNavyBarItem(
                  icon: const Icon(Icons.settings),
                  title: const Text('Settings'),
                  activeColor: Colors.blue),
            ],
          );
        },
      ),
    );
  }
}