如何将 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),
],
);
},
),
);
}
}
在我的应用程序中,我使用底部海军栏在屏幕底部显示带有屏幕的选项卡。要在选项卡之间切换,我使用 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),
],
);
},
),
);
}
}