Вы используете одну большую функцию сборки, вам нужно разделить ее на разные виджеты, потому что, когда состояние данных изменяется и вы вызываете setState()
, все потомки-потомки будут перестраиваться, поэтому избегайте использования очень большой вложенной функции сборки, которая будет очень дорогостоящим.
Кроме того, отладка влияет на производительность приложения, поэтому будет полезно принять решение о создании приложения выпуска.
выполните эту команду, чтобы построить приложение flutter build apk
.
Вы также можете проверить Построить и выпустить Android приложение или Построить и выпустить iOS приложение
Вы можете использовать профилирование Flutter Инструменты для определения производительности и определения проблем производительности в вашем приложении, вы можете найти более полезную информацию в следующей ссылке о профилировании производительности Flutter.
Профилирование производительности Flutter
также перейдите по этой ссылке для получения дополнительной информации и сведений о лучших методах повышения производительности.
Performan Лучшие практики CE
Обновление
Согласно Лучшие практики производительности
Избегайте слишком больших одиночных виджетов с большой функцией build (). Разделите их на разные виджеты, основываясь на инкапсуляции, а также на том, как они меняются: когда setState () вызывается для State, все дочерние виджеты будут перестраиваться. Поэтому локализуйте вызов setState () для той части поддерева, пользовательский интерфейс которой нужно изменить. Избегайте вызова setState () высоко в дереве, если изменение содержится в небольшой части дерева.
и в соответствии с документами
Вызов setState уведомляет платформу о том, что внутреннее состояние этого объекта изменилось таким образом, что это может повлиять на пользовательский интерфейс в этом поддереве, что заставляет платформу запланировать построение для этого объекта состояния.
Так что гораздо лучше разделить ваш код на маленькие виджеты, чтобы избежать больших вложенных виджетов в функции длинной сборки, и я рекомендую прочитать о Управление состоянием , это очень полезно для управления данными в вашем приложении и улучшает читаемость и возможность сопровождения вашего кода, что в конечном итоге приведет к повышению производительности.
Здесь я приведу пример развязки виджетов с помощью кода, приведенного в этом вопросе, вам необходимо прочитать комментарии в следующем коде, чтобы понять, как я разделил виджеты приложения, и я использовал флаттер производительность и количество кадров в секунду не упали ниже 30 в режиме отладки, в то время как предоставленный вами код упал ниже 15 кадров в секунду.
Вы можете сравнить оба кода и увидеть разницу в производительности, и не Не стесняйтесь спрашивать меня о коде для уточнения.
Файл home.dart
import 'package:flutter/material.dart';
/*
I created this class for a better data management around the application
but this design is not recommended
*/
class Bill {
static int _tipPercentage = 0;
static int _personCounter = 1;
static double _billAmount = 0.0;
static _calculateTotalPerPerson(
double billAmount, int splitBy, int tipPercentage) {
double totalPerPerson =
(billAmount + _calculateTotalTip(billAmount, splitBy, tipPercentage)) /
splitBy;
return totalPerPerson.toStringAsFixed(2);
}
static _calculateTotalTip(double billAmount, int splitBy, int tipPercentage) {
double totalTip = 0.0;
if (billAmount < 0 || billAmount.toString().isEmpty || billAmount == null) {
} else {
totalTip = (billAmount * tipPercentage) / 100;
}
return totalTip;
}
}
// I converted the main widget to a stateless widget
// and for a better data management I highly recommend searching about
// state management
class BillSplitter extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"APP Teste 1.0",
style: TextStyle(fontWeight: FontWeight.bold),
),
centerTitle: true,
backgroundColor: Colors.purple.withOpacity(0.5),
),
body: Container(
margin: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.1),
alignment: Alignment.center,
color: Colors.white,
/*
Inside this ListView a lot of children widgets which can be converted
to smaller widgets in different classes based on the state of the widget
either it's stateless or stateful
*/
child: ListView(
scrollDirection: Axis.vertical,
padding: EdgeInsets.all(20.5),
children: <Widget>[
CurrentBillContainer(), //Check this widget class down below
BillCalculator(),
],
),
),
);
}
}
/*
This container is for the upper pink box which holds the bill value
and viewed in a different widget with a different build function
which will enhance the build() function time
*/
class CurrentBillContainer extends StatefulWidget {
@override
_CurrentBillContainerState createState() => _CurrentBillContainerState();
}
class _CurrentBillContainerState extends State<CurrentBillContainer> {
@override
Widget build(BuildContext context) {
return Container(
width: 150,
height: 150,
decoration: BoxDecoration(
color: Colors.purple.withOpacity(0.1),
borderRadius: BorderRadius.circular(12.0)),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"Total por pessoa",
style: TextStyle(
color: Colors.purple,
fontWeight: FontWeight.normal,
fontSize: 17.0),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
"R\$ ${Bill._calculateTotalPerPerson(Bill._billAmount, Bill._personCounter, Bill._tipPercentage)}",
style: TextStyle(
color: Colors.purple,
fontWeight: FontWeight.bold,
fontSize: 35.0),
),
)
],
),
),
);
}
}
class BillCalculator extends StatefulWidget {
@override
_BillCalculatorState createState() => _BillCalculatorState();
}
class _BillCalculatorState extends State<BillCalculator> {
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(top: 20.0),
padding: EdgeInsets.all(12.0),
decoration: BoxDecoration(
color: Colors.transparent,
border: Border.all(
color: Colors.blueGrey.shade100, style: BorderStyle.solid),
borderRadius: BorderRadius.circular(12.0)),
child: Column(
children: <Widget>[
TotalBillTextField(),
DividirRow(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"Gorjeta",
style: TextStyle(color: Colors.grey.shade700),
),
Padding(
padding: const EdgeInsets.all(18.0),
child: Text(
"R\$ ${(Bill._calculateTotalTip(Bill._billAmount, Bill._personCounter, Bill._tipPercentage)).toStringAsFixed(2)}",
style: TextStyle(
color: Colors.purple,
fontWeight: FontWeight.bold,
fontSize: 17.0),
),
)
],
),
Column(
children: <Widget>[
Text(
"${Bill._tipPercentage}%",
style: TextStyle(
color: Colors.purple,
fontSize: 17.0,
fontWeight: FontWeight.bold),
),
Slider(
activeColor: Colors.purple,
inactiveColor: Colors.grey,
min: 0,
max: 100,
divisions: 10,
value: Bill._tipPercentage.toDouble(),
onChanged: (double value) {
setState(() {
Bill._tipPercentage = value.round();
});
})
],
)
],
),
);
}
}
/*
Take this TextField as an example you can create a stateless widget for it
and place it inside the column of BillCalculator class
and you can apply the same concept all over the application,
and divide widgets to small classes and inside sub folders to reduce the size
of the build function and optimize the performance and make it easier to
maintain and add a new features in your application
*/
class TotalBillTextField extends StatelessWidget {
@override
Widget build(BuildContext context) {
return TextField(
keyboardType: TextInputType.numberWithOptions(decimal: true),
style: TextStyle(color: Colors.purple),
decoration: InputDecoration(
prefixText: "Total da Conta: R\$ ",
prefixIcon: Icon(Icons.attach_money)),
onChanged: (String value) {
try {
Bill._billAmount = double.parse(value);
} catch (e) {
Bill._billAmount = 0.0;
}
},
);
}
}
/*
This row has to be a Stateful widget because you are using
setState() function, you can apply the same method to all of the widgets
*/
class DividirRow extends StatefulWidget {
@override
_DividirRowState createState() => _DividirRowState();
}
class _DividirRowState extends State<DividirRow> {
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"Dividir",
style: TextStyle(color: Colors.grey.shade700),
),
Row(
children: <Widget>[
InkWell(
onTap: () {
setState(() {
if (Bill._personCounter > 1) {
Bill._personCounter--;
}
});
},
child: Container(
width: 40.0,
height: 40.0,
margin: EdgeInsets.all(10.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(7.0),
color: Colors.purpleAccent.withOpacity(0.1)),
child: Center(
child: Text(
"-",
style: TextStyle(
color: Colors.purple,
fontWeight: FontWeight.bold,
fontSize: 17.0),
)),
),
),
Text(
"${Bill._personCounter}",
style: TextStyle(
color: Colors.purple,
fontWeight: FontWeight.bold,
fontSize: 17.0),
),
InkWell(
onTap: () {
setState(() {
Bill._personCounter++;
});
},
child: Container(
width: 40.0,
height: 40.0,
margin: EdgeInsets.all(10.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(7.0),
color: Colors.purpleAccent.withOpacity(0.1)),
child: Center(
child: Text(
"+",
style: TextStyle(
color: Colors.purple,
fontWeight: FontWeight.bold,
fontSize: 17.0),
)),
),
),
],
),
],
);
}
}