
Ada banyak pertanyaan, solusi, dan kesalahpahaman tentang bagaimana kita dapat meningkatkan kinerja aplikasi Flutter kita. Anda harus segera mengklarifikasi bahwa Flutter kuat secara default, tetapi kami harus menghindari beberapa kesalahan saat menulis kode agar aplikasi selalu berfungsi dengan baik dan cepat. Di bawah ini saya siapkan untuk Anda serangkaian tips dan trik tentang cara menulis sehingga Anda tidak harus terus-menerus beralih ke alat profil.
Kandungan:
Jangan memasukkan widget ke dalam metode kelas
, , , .
, , "" (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 Sekali lagi, tautan ke artikel asli Cara meningkatkan kinerja aplikasi Flutter Anda oleh Diego Velásquez