在Flutter开发中,为了提高应用程序的性能和稳定性,我们需要注意以下几个方面:
-
避免不必要的重建:在使用StatefulWidget时,我们应该尽量避免重复创建相同的Widget对象,可以使用
const
关键字或Key
来避免不必要的重建。 -
避免不必要的渲染:在使用StatefulWidget时,我们应该尽量避免不必要的渲染,可以使用
shouldRebuild
方法来判断是否需要重新构建Widget。 -
避免不必要的状态更新:在使用StatefulWidget时,我们应该尽量避免不必要的状态更新,可以使用
setState
方法的回调函数来避免不必要的状态更新。 -
避免不必要的资源浪费:在使用资源时,我们应该尽量避免不必要的资源浪费,例如使用
CachedNetworkImage
来缓存网络图片、使用Disposable
来释放资源等。 -
避免内存泄漏:在使用StatefulWidget时,我们应该注意及时释放资源,避免内存泄漏,例如在使用异步操作时,必须在Widget销毁时取消异步操作。
-
避免不必要的重复计算:在使用计算密集型操作时,我们应该尽量避免不必要的重复计算,例如在使用ListView时,可以使用
ListView.builder
来避免不必要的重复计算。 -
避免不必要的布局:在使用布局时,我们应该尽量避免不必要的布局,例如使用
Expanded
、Flexible
等Widget来优化布局,避免不必要的布局计算。 -
避免不必要的重绘:在使用自定义绘制时,我们应该尽量避免不必要的重绘,可以使用
shouldRepaint
方法来判断是否需要重绘。 -
避免不必要的动画:在使用动画时,我们应该尽量避免不必要的动画,例如在滚动列表时,可以使用
AnimatedList
来实现平滑的滚动效果,避免不必要的动画效果。 -
避免不必要的网络请求:在使用网络请求时,我们应该尽量避免不必要的网络请求,例如使用缓存、使用WebSockets等技术来优化网络请求。
-
避免不必要的阻塞:在使用异步操作时,我们应该尽量避免不必要的阻塞,例如使用异步方式来执行耗时操作,避免阻塞UI线程。
-
避免不必要的多线程:在使用多线程时,我们应该尽量避免不必要的多线程,例如使用Isolate等技术来优化多线程操作。
对此12个注意点,我们分别进行详细的举例说明:
- 避免不必要的重建:例如,我们可以使用
const
关键字或Key
来避免不必要的重建,例如:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'MyApp',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('HomePage')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('You have pushed the button this many times:'),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
key: const Key('increment_fab'),
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
- 避免不必要的渲染:例如,我们可以使用
shouldRebuild
方法来判断是否需要重新构建Widget,例如:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MyApp',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _counter = 0;
bool _shouldRebuild(_HomePageState oldWidget) {
return _counter != oldWidget._counter;
}
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('HomePage')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('You have pushed the button this many times:'),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
- 避免不必要的状态更新:例如,我们可以使用
setState
方法的回调函数来避免不必要的状态更新,例如:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MyApp',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
}, () {
print('Counter has been updated.');
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('HomePage')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('You have pushed the button this many times:'),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
- 避免不必要的资源浪费:例如,我们可以使用
CachedNetworkImage
来缓存网络图片、使用Disposable
来释放资源等,例如:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MyApp',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final _imageProvider = CachedNetworkImageProvider(
'https://flutter.github.io/assets-for-api-docs/assets/widgets/owl-2.jpg');
@override
void dispose() {
_imageProvider.evict();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('HomePage')),
body: Center(
child: Image(image: _imageProvider),
),
);
}
}
- 避免内存泄漏:例如,在使用异步操作时,必须在Widget销毁时取消异步操作,例如:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MyApp',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final _subscription = Stream.periodic(const Duration(seconds: 1), (i) => i + 1);
@override
void dispose() {
_subscription.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('HomePage')),
body: StreamBuilder<int>(
stream: _subscription,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Center(
child: Text(
'Count: ${snapshot.data}',
style: Theme.of(context).textTheme.headline4,
),
);
} else {
return const Center(child: CircularProgressIndicator());
}
},
),
);
}
}
- 避免不必要的重复计算:例如,在使用ListView时,可以使用
ListView.builder
来避免不必要的重复计算,例如:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MyApp',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final _items = List.generate(100000, (index) => 'Item $index');
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('HomePage')),
body: ListView.builder(
itemCount: _items.length,
itemBuilder: (context, index) {
return ListTile(title: Text(_items[index]));
},
),
);
}
}
- 避免不必要的布局:例如,在使用布局时,我们应该尽量避免不必要的布局,例如使用
Expanded
、Flexible
等Widget来优化布局,避免不必要的布局计算,例如:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MyApp',
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('HomePage')),
body: Column(
children: <Widget>[
Expanded(
child: Container(color: Colors.red),
flex: 1,
),
Expanded(
child: Container(color: Colors.blue),
flex: 2,
),
],
),
);
}
}
- 避免不必要的重绘:例如,在使用自定义绘制时,我们应该尽量避免不必要的重绘,可以使用
shouldRepaint
方法来判断是否需要重绘,例如:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MyApp',
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('HomePage')),
body: CustomPaint(
painter: MyPainter(),
),
);
}
}
class MyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
canvas.drawCircle(Offset.zero, 50, Paint()..color = Colors.red);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return false;
}
}
- 避免不必要的动画:例如,在滚动列表时,可以使用
AnimatedList
来实现平滑的滚动效果,避免不必要的动画效果,例如:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MyApp',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final _items = List.generate(100, (index) => 'Item $index');
final _animationController = AnimationController(
vsync: const TestVSync(),
duration: const Duration(seconds: 2),
);
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
void _addItem() {
setState(() {
_items.add('Item ${_items.length}');
});
}
void _removeItem() {
setState(() {
_items.removeLast();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('HomePage')),
body: AnimatedList(
itemBuilder: (context, index, animation) {
return ListTile(
title: Text(_items[index]),
trailing: IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
_removeItem();
},
),
);
},
initialItemCount: _items.length,
key: UniqueKey(),
),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FloatingActionButton(
heroTag: 'addItem',
onPressed: _addItem,
tooltip: 'Add Item',
child: const Icon(Icons.add),
),
const SizedBox(width: 16),
FloatingActionButton(
heroTag: 'removeItem',
onPressed: _removeItem,
tooltip: 'Remove Item',
child: const Icon(Icons.remove),
),
],
),
);
}
}
- 避免不必要的网络请求:例如,我们可以使用缓存、使用WebSockets等技术来优化网络请求,例如:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MyApp',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final _httpClient = HttpClient();
String _response = '';
Future<void> _makeRequest() async {
final request =
await _httpClient.getUrl(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'));
final response = await request.close();
final responseBody = await response.transform(utf8.decoder).join();
setState(() {
_response = responseBody;
});
}
@override
void dispose() {
_httpClient.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('HomePage')),
body: Center(
child: Text(_response), ),
floatingActionButton: FloatingActionButton( onPressed: _makeRequest, tooltip: 'Make Request',
child: const Icon(Icons.refresh),
),
);
}
}
- 避免不必要的阻塞:例如,在使用异步操作时,我们应该尽量避免不必要的阻塞,例如使用异步方式来执行耗时操作,避免阻塞UI线程,例如:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp( title: 'MyApp', home: HomePage(),
); } }
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState(); }
class _HomePageState extends State<HomePage> {
Future<int> _calculate() async {
await Future.delayed(
const Duration(seconds: 1));
return 42; }
@override
Widget build(BuildContext context) {
return Scaffold( appBar: AppBar(title: const Text('HomePage')),
body: Center( child: FutureBuilder<int>( future: _calculate(),
builder: (context, snapshot){
if (snapshot.hasData) {
return Text('Result: ${snapshot.data}'); } else {
return const CircularProgressIndicator();
} }, ), ),
);
}
}
- 避免不必要的多线程:例如,在使用多线程时,我们应该尽量避免不必要的多线程,例如使用Isolate等技术来优化多线程操作,例如:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp( title: 'MyApp', home: HomePage(), ); } }
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState(); }
class _HomePageState extends State<HomePage> {
Future<int> _calculate() async {
final receivePort = ReceivePort();
await Isolate.spawn(_calculateInIsolate, receivePort.sendPort);
final completer = Completer<int>();
receivePort.listen((message) {
completer.complete(message); receivePort.close();
});
return completer.future; }
static void _calculateInIsolate(SendPort sendPort) { sendPort.send(42); }
@override
Widget build(BuildContext context) {
return Scaffold( appBar: AppBar(title: const Text('HomePage')),
body: Center( child: FutureBuilder<int>( future: _calculate(), builder: (context, snapshot) {
if (snapshot.hasData) {
return Text('Result: ${snapshot.data}'); } else {
return const CircularProgressIndicator();
} }, ), ), );
}
}
以上就是实际开发中12个需要我们注意的点。
最后,在我们成长的道路上日拱一卒,是我们最平凡的人能做到的最不平凡的事。