
(рдореВрд▓ рд▓реЗрдЦ рдЕрдВрдЧреНрд░реЗрдЬреА рдореЗрдВ рдорд╛рдзреНрдпрдо рдкрд░ рдкреНрд░рдХрд╛рд╢рд┐рдд)
рд╕реНрдкрдВрджрди рдПрдХ рдЖрдзреБрдирд┐рдХ рдЙрддреНрддрд░рджрд╛рдпреА рд░реВрдкрд░реЗрдЦрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рд╡рд┐рдЧреЗрдЯреНрд╕ рдФрд░ рдЙрдкрдХрд░рдгреЛрдВ рдХрд╛ рдПрдХ рдмрдбрд╝рд╛ рд╕реЗрдЯред рд▓реЗрдХрд┐рди, рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдкреНрд░рд▓реЗрдЦрди Android рдЖрд╡реЗрджрди рдХреА рд╕рд┐рдлрд╛рд░рд┐рд╢ рдХреА рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдЧрд╛рдЗрдб рдХреА рддрд░рд╣ рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣реИред
рдХреЛрдИ рдЖрджрд░реНрд╢, рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдирд╣реАрдВ рд╣реИ рдЬреЛ рдХрд┐рд╕реА рддрдХрдиреАрдХреА рдХрд╛рд░реНрдп рдХреА рдХрд┐рд╕реА рднреА рдмреЛрдзрдЧрдореНрдп рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЛ рдкреВрд░рд╛ рдХрд░ рд╕рдХреЗ, рд▓реЗрдХрд┐рди рдпрд╣ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░реЗрдВ рдХрд┐ рд╣рдо рдЬрд┐рди рдореЛрдмрд╛рдЗрд▓ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдкрд░ рдХрд╛рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдЙрдирдореЗрдВ рд╕реЗ рдЕрдзрд┐рдХрд╛рдВрд╢ рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд╣реИ:
- рдЕрдиреБрд░реЛрдз рдФрд░ рдбреЗрдЯрд╛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВред
- рдкрд░рд┐рд╡рд░реНрддрди рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рдХреА рддреИрдпрд╛рд░реАред
- рдбреЗрдЯрд╛рдмреЗрд╕ рдпрд╛ рдлрд╝рд╛рдЗрд▓ рд╕рд┐рд╕реНрдЯрдо рд╕реЗ рдбреЗрдЯрд╛ рд▓рд┐рдЦрдирд╛ рдФрд░ рдкрдврд╝рдирд╛ред
рдпрд╣ рд╕рдм рджреЗрдЦрддреЗ рд╣реБрдП, рдореИрдВрдиреЗ рдПрдХ рдбреЗрдореЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдпрд╛ рдЬреЛ рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХреЗ рд╡рд┐рднрд┐рдиреНрди рддрд░реАрдХреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рд╣реА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИред
рдкреНрд░рд╛рд░рдВрдн рдореЗрдВ, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдХреЗрдВрджреНрд░ рдореЗрдВ рд╕реНрдерд┐рдд "рд▓реЛрдб рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдбреЗрдЯрд╛" рдмрдЯрди рдХреЗ рд╕рд╛рде рдПрдХ рд╕реНрдХреНрд░реАрди рджрд┐рдЦрд╛рдИ рдЬрд╛рддреА рд╣реИред рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдбреЗрдЯрд╛ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рд░реВрдк рд╕реЗ рд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдмрдЯрди рдХреЛ рдПрдХ рд▓реЛрдбрд┐рдВрдЧ рд╕рдВрдХреЗрддрдХ рджреНрд╡рд╛рд░рд╛ рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЬрдм рдбреЗрдЯрд╛ рдбрд╛рдЙрдирд▓реЛрдб рдкреВрд░рд╛ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдбрд╛рдЙрдирд▓реЛрдб рд╕рдВрдХреЗрддрдХ рдХреЛ рдбреЗрдЯрд╛ рджреНрд╡рд╛рд░рд╛ рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рддреЛ рдЪрд▓рд┐рдП рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред

рдбреЗрдЯрд╛
рдХрд╛рд░реНрдп рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ Repository
рд╡рд░реНрдЧ рдмрдирд╛рдпрд╛, рдЬрд┐рд╕рдореЗрдВ getUser()
рд╡рд┐рдзрд┐ рд╢рд╛рдорд┐рд▓ рд╣реИред рдпрд╣ рд╡рд┐рдзрд┐ рдиреЗрдЯрд╡рд░реНрдХ рд╕реЗ рдбреЗрдЯрд╛ рдХреЗ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд▓реЛрдбрд┐рдВрдЧ рдХрд╛ рдЕрдиреБрдХрд░рдг рдХрд░рддреА рд╣реИ рдФрд░ Future<User>
рд▓реМрдЯрд╛рддреА рд╣реИред
рдпрджрд┐ рдЖрдк рдбрд╛рд░реНрдЯ рдореЗрдВ рдлреНрдпреВрдЪрд░реНрд╕ рдФрд░ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рдирд╣реАрдВ рд╣реИрдВ, рддреЛ рд╣рдо рдпрд╣рд╛рдВ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдлреНрдпреВрдЪрд░ рдХреНрд▓рд╛рд╕ рдХреЗ рдкреНрд░рд▓реЗрдЦрди рдХреЛ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред
class Repository { Future<User> getUser() async { await Future.delayed(Duration(seconds: 2)); return User(name: 'John', surname: 'Smith'); } }
class User { User({ @required this.name, @required this.surname, }); final String name; final String surname; }
рд╡реИрдиреАрд▓рд╛
рдЪрд▓реЛ рдПрдХ рдбреЗрд╡рд▓рдкрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЖрд╡реЗрджрди рдХреЛ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЕрдЧрд░ рд╡рд╣ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рд╡реЗрдмрд╕рд╛рдЗрдЯ рдкрд░ рдлрд╝реНрд▓рдЯрд░ рдкреНрд░рд▓реЗрдЦрди рдХреЛ рдкрдврд╝рддрд╛ рд╣реИред
Navigator
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ VanillaScreen
рд╕реНрдХреНрд░реАрди рдЦреЛрд▓реЗрдВ
Navigator.push( context, MaterialPageRoute( builder: (context) => VanillaScreen(_repository), ), );
рдЪреВрдВрдХрд┐ рдПрдХ рд╡рд┐рдЬреЗрдЯ рдХреА рд╕реНрдерд┐рддрд┐ рдЕрдкрдиреЗ рдЬреАрд╡рди рдЪрдХреНрд░ рдХреЗ рджреМрд░рд╛рди рдХрдИ рдмрд╛рд░ рдмрджрд▓ рд╕рдХрддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ StatefulWidget
рд╕реЗ рдЗрдирд╣реЗрд░рд┐рдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЕрдкрдиреЗ рд╕реНрдЯреЗрдЯрдлреБрд▓ рд╡рд┐рдЬреЗрдЯ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ State
рдХреНрд▓рд╛рд╕ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред _VanillaScreenState
рд╡рд░реНрдЧ рдореЗрдВ bool _isLoading
рдФрд░ User _user
рдлрд╝реАрд▓реНрдб рд╡рд┐рдЬреЗрдЯ рдХреА рд╕реНрдерд┐рддрд┐ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддреЗ рд╣реИрдВред build(BuildContext context)
рд╡рд┐рдзрд┐ рд╕реЗ рдкрд╣рд▓реЗ рджреЛрдиреЛрдВ рдлрд╝реАрд▓реНрдбреНрд╕ рдХреЛ рдкрд╣рд▓реА рдмрд╛рд░ рдкреНрд░рд╛рд░рдВрдн рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
class VanillaScreen extends StatefulWidget { VanillaScreen(this._repository); final Repository _repository; @override State<StatefulWidget> createState() => _VanillaScreenState(); } class _VanillaScreenState extends State<VanillaScreen> { bool _isLoading = false; User _user; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Vanilla'), ), body: SafeArea( child: _isLoading ? _buildLoading() : _buildBody(), ), ); } Widget _buildBody() { if (_user != null) { return _buildContent(); } else { return _buildInit(); } } Widget _buildInit() { return Center( child: RaisedButton( child: const Text('Load user data'), onPressed: () { setState(() { _isLoading = true; }); widget._repository.getUser().then((user) { setState(() { _user = user; _isLoading = false; }); }); }, ), ); } Widget _buildContent() { return Center( child: Text('Hello ${_user.name} ${_user.surname}'), ); } Widget _buildLoading() { return const Center( child: CircularProgressIndicator(), ); } }
рд╡рд┐рдЬреЗрдЯ рдХреА рд░рд╛рдЬреНрдп рд╡рд╕реНрддреБ рдмрдирдиреЗ рдХреЗ рдмрд╛рдж, UI build(BuildContext context)
рд▓рд┐рдП build(BuildContext context)
рд╡рд┐рдзрд┐ рдХреЛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рдпреВрдЖрдИ рдШреЛрд╖рдгрд╛ рдХреЛрдб рдореЗрдВ рд╕реНрдХреНрд░реАрди рдкрд░ рд╡рд┐рдЬреЗрдЯ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рднреА рдирд┐рд░реНрдгрдп рд╕рд╣реА рджрд┐рдЦрд╛рдП рдЬрд╛рдиреЗ рдЪрд╛рд╣рд┐рдПред
body: SafeArea( child: _isLoading ? _buildLoading() : _buildBody(), )
рдкреНрд░рдЧрддрд┐ рд╕рдВрдХреЗрддрдХ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ "рд▓реЛрдб рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╡рд┐рд╡рд░рдг" рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддрд╛ рд╣реИ, рддреЛ рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд░рддреЗ рд╣реИрдВред
setState(() { _isLoading = true; });
рдкреНрд░рд▓реЗрдЦрди рд╕реЗ (рдЕрдиреБрд╡рд╛рдж):
SetState () рд╡рд┐рдзрд┐ рдХреЗ рд▓рд┐рдП рдПрдХ рдХреЙрд▓ рдЙрд╕ рд░реВрдкрд░реЗрдЦрд╛ рдХреЛ рд╕реВрдЪрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреА рдЖрдВрддрд░рд┐рдХ рд╕реНрдерд┐рддрд┐ рдмрджрд▓ рдЧрдИ рд╣реИ, рдФрд░ рдЙрдкрдкреНрд░рдХрд╛рд░ рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдлреНрд░реЗрдорд╡рд░реНрдХ рдЗрд╕ рд░рд╛рдЬреНрдп рдСрдмреНрдЬреЗрдХреНрдЯ рдкрд░ рдмрд┐рд▓реНрдб рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред
рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ setState()
рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдлреНрд░реЗрдо build(BuildContext context)
рд╡рд┐рдзрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдХреЙрд▓ рдХрд░реЗрдЧрд╛, рдЬреЛ рдкреВрд░реЗ рд╡рд┐рдЬреЗрдЯ рдЯреНрд░реА рдХреЛ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдПрдЧрд╛ред рдЪреВрдВрдХрд┐ _buildBody()
рд╡рд┐рдзрд┐ рдХреЗ рдмрдЬрд╛рдп _isLoading
рдлрд╝реАрд▓реНрдб _isLoading
рдорд╛рди рдмрджрд▓ рдЧрдпрд╛ true
, рдЗрд╕рд▓рд┐рдП _buildLoading()
рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдФрд░ рд╕реНрдХреНрд░реАрди рдкрд░ рдПрдХ рдкреНрд░рдЧрддрд┐ рд╕рдВрдХреЗрддрдХ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рд╣реА рдмрд╛рдд рддрдм рд╣реЛрдЧреА рдЬрдм рд╣рдо getUser()
рд╕реЗ рдХреЙрд▓рдмреИрдХ рдкреНрд░рд╛рдкреНрдд getUser()
рдФрд░ рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░реЗрдВрдЧреЗ
setState()
_isLoading
рдФрд░ _user
рдлрд╝реАрд▓реНрдб рдореЗрдВ рдирдП рдорд╛рди рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред
widget._repository.getUser().then((user) { setState(() { _user = user; _isLoading = false; }); });
рдЖрдХрд░реНрд╖рдг рдЖрддреЗ рд╣реИрдВ
- рдХрдо рдкреНрд░рд╡реЗрд╢ рджрд╣рд▓реАрдЬред
- рдХрд┐рд╕реА рддреАрд╕рд░реЗ рдкрдХреНрд╖ рдХреЗ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВред
рд╡рд┐рдкрдХреНрд╖
- рдЬрдм рд╡рд┐рдЬреЗрдЯ рдХреА рд╕реНрдерд┐рддрд┐ рдмрджрд▓ рдЬрд╛рддреА рд╣реИ, рддреЛ рд╡рд┐рдЬреЗрдЯ рдЯреНрд░реА рдХреЛ рд╣рд░ рдмрд╛рд░ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
- рдПрдХрдорд╛рддреНрд░ рдЬрд┐рдореНрдореЗрджрд╛рд░реА рдХреЗ рд╕рд┐рджреНрдзрд╛рдВрдд рдХрд╛ рдЙрд▓реНрд▓рдВрдШрди рдХрд░рддрд╛ рд╣реИред рд╡рд┐рдЬреЗрдЯ рди рдХреЗрд╡рд▓ UI рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд▓реНрдХрд┐ рдбреЗрдЯрд╛, рд╡реНрдпрд╡рд╕рд╛рдп рддрд░реНрдХ рдФрд░ рд░рд╛рдЬреНрдп рдкреНрд░рдмрдВрдзрди рд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рднреА рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред
- рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХреЛ рдХреИрд╕реЗ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдП рдЗрд╕ рдкрд░ рдирд┐рд░реНрдгрдп рд╕реАрдзреЗ рдпреВрдЖрдИ рдХреЛрдб рдореЗрдВ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред рдпрджрд┐ рд░рд╛рдЬреНрдп рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдХреЛрдб рдХреА рдкрдардиреАрдпрддрд╛ рдмрд╣реБрдд рдХрдо рд╣реЛ рдЬрд╛рдПрдЧреАред
рд╕реНрдХреЛрдкреНрдб рдореЙрдбрд▓
рд╕реНрдХреЛрдкреНрдб рдореЙрдбрд▓ рдПрдХ рддреГрддреАрдп-рдкрдХреНрд╖ рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╣реИ ред рдпрд╣рд╛рдВ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдЗрд╕рдХрд╛ рд╡рд░реНрдгрди рдХреИрд╕реЗ рдХрд░рддреЗ рд╣реИрдВ:
рдЙрдкрдпреЛрдЧрд┐рддрд╛рдУрдВ рдХрд╛ рдПрдХ рд╕реЗрдЯ рдЬреЛ рдЖрдкрдХреЛ рдкреВрд░реНрд╡рдЬреЛрдВ рдХреЗ рд╡рд┐рдЬреЗрдЯ рдХреЗ рдбреЗрдЯрд╛ рдореЙрдбрд▓ рдХреЛ рдЙрд╕рдХреЗ рд╕рднреА рд╡рдВрд╢рдЬреЛрдВ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЬрдм рдореЙрдбрд▓ рдбреЗрдЯрд╛ рдмрджрд▓рддрд╛ рд╣реИ, рддреЛ рдореЙрдбрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рд╕рднреА рд╡рдВрд╢рдЬ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдП рдЬрд╛рдПрдВрдЧреЗред рдпрд╣ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореВрд▓ рд░реВрдк рд╕реЗ рдлреБрдЪрд┐рдпрд╛ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛрдб рд╕реЗ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред
рдЪрд▓реЛ рдкрд┐рдЫрд▓реЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рдорд╛рди рд╕реНрдХреНрд░реАрди рдмрдирд╛рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╕реНрдХреЛрдкреНрдб рдореЙрдбрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдПред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рд╕реНрдХреЛрдкреНрдб рдореЙрдбрд▓ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛ рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛ред dependencies
рдЕрдиреБрднрд╛рдЧ рдореЗрдВ scoped_model
рдлрд╝рд╛рдЗрд▓ рдореЗрдВ scoped_model
рдирд┐рд░реНрднрд░рддрд╛ рдЬреЛрдбрд╝реЗрдВред
scoped_model: ^1.0.1
рдЖрдЗрдП UserModelScreen
рдХреЛрдб рдХреЛ рджреЗрдЦреЗрдВ рдФрд░ рдкрд┐рдЫрд▓реЗ рдЙрджрд╛рд╣рд░рдг рд╕реЗ рддреБрд▓рдирд╛ рдХрд░реЗрдВ, рдЬрд┐рд╕рдореЗрдВ рд╣рдордиреЗ рд╕реНрдХреЛрдкреНрдб рдореЙрдбрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИред рд╣рдорд╛рд░реЗ рдореЙрдбрд▓ рдХреЛ рд╡рд┐рдЬреЗрдЯ рдХреЗ рд╡рдВрд╢рдЬреЛрдВ рдХреЗ рд▓рд┐рдП рд╕реБрд▓рдн рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ ScopedModel
рдореЗрдВ рд╡рд┐рдЬреЗрдЯ рдФрд░ рдореЙрдбрд▓ рдХреЛ рд▓рдкреЗрдЯрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
class UserModelScreen extends StatefulWidget { UserModelScreen(this._repository); final Repository _repository; @override State<StatefulWidget> createState() => _UserModelScreenState(); } class _UserModelScreenState extends State<UserModelScreen> { UserModel _userModel; @override void initState() { _userModel = UserModel(widget._repository); super.initState(); } @override Widget build(BuildContext context) { return ScopedModel( model: _userModel, child: Scaffold( appBar: AppBar( title: const Text('Scoped model'), ), body: SafeArea( child: ScopedModelDescendant<UserModel>( builder: (context, child, model) { if (model.isLoading) { return _buildLoading(); } else { if (model.user != null) { return _buildContent(model); } else { return _buildInit(model); } } }, ), ), ), ); } Widget _buildInit(UserModel userModel) { return Center( child: RaisedButton( child: const Text('Load user data'), onPressed: () { userModel.loadUserData(); }, ), ); } Widget _buildContent(UserModel userModel) { return Center( child: Text('Hello ${userModel.user.name} ${userModel.user.surname}'), ); } Widget _buildLoading() { return const Center( child: CircularProgressIndicator(), ); } }
рдкрд┐рдЫрд▓реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╣рд░ рдмрд╛рд░ рдЬрдм рдХреЛрдИ рд╡рд┐рдЬреЗрдЯ рд╕реНрдерд┐рддрд┐ рдмрджрд▓рддрд╛ рд╣реИ, рддреЛ рд╡рд┐рдЬреЗрдЯ рдЯреНрд░реА рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ред рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣рдореЗрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдкреВрд░реЗ рд╡рд┐рдЬреЗрдЯ рдЯреНрд░реА (рдкреВрд░реНрдг рд╕реНрдХреНрд░реАрди) рдХреЛ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ? рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, AppBar рдмрд┐рд▓реНрдХреБрд▓ рдирд╣реАрдВ рдмрджрд▓рддрд╛ рд╣реИ, рдФрд░ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдиреЗ рдХрд╛ рдХреЛрдИ рдорддрд▓рдм рдирд╣реАрдВ рд╣реИред рдЖрджрд░реНрд╢ рд░реВрдк рд╕реЗ, рдЖрдкрдХреЛ рдХреЗрд╡рд▓ рдЙрди рд╡рд┐рдЬреЗрдЯреНрд╕ рдХреЛ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрд┐рдиреНрд╣реЗрдВ рд░рд╛рдЬреНрдп рдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдмрджрд▓рдирд╛ рдЪрд╛рд╣рд┐рдПред рдФрд░ рд╕реНрдХреЛрдкреНрдб рдореЙрдбрд▓ рд╣рдореЗрдВ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░ рд╕рдХрддрд╛ рд╣реИред
ScopedModelDescendant<UserModel>
рд╡рд┐рдЬреЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╡рд┐рдЬреЗрдЯ рд╡рд┐рдЬреЗрдЯ рдореЗрдВ UserModel
рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╣рд░ рдмрд╛рд░ рдЬрдм UserModel
рд╕реВрдЪрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдмрджрд▓рд╛рд╡ рд╣реБрдЖ рд╣реИ рддреЛ рдпрд╣ рд╕реНрд╡рддрдГ рд╣реА рдлрд┐рд░ рд╕реЗ рдЖ рдЬрд╛рдПрдЧрд╛ред
рдПрдХ рдФрд░ рд╕реБрдзрд╛рд░ рдпрд╣ рд╣реИ рдХрд┐ UserModelScreen
рдЕрдм рд░рд╛рдЬреНрдп рдкреНрд░рдмрдВрдзрди, рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рддрд░реНрдХ рдФрд░ рдбреЗрдЯрд╛ рд▓реЛрдбрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рдирд╣реАрдВ рд╣реИред
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛрдб рдХреЗ рд▓рд┐рдП рдХреЛрдб рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВред
class UserModel extends Model { UserModel(this._repository); final Repository _repository; bool _isLoading = false; User _user; User get user => _user; bool get isLoading => _isLoading; void loadUserData() { _isLoading = true; notifyListeners(); _repository.getUser().then((user) { _user = user; _isLoading = false; notifyListeners(); }); } static UserModel of(BuildContext context) => ScopedModel.of<UserModel>(context); }
UserModel
рдЕрдм рд╢рд╛рдорд┐рд▓ рд╣реИ рдФрд░ рд░рд╛рдЬреНрдп рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░рддрд╛ рд╣реИред рд╢реНрд░реЛрддрд╛рдУрдВ рдХреЛ рд╕реВрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП (рдФрд░ рд╡рдВрд╢рдЬреЛрдВ рдХреЛ рдлрд┐рд░ рд╕реЗ notifyListeners()
рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП) рдХрд┐ рдПрдХ рдмрджрд▓рд╛рд╡ рд╣реБрдЖ рд╣реИ, notifyListeners()
рд╡рд┐рдзрд┐ рдХреЛ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдЖрдХрд░реНрд╖рдг рдЖрддреЗ рд╣реИрдВ
- рд╕реНрдЯреЗрдЯ рдореИрдиреЗрдЬрдореЗрдВрдЯ, рдмрд┐рдЬрдиреЗрд╕ рд▓реЙрдЬрд┐рдХ рдФрд░ рдбреЗрдЯрд╛ рд▓реЛрдбрд┐рдВрдЧ рдпреВрдЖрдИ рдХреЛрдб рд╕реЗ рдЕрд▓рдЧ рд╣реЛрддреЗ рд╣реИрдВред
- рдХрдо рдкреНрд░рд╡реЗрд╢ рджрд╣рд▓реАрдЬред
рд╡рд┐рдкрдХреНрд╖
- рддреГрддреАрдп-рдкрдХреНрд╖ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдирд┐рд░реНрднрд░рддрд╛ред
- рдпрджрд┐ рдореЙрдбрд▓ рдкрд░реНрдпрд╛рдкреНрдд рд░реВрдк рд╕реЗ рдЬрдЯрд┐рд▓ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЕрдирд╛рд╡рд╢реНрдпрдХ рдордиреЛрд░рдВрдЬрди рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП
notifyListeners()
рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЖрд╡рд╢реНрдпрдХ рд╣реЛрдиреЗ рдкрд░ рдирдЬрд╝рд░ рд░рдЦрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реЛрдЧрд╛ред
рдмреНрд▓реЙрдХ
BLoC ( B usiness Logic C рдУрдордкрд░реНрд╕) Google рд╕реЗ рдбреЗрд╡рд▓рдкрд░реНрд╕ рджреНрд╡рд╛рд░рд╛ рдЕрдиреБрд╢рдВрд╕рд┐рдд рдПрдХ рдкреИрдЯрд░реНрди рд╣реИред рд░рд╛рдЬреНрдп рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░рдиреЗ рдФрд░ рд░рд╛рдЬреНрдп рдкрд░рд┐рд╡рд░реНрддрди рдХреА рд╕реВрдЪрдирд╛ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдзрд╛рд░рд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдПрдВрдбреНрд░реЙрдЗрдб рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рд▓рд┐рдП: рдЖрдк рдХрд▓реНрдкрдирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ Bloc
рдПрдХ LiveData
рд╣реИ, рдФрд░ LiveData
рдПрдХ LiveData
ред рдпрд╣ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рдХреЛ рд╕рдордЭрдиреЗ рдореЗрдВ рдЖрд╕рд╛рди рдмрдирд╛ рджреЗрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдЖрдк рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдореВрд▓ рд╕рд┐рджреНрдзрд╛рдВрддреЛрдВ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реИрдВред
class UserBloc { UserBloc(this._repository); final Repository _repository; final _userStreamController = StreamController<UserState>(); Stream<UserState> get user => _userStreamController.stream; void loadUserData() { _userStreamController.sink.add(UserState._userLoading()); _repository.getUser().then((user) { _userStreamController.sink.add(UserState._userData(user)); }); } void dispose() { _userStreamController.close(); } } class UserState { UserState(); factory UserState._userData(User user) = UserDataState; factory UserState._userLoading() = UserLoadingState; } class UserInitState extends UserState {} class UserLoadingState extends UserState {} class UserDataState extends UserState { UserDataState(this.user); final User user; }
рдХреЛрдб рджрд┐рдЦрд╛рддрд╛ рд╣реИ рдХрд┐ рд░рд╛рдЬреНрдп рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реВрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрддрд┐рд░рд┐рдХреНрдд рддрд░реАрдХреЛрдВ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред
рдореИрдВрдиреЗ рд╕рдВрднрд╛рд╡рд┐рдд рд░рд╛рдЬреНрдпреЛрдВ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП 3 рдХрдХреНрд╖рд╛рдПрдВ рдмрдирд╛рдИрдВ:
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗрдВрджреНрд░ рдореЗрдВ рдПрдХ рдмрдЯрди рдХреЗ рд╕рд╛рде рдПрдХ рд╕реНрдХреНрд░реАрди рдЦреЛрд▓рддрд╛ рд╣реИ, рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд▓рд┐рдП UserInitState
ред
рдЬрдм рдбреЗрдЯрд╛ рд▓реЛрдб рд╣реЛ рд░рд╣рд╛ рд╣реИ рддреЛ рд▓реЛрдбрд┐рдВрдЧ рдЗрдВрдбрд┐рдХреЗрдЯрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рд╣реЛрдиреЗ рдкрд░ рд░рд╛рдЬреНрдп рдХреЗ рд▓рд┐рдП UserLoadingState
ред
рдЬрдм рдбреЗрдЯрд╛ рдкрд╣рд▓реЗ рд╕реЗ рд▓реЛрдб рд╣реЛ рдФрд░ рд╕реНрдХреНрд░реАрди рдкрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рд╣реЛ, рддрдм рд╕реНрдЯреЗрдЯ рдХреЗ рд▓рд┐рдП UserDataState
ред
рдЗрд╕ рддрд░рд╣ рд╕реЗ рдкрд╛рд╕рд┐рдВрдЧ рд╕реНрдЯреЗрдЯ рд╣рдореЗрдВ рдпреВрдЖрдИ рдХреЛрдб рдореЗрдВ рддрд░реНрдХ рд╕реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рд╕реНрдХреЛрдкреЗрдб рдореЙрдбрд▓ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╣рдордиреЗ рдЕрднреА рднреА рдЬрд╛рдБрдЪ рдХреА рд╣реИ рдХрд┐ _isLoading
рдлрд╝реАрд▓реНрдб _isLoading
рдорд╛рди true
рдпрд╛ false
рд╣реИ рдХрд┐ рдХреМрди рд╕рд╛ рд╡рд┐рдЬреЗрдЯ рдмрдирд╛рдирд╛ рд╣реИред BLoC рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдо рдирдИ рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕реНрдЯреНрд░реАрдо рдореЗрдВ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ UserBlocScreen
рд╡рд┐рдЬреЗрдЯ UserBlocScreen
рдПрдХрдорд╛рддреНрд░ рдХрд╛рд░реНрдп рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХреЗ рд▓рд┐рдП UI рдмрдирд╛рдирд╛ рд╣реИред
class UserBlocScreen extends StatefulWidget { UserBlocScreen(this._repository); final Repository _repository; @override State<StatefulWidget> createState() => _UserBlocScreenState(); } class _UserBlocScreenState extends State<UserBlocScreen> { UserBloc _userBloc; @override void initState() { _userBloc = UserBloc(widget._repository); super.initState(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Bloc'), ), body: SafeArea( child: StreamBuilder<UserState>( stream: _userBloc.user, initialData: UserInitState(), builder: (context, snapshot) { if (snapshot.data is UserInitState) { return _buildInit(); } if (snapshot.data is UserDataState) { UserDataState state = snapshot.data; return _buildContent(state.user); } if (snapshot.data is UserLoadingState) { return _buildLoading(); } }, ), ), ); } Widget _buildInit() { return Center( child: RaisedButton( child: const Text('Load user data'), onPressed: () { _userBloc.loadUserData(); }, ), ); } Widget _buildContent(User user) { return Center( child: Text('Hello ${user.name} ${user.surname}'), ); } Widget _buildLoading() { return const Center( child: CircularProgressIndicator(), ); } @override void dispose() { _userBloc.dispose(); super.dispose(); } }
рдкрд┐рдЫрд▓реЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ UserBlocScreen
рд╡рд┐рдЬреЗрдЯ рдХреЗ рд▓рд┐рдП рдХреЛрдб рдФрд░ рднреА рд╕рд░рд▓ рд╣реИред рд░рд╛рдЬреНрдп рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рд╕реБрдирдиреЗ рдХреЗ рд▓рд┐рдП, StreamBuilder рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред StreamBuilder
рдПрдХ StatefulWidget
рдЬреЛ рд╕реНрдЯреНрд░реАрдо ( рд╕реНрдЯреНрд░реАрдо ) рдХреЗ рдЕрдВрддрд┐рдо рдорд╛рди (рд╕реНрдиреИрдкрд╢реЙрдЯ) рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдЦреБрдж рдХреЛ рдмрдирд╛рддрд╛ рд╣реИред
рдЖрдХрд░реНрд╖рдг рдЖрддреЗ рд╣реИрдВ
- рдХрд┐рд╕реА рддреАрд╕рд░реЗ рдкрдХреНрд╖ рдХреЗ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВред
- рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рддрд░реНрдХ, рд░рд╛рдЬреНрдп рдкреНрд░рдмрдВрдзрди рдФрд░ рдбреЗрдЯрд╛ рд▓реЛрдбрд┐рдВрдЧ UI рдХреЛрдб рд╕реЗ рдЕрд▓рдЧ рд╣реЛрддреЗ рд╣реИрдВред
- Reactivityред рдЕрддрд┐рд░рд┐рдХреНрдд рддрд░реАрдХреЛрдВ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП
notifyListeners()
рдореЙрдбрд▓ notifyListeners()
ред
рд╡рд┐рдкрдХреНрд╖
- рдкреНрд░рд╡реЗрд╢ рд╕реАрдорд╛ рдереЛрдбрд╝реА рдЕрдзрд┐рдХ рд╣реИред рдзрд╛рд░рд╛рдУрдВ рдпрд╛ rxdart рдХреЗ рд╕рд╛рде рдЕрдиреБрднрд╡ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рд▓рд┐рдВрдХ
рдЖрдк рдореЗрд░реЗ рдЬреАрдердм рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рд╕реЗ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдХреЗ рдкреВрд░рд╛ рдХреЛрдб рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред
рдорд╛рдзреНрдпрдо рдкрд░ рдкреНрд░рдХрд╛рд╢рд┐рдд рдореВрд▓ рд▓реЗрдЦ