ลองแบบมั่วๆกับ flutter_bloc
Perm Chao
Posted on February 6, 2020
BLoC Pattern
ตัวอย่างการใช้งาน BLoC Pattern โดยใช้ Library ชื่อ flutter_bloc
โครงสร้างแอปโดยสมมุติ
-
App -> (context ของ App ถูกส่งไปที่ HomeScreen โดยที่มี BLoC ส่งไปด้วย)
- HomeScreen -> (context ของ App และ HomeScreen ถูกส่งไปที่ ContainerX โดยที่มี BLoC ส่งไปด้วย)
- ContainerX
ไฟล์ app.dart
void main() {
// ให้ userRepository เป็นจุดเริ่มต้นทุกอย่างใน App อาจจะเป็น Object ที่ใช้ในการเชื่อมต่อฐานข้อมูล หรือเรียก APIs ก็ได้
// ในกรณี Firestore ก็อาจจะเป็น Firestore.instance
final userRepository = ...;
runApp(
// ครอบ BLoC ชั้นแรกด้วย AuthenticationBloc
BlocProvider<AuthenticationBloc>(
create: (context) {
// สร้าง AuthenticationBloc() ขึ้นมาใหม่ตัวนึงส่งค่า userRepository เข้าไปเช็ค Business Logic และ ....
// ทำการส่ง Event ไปให้ BLoC เพื่อเริ่มการทำงานของ BLoC โดย BLoC ทำงานเป็น Stream มันจะทำงานเช็ค Event เรื่อยๆ เพื่อให้ได้ state กลับมาเรื่อยๆ
// และเราจะใช้ state นั้นในการกำหนดว่า App เราควรแสดงผลอะไร (Declarative style)
return AuthenticationBloc(userRepository: userRepository)
..add(AppStarted());
},
// context ที่ส่งไปใน App() จะถูกแนบไปด้วย AuthenticationBloc ทีอยู่ในสถานะ AppStarted()
child: App(userRepository: userRepository),
),
);
}
class App extends StatelessWidget {
final OdooClient userRepository;
App({Key key, @required this.userRepository}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: BlocBuilder<AuthenticationBloc, AuthenticationState>(
builder: (context, state) {
if (state is AuthenticationUninitialized) {
return SplashPage();
}
if (state is AuthenticationAuthenticated) {
return HomeScreen(userRepository: userRepository);
}
if (state is AuthenticationUnauthenticated) {
return LoginScreen(userRepository: userRepository);
}
if (state is AuthenticationLoading) {
return LoadingIndicator();
}
return SplashPage();
},
),
);
}
}
ไฟล์ HomeScreen.dart
class HomeScreen extends StatefulWidget {
final OdooClient _userRepository;
HomeScreen({
@required Key key,
@required userRepository,
}) : assert(userRepository != null),
_userRepository = userRepository,
super(key: key);
State<HomeScreen> createState() => _HomeScreen();
}
class _HomeScreen extends State<HomeScreen> {
OdooClient get _userRepository => widget._userRepository;
OdooUser get _odooUser => widget._userRepository.odooUser;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
// นอกจาก BlocProvider ที่ใช้ฝัง BLoC เข้าไปใน context แล้วเรายังใข้ MultiBlocProvider ในการฝัง BLoC หลายๆชนิด เข้าไปใน context ได้อีก
// ซึ่ง BLoC [FetchUserBloc, FetchWorkOrderBloc] จะเอาไว้ใช้ใน WorkOrderScreen() อีกที
return MultiBlocProvider(
providers: [
BlocProvider<FetchUserBloc>(
create: (BuildContext context) =>
FetchUserBloc(odooUser: _odooUser)..add(FetchUserStarted()),
),
BlocProvider<FetchWorkOrderBloc>(
create: (BuildContext context) =>
FetchWorkOrderBloc(odooClient: _userRepository)..add(FetchWorkOrderStarted()),
),
],
child: ContainerX()
);
}
}
ไฟล์ container_x.dart
class ContainerX extends StatefulWidget {
@override
State<ContainerX> createState() => _ContainerX();
}
class _ContainerX extends State<ContainerX> {
@override
Widget build(BuildContext context) {
// ประกาศวิตเจตเก็บไว้ชื่อ _Container
// วิตเจตนี้ใช้ BlocBuilder ในการสร้างวิตเจตอีกที
Widget _Container = BlocBuilder<FetchUserBloc, FetchDataState>(
// BlocBuilder นี้รับ BLoC ประเภท FetchUserBloc ที่อยู่ใน context วิตเจตต้นทาง
bloc: BlocProvider.of<FetchUserBloc>(context),
// ตัวสร้าง Widget โดยส่ง state มาให้
builder: (context, state) {
// อยู่ในขั้นตอนการเช็ก state ของ BLoC นี้เพื่อดูว่าควรจะ return วิตเจตไหนออกไปดี
if(state is FetchUserSuccess) {
return Container(
child: StreamBuilder(
stream: state.info(),
builder: (context, snapshot) {
if(snapshot.hasError) {
return Text('SnapShot Error');
} else if(snapshot.hasData) {
print(snapshot.data);
return Text(snapshot.data['name']);
} else {
return Text("Loading ... in Stream Builder");
}
},
)
);
} else if(state is FetchUserFailed) {
return Container(
child: Text('Failed')
);
} else {
return Container(
child: Text('Loading ...')
);
}
},
);
return _Container;
}
}
💖 💪 🙅 🚩
Perm Chao
Posted on February 6, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
githubcopilot AI Innovations at Microsoft Ignite 2024 What You Need to Know (Part 2)
November 29, 2024