
هناك العديد من الأسئلة والحلول والمفاهيم الخاطئة حول كيفية تحسين أداء تطبيق 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