当前位置:网站首页>Use bloc to build a page instance of shutter
Use bloc to build a page instance of shutter
2022-07-03 12:23:00 【Ma Nong @ official account on the island with the same name】
Preface
We talked about... In our last article BlocProvider Use , Sense and Provider It's almost the same , Nothing new . In the last article, there was a BlocBuilder It's a little strange , Let's review the code :
BlocBuilder<CounterCubit, int>(
builder: (context, count) => Text(
'$count',
style: TextStyle(
fontSize: 32,
color: Colors.blue,
),
),
Inside count Will automatically follow BlocProvider The state of the object changes , But we don't see the binding action , For example, we use Provider It's using context.watch Method , But there is no . What's the matter with this ? In this article, we will introduce BlocBuilder Use .
BlocBuilder Binding to state objects
flutter_bloc In the source BlocBuilder Is defined as follows :
class BlocBuilder<B extends BlocBase<S>, S> extends BlocBuilderBase<B, S> {
const BlocBuilder({
Key? key,
required this.builder,
B? bloc,
BlocBuilderCondition<S>? buildWhen,
}) : super(key: key, bloc: bloc, buildWhen: buildWhen);
final BlocWidgetBuilder<S> builder;
@override
Widget build(BuildContext context, S state) => builder(context, state);
}
There are two ways to bind state objects , Not specified in bloc Parameter time , It will pass. BlocProvider and context Automatically look up for matching status objects . This code is in its parent class BlocBuilderBase( It's a StatefulWidget) Of State Object , In fact, it's still context.read To complete .
@override
void initState() {
super.initState();
_bloc = widget.bloc ?? context.read<B>();
_state = _bloc.state;
}
And if you specify bloc Parameters , Then use the specified bloc object , In this way, you can use your own bloc Object without BlocProvider Provide . This usage is a bit like GetX Of GetBuilder 了 . For example, our counter application , It can be simplified to the following form .
class BlocBuilderDemoPage extends StatelessWidget {
final counterCubit = CounterCubit();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Bloc Counter '),
),
body: Center(
child: BlocBuilder<CounterCubit, int>(
builder: (context, count) => Text(
'$count',
style: TextStyle(
fontSize: 32,
color: Colors.blue,
),
),
bloc: counterCubit,
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
counterCubit.increment();
},
tooltip: ' Click to increase ',
child: Icon(Icons.add),
),
);
}
}
Refresh by conditions
BlocBuilder One more parameter buildWhen, This is a return bool Callback method of value :
typedef BlocBuilderCondition<S> = bool Function(S previous, S current);
That is, we can decide whether to refresh the interface according to the front and back States . for instance , For example, the data before and after refresh is consistent , Then there's no need to refresh the interface . Let's verify it with the imitation Nuggets personal home page written before . In order to complete the network request service , We constructed four states :
enum LoadingStatus {
loading, // load
success, // Loading successful
failed, // Loading failed
}
And then use Bloc Of event Pattern , Definition 3 individual Event.
abstract class PersonalEvent {}
// Get data events
class FetchEvent extends PersonalEvent {}
// Success Events
class FetchSucessEvent extends PersonalEvent {}
// Failure events
class FetchFailedEvent extends PersonalEvent {}
At the same time, a response state data class is defined , Aggregating personal information objects and loading states .
class PersonalResponse {
PersonalEntity? personalProfile;
LoadingStatus status = LoadingStatus.loading;
PersonalResponse({this.personalProfile, required this.status});
}
PersonalBloc The code implementation is as follows , Corresponding 3 The way we handle these events is as follows :
FetchEvent: Request network data ;FetchSucessEvent: After loading successfully , Build a new... With the requested personal information object and loading statusPersonalResponseobject , UseemitThe notification interface is refreshed ;FetchFailedEvent: Loading failed , emptyPersonalResponsePersonal information object , And mark the loading status as failed .
class PersonalBloc extends Bloc<PersonalEvent, PersonalResponse> {
final String userId;
PersonalEntity? _personalProfile;
PersonalBloc(PersonalResponse initial, {required this.userId})
: super(initial) {
on<FetchEvent>((event, emit) {
getPersonalProfile(userId);
});
on<FetchSucessEvent>((event, emit) {
emit(PersonalResponse(
personalProfile: _personalProfile,
status: LoadingStatus.success,
));
});
on<FetchFailedEvent>((event, emit) {
emit(PersonalResponse(
personalProfile: null,
status: LoadingStatus.failed,
));
});
on<RefreshEvent>((event, emit) {
getPersonalProfile(userId);
});
add(FetchEvent());
}
void getPersonalProfile(String userId) async {
_personalProfile = await JuejinService().getPersonalProfile(userId);
if (_personalProfile != null) {
add(FetchSucessEvent());
} else {
add(FetchFailedEvent());
}
}
}
In the constructor, we directly request data ( You can also let the interface control ). The implementation of the page is the same as before GetX Similar ( See :Flutter Introduction and actual combat ( 73 ): Then follow the personal homepage of nuggets GetX and Provider Between PK), It's just that we use BlocBuilder To complete . The code is as follows :
class PersonalHomePage extends StatelessWidget {
PersonalHomePage({Key? key}) : super(key: key);
final personalBloc = PersonalBloc(
PersonalResponse(
personalProfile: null,
status: LoadingStatus.loading,
),
userId: '70787819648695');
@override
Widget build(BuildContext context) {
return BlocBuilder<PersonalBloc, PersonalResponse>(
bloc: personalBloc,
builder: (_, personalResponse) {
print('build PersonalHomePage');
if (personalResponse.status == LoadingStatus.loading) {
return Center(
child: Text(' Loading ...'),
);
}
if (personalResponse.status == LoadingStatus.failed) {
return Center(
child: Text(' request was aborted '),
);
}
PersonalEntity personalProfile = personalResponse.personalProfile!;
return Stack(
children: [
CustomScrollView(
slivers: [
_getBannerWithAvatar(context, personalProfile),
_getPersonalProfile(personalProfile),
_getPersonalStatistic(personalProfile),
],
),
Positioned(
top: 40,
right: 10,
child: IconButton(
onPressed: () {
personalBloc.add(FetchEvent());
},
icon: Icon(
Icons.refresh,
color: Colors.white,
),
),
),
],
);
},
buildWhen: (previous, next) {
if (previous.personalProfile == null || next.personalProfile == null) {
return true;
}
return previous.personalProfile!.userId != next.personalProfile!.userId;
},
);
}
// Other codes are omitted
}
Here we add a refresh button , Each click will launch a FetchEvent To request new data , And in BlocBuilder Of builder Use in print Print interface refresh information . But we built a buildWhen Parameters , Only the current last two users id Refresh the interface only when it is inconsistent ( In fact, you can also compare objects , Overload required PersonalEntity Of == and hashCode Method ), To reduce unnecessary interface refresh . Then we comment out this line of code , Then go straight back true, That is, refresh every time . Let's look at the comparison of the two effects .

You can see , After judging the service conditions , Clicking the refresh button will not refresh the interface , This is because we use userId It's all the same . And if you comment it out, you will directly return true after , Every time you click the refresh button, it will refresh . In this way , We can reduce unnecessary interface refresh when the user refreshes but the data does not change . Please download the complete source code here :BLoC State management source code .
summary
As can be seen from this article ,BlocBuilder The use of is quite simple , and Bloc Of event The model is actually in harmony with Redux The pattern of ( You can refer to :Flutter Introduction and actual combat ( fifty-nine ): Hand in hand with you Redux The middleware implements asynchronous state management ) It's quite similar , Are triggered by user behavior , And then respond to the event , Return a new data object in status management to trigger interface refresh . and BlocBuilder Both can cooperate BlocProvider Use... In the component tree Bloc object , You can also have your own Bloc object . While using buildWhen Callback function , You can decide whether to refresh the interface by comparing the status data before and after , So as to reduce unnecessary interface refresh . 
边栏推荐
- Vulnhub's Tomato (tomato)
- 2020-09_ Shell Programming Notes
- Use of QT OpenGL camera
- Pragma pack syntax and usage
- Optimize interface performance
- DNS multi-point deployment IP anycast+bgp actual combat analysis
- Self made pop-up input box, input text, and click to complete the event.
- Dart: self study system
- ArcGIS application (XXI) ArcMap method of deleting layer specified features
- Unicode查询的官方网站
猜你喜欢

Wrong arrangement (lottery, email)

Solution to the second weekly test of ACM intensive training of Hunan Institute of technology in 2022

CGroup introduction

Introduction to the implementation principle of rxjs observable filter operator

Symlink(): solution to protocol error in PHP artisan storage:link on win10
![[official MySQL document] deadlock](/img/2d/04e97d696f20c2524701888ea9cd10.png)
[official MySQL document] deadlock

为什么我的mysql容器启动不了呢

【mysql专项】读锁和写锁

Shardingsphere sub database and sub table < 3 >

Develop plug-ins for idea
随机推荐
Fundamentals of concurrent programming (III)
【mysql官方文档】死锁
PHP get the file list and folder list under the folder
New features of ES6
Adult adult adult
MCDF Experiment 1
实现验证码验证
Interview experience in summer camp of Central South University in 2022
Vulnhub's Nagini
Solutions to the failure of installing electron
Wechat applet development - page Jump transfer parameters
雲計算未來 — 雲原生
Is BigDecimal safe to calculate the amount? Look at these five pits~~
023 ([template] minimum spanning tree) (minimum spanning tree)
2.9 overview of databinding knowledge points
QT OpenGL rotate, pan, zoom
Vulnhub's Tomato (tomato)
Basic knowledge of OpenGL (sort it out according to your own understanding)
347. Top k high frequency elements
Systemverilog-- OOP--对象的拷贝