
هناك العديد من الأسئلة والحلول والمفاهيم الخاطئة حول كيفية تحسين أداء تطبيق Flutter. تحتاج إلى توضيح فورًا أن Flutter فعال بشكل افتراضي ، ولكن يجب علينا تجنب بعض الأخطاء عند كتابة التعليمات البرمجية حتى يعمل التطبيق دائمًا بشكل جيد وسريع. أدناه ، أعددت لك سلسلة من النصائح والحيل حول كيفية الكتابة حتى لا تضطر إلى اللجوء باستمرار إلى أدوات التنميط.
المحتوى:
لا تضع الحاجيات في أساليب الصف
, , , .
, , "" (footer).
class MyHomePage extends StatelessWidget {
Widget _buildHeaderWidget() {
final size = 40.0;
return Padding(
padding: const EdgeInsets.all(8.0),
child: CircleAvatar(
backgroundColor: Colors.grey[700],
child: FlutterLogo(
size: size,
),
radius: size,
),
);
}
Widget _buildMainWidget(BuildContext context) {
return Expanded(
child: Container(
color: Colors.grey[700],
child: Center(
child: Text(
'Hello Flutter',
style: Theme.of(context).textTheme.display1,
),
),
),
);
}
Widget _buildFooterWidget() {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Text('This is the footer '),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_buildHeaderWidget(),
_buildMainWidget(context),
_buildFooterWidget(),
],
),
),
);
}
}

, , – . ? , , MyHomePage
, , , , .
, StatelessWidget
.
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
HeaderWidget(),
MainWidget(),
FooterWidget(),
],
),
),
);
}
}
class HeaderWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final size = 40.0;
return Padding(
padding: const EdgeInsets.all(8.0),
child: CircleAvatar(
backgroundColor: Colors.grey[700],
child: FlutterLogo(
size: size,
),
radius: size,
),
);
}
}
class MainWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Expanded(
child: Container(
color: Colors.grey[700],
child: Center(
child: Text(
'Hello Flutter',
style: Theme.of(context).textTheme.display1,
),
),
),
);
}
}
class FooterWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Text('This is the footer '),
);
}
}
Stateful
/Stateless
"", , , . , . ( )
const
. , .
, , Flutter StatefulWidget
setState
.
— , FloatingActionButton
, . , . , print
build
, , .
class _MyHomePageState extends State<MyHomePage> {
Color _currentColor = Colors.grey;
Random _random = new Random();
void _onPressed() {
int randomNumber = _random.nextInt(30);
setState(() {
_currentColor = Colors.primaries[randomNumber % Colors.primaries.length];
});
}
@override
Widget build(BuildContext context) {
print('building `MyHomePage`');
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _onPressed,
child: Icon(Icons.colorize),
),
body: Stack(
children: [
Positioned.fill(
child: BackgroundWidget(),
),
Center(
child: Container(
height: 150,
width: 150,
color: _currentColor,
),
),
],
),
);
}
}
class BackgroundWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
print('building `BackgroundWidget`');
return Image.network(
'https://cdn.pixabay.com/photo/2017/08/30/01/05/milky-way-2695569_960_720.jpg',
fit: BoxFit.cover,
);
}
}

flutter: building `MyHomePage`
flutter: building `BackgroundWidget`
, , : Scaffold
, BackgroundWidget
, , , , – -Container
.
, – . , . , : flutter_bloc, mobx, provider . . , , Flutter , - .
, , ValueNotifier
.
class _MyHomePageState extends State<MyHomePage> {
final _colorNotifier = ValueNotifier<Color>(Colors.grey);
Random _random = new Random();
void _onPressed() {
int randomNumber = _random.nextInt(30);
_colorNotifier.value =
Colors.primaries[randomNumber % Colors.primaries.length];
}
@override
void dispose() {
_colorNotifier.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
print('building `MyHomePage`');
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _onPressed,
child: Icon(Icons.colorize),
),
body: Stack(
children: [
Positioned.fill(
child: BackgroundWidget(),
),
Center(
child: ValueListenableBuilder(
valueListenable: _colorNotifier,
builder: (_, value, __) => Container(
height: 150,
width: 150,
color: value,
),
),
),
],
),
);
}
}
… . , , , (. ValueListenableBuilder ValueNotifier).
, , - (, , ) ( ).
, ChangeNotifier
.
class MyColorNotifier extends ChangeNotifier {
Color myColor = Colors.grey;
Random _random = new Random();
void changeColor() {
int randomNumber = _random.nextInt(30);
myColor = Colors.primaries[randomNumber % Colors.primaries.length];
notifyListeners();
}
}
class _MyHomePageState extends State<MyHomePage> {
final _colorNotifier = MyColorNotifier();
void _onPressed() {
_colorNotifier.changeColor();
}
@override
void dispose() {
_colorNotifier.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
print('building `MyHomePage`');
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _onPressed,
child: Icon(Icons.colorize),
),
body: Stack(
children: [
Positioned.fill(
child: BackgroundWidget(),
),
Center(
child: AnimatedBuilder(
animation: _colorNotifier,
builder: (_, __) => Container(
height: 150,
width: 150,
color: _colorNotifier.myColor,
),
),
),
],
),
);
}
}
, .
const
const
, , ( const
, ), , (. const).
setState
, , 1 .
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _onPressed() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
print('building `MyHomePage`');
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _onPressed,
child: Icon(Icons.colorize),
),
body: Stack(
children: [
Positioned.fill(
child: BackgroundWidget(),
),
Center(
child: Text(
_counter.toString(),
style: Theme.of(context).textTheme.display4.apply(
color: Colors.white,
fontWeightDelta: 2,
),
)),
],
),
);
}
}
class BackgroundWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
print('building `BackgroundWidget`');
return Image.network(
'https://cdn.pixabay.com/photo/2017/08/30/01/05/milky-way-2695569_960_720.jpg',
fit: BoxFit.cover,
);
}
}

2 , , – BackgroundWidget
. , , , , .
flutter: building `MyHomePage`
flutter: building `BackgroundWidget`
const
BackgroundWidget
:
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _onPressed() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
print('building `MyHomePage`');
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _onPressed,
child: Icon(Icons.colorize),
),
body: Stack(
children: [
Positioned.fill(
child: const BackgroundWidget(),
),
Center(
child: Text(
_counter.toString(),
style: Theme.of(context).textTheme.display4.apply(
color: Colors.white,
fontWeightDelta: 2,
),
)),
],
),
);
}
}
class BackgroundWidget extends StatelessWidget {
const BackgroundWidget();
@override
Widget build(BuildContext context) {
print('building `BackgroundWidget`');
return Image.network(
'https://cdn.pixabay.com/photo/2017/08/30/01/05/milky-way-2695569_960_720.jpg',
fit: BoxFit.cover,
);
}
}
(, , , ) , const
.
itemExtent
ListView
, , , , , itemExtent
.
. 10 . . itemExtent
.
class MyHomePage extends StatelessWidget {
final widgets = List.generate(
10000,
(index) => Container(
height: 200.0,
color: Colors.primaries[index % Colors.primaries.length],
child: ListTile(
title: Text('Index: $index'),
),
),
);
final _scrollController = ScrollController();
void _onPressed() async {
_scrollController.jumpTo(
_scrollController.position.maxScrollExtent,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _onPressed,
splashColor: Colors.red,
child: Icon(Icons.slow_motion_video),
),
body: ListView(
controller: _scrollController,
children: widgets,
),
);
}
}

, (~10 ). - , . UI!
, itemExtent
, , .
class MyHomePage extends StatelessWidget {
final widgets = List.generate(
10000,
(index) => Container(
color: Colors.primaries[index % Colors.primaries.length],
child: ListTile(
title: Text('Index: $index'),
),
),
);
final _scrollController = ScrollController();
void _onPressed() async {
_scrollController.jumpTo(
_scrollController.position.maxScrollExtent,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _onPressed,
splashColor: Colors.red,
child: Icon(Icons.slow_motion_video),
),
body: ListView(
controller: _scrollController,
children: widgets,
itemExtent: 200,
),
);
}
}

- .
AnimatedBuilder
, . (addListener) AnimationController
setState
. , , . AnimatedBuilder
, .
, , 360 . CounterWidget
, , , .
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
AnimationController _controller;
int counter = 0;
void _onPressed() {
setState(() {
counter++;
});
_controller.forward(from: 0.0);
}
@override
void initState() {
_controller = AnimationController(
vsync: this, duration: const Duration(milliseconds: 600));
super.initState();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _onPressed,
splashColor: Colors.red,
child: Icon(Icons.slow_motion_video),
),
body: AnimatedBuilder(
animation: _controller,
builder: (_, child) => Transform(
alignment: Alignment.center,
transform: Matrix4.identity()
..setEntry(3, 2, 0.001)
..rotateY(360 * _controller.value * (pi / 180.0)),
child: CounterWidget(
counter: counter,
),
),
),
);
}
}
class CounterWidget extends StatelessWidget {
final int counter;
const CounterWidget({Key key, this.counter}) : super(key: key);
@override
Widget build(BuildContext context) {
print('building `CounterWidget`');
return Center(
child: Text(
counter.toString(),
style: Theme.of(context).textTheme.display4.apply(fontWeightDelta: 3),
),
);
}
}

.
flutter: building `CounterWidget`
flutter: building `CounterWidget`
flutter: building `CounterWidget`
flutter: building `CounterWidget`
flutter: building `CounterWidget`
...
flutter: building `CounterWidget`
, 1, , , , setState
. CounterWidget
?
! AnimatedBuilder
child
, . , , , , , Transform
.
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _onPressed,
splashColor: Colors.red,
child: Icon(Icons.slow_motion_video),
),
body: AnimatedBuilder(
animation: _controller,
child: CounterWidget(
counter: counter,
),
builder: (_, child) => Transform(
alignment: Alignment.center,
transform: Matrix4.identity()
..setEntry(3, 2, 0.001)
..rotateY(360 * _controller.value * (pi / 180.0)),
child: child,
),
),
);
}
, , , , . .
Opacity
.
- , Opacity
. , Transform
, Opacity
, .
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
AnimationController _controller;
int counter = 0;
void _onPressed() {
setState(() {
counter++;
});
_controller.forward(from: 0.0);
}
@override
void initState() {
_controller = AnimationController(
vsync: this, duration: const Duration(milliseconds: 600));
_controller.addStatusListener((status) {
if (status == AnimationStatus.completed) {
_controller.reverse();
}
});
super.initState();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _onPressed,
splashColor: Colors.red,
child: Icon(Icons.slow_motion_video),
),
body: AnimatedBuilder(
animation: _controller,
child: CounterWidget(
counter: counter,
),
builder: (_, child) => Opacity(
opacity: (1 - _controller.value),
child: child,
),
),
);
}
}

, , , Opacity
(, , ) , .
:
1 – FadeTransition
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
AnimationController _controller;
int counter = 0;
void _onPressed() {
setState(() {
counter++;
});
_controller.forward(from: 0.0);
}
@override
void initState() {
_controller = AnimationController(
vsync: this, duration: const Duration(milliseconds: 600));
_controller.addStatusListener((status) {
if (status == AnimationStatus.completed) {
_controller.reverse();
}
});
super.initState();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _onPressed,
splashColor: Colors.red,
child: Icon(Icons.slow_motion_video),
),
body: FadeTransition(
opacity: Tween(begin: 1.0, end: 0.0).animate(_controller),
child: CounterWidget(
counter: counter,
),
),
);
}
}
2 – AnimatedOpacity
const duration = const Duration(milliseconds: 600);
class _MyHomePageState extends State<MyHomePage> {
int counter = 0;
double opacity = 1.0;
void _onPressed() async {
counter++;
setState(() {
opacity = 0.0;
});
await Future.delayed(duration);
setState(() {
opacity = 1.0;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _onPressed,
splashColor: Colors.red,
child: Icon(Icons.slow_motion_video),
),
body: AnimatedOpacity(
opacity: opacity,
duration: duration,
child: CounterWidget(
counter: counter,
),
),
);
}
}
, Opacity
.
, Flutter , . , .
, - Filip Hráček Flutter Europe, Flutter .
:
:
Diego Velásquez – Flutter Dart GDE , . Flutter. Diego . Twitter.
PS مرة أخرى ، رابط إلى المقالة الأصلية كيفية تحسين أداء تطبيق Flutter الخاص بك بواسطة Diego Velásquez