下面是一个最小的应用程序,展示了我的担忧。如果运行它,您将看到每个可见项的构建方法都会运行,即使只有一项的数据发生了更改。
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyList extends StatelessWidget {
final List<int> items;
MyList(this.items);
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
print("item $index built");
return ListTile(
title: Text('${items[index]}'),
);
});
}
}
class MyApp extends StatefulWidget {
MyApp({Key? key}) : super(key: key);
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<int> items = List<int>.generate(10000, (i) => i);
void _incrementItem2() {
setState(() {
this.items[1]++;
});
}
@override
Widget build(BuildContext context) {
final title = 'Long List';
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Column(
children: <Widget>[
MyButton(_incrementItem2),
Expanded(child: MyList(this.items))
],
),
),
);
}
}
class MyButton extends StatelessWidget {
final Function incrementItem2;
void handlePress() {
incrementItem2();
}
MyButton(this.incrementItem2);
@override
Widget build(BuildContext context) {
return TextButton(
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all<Color>(Colors.blue),
),
onPressed: handlePress,
child: Text('increment item 2'),
);
}
}
Run Code Online (Sandbox Code Playgroud)
在 React / React Native 中,我会使用 shouldComponentUpdate 或 UseMemo 来防止不必要的渲染。我想在 Flutter 中做同样的事情。
以下是 Flutter github 上同一主题的已关闭问题的链接:(我将在此问题的链接中发表评论) https://github.com/flutter/flutter/issues/19421
避免无用的“重新渲染”或调用 Flutter 中的构建方法的最佳实践是什么,或者考虑到 Flutter 和 React 之间的结构差异,这些额外的构建不是一个严重的问题吗?
这或多或少类似于几年前在堆栈溢出上提出的这个问题:How to Prevent rerender of a widget based on custom logic in flutter?
给出的赞成答案是使用 ListView.builder。虽然这可以阻止一些(如果不是大多数)无用的渲染,但它并不能阻止所有无用的渲染,如我的示例所示。
预先感谢您的知识和见解。
Flutter 的关键特性之一是每个 Widget 都是自己的单元,并且可以在需要时决定重建。
Bloc 库可以很好地控制重建的内容。如果 ListTile 中的文本发生变化,您将有一个 MyListTile 类:
class MyListTile extends StatelessWidget {
final int index;
MyListTile(this.index):super(key:ValueKey(index));
@override
Widget build(BuildContext context) {
return BlocBuilder<ItemBloc, ItemState>(
buildWhen: (previous, current) {
return previous.items[index] != current.items[index];
},
builder: (context, state) {
return ListTile(title: Text('${state.items[index]}'));
},
);
}
}
Run Code Online (Sandbox Code Playgroud)
BlocBuilder 的 buildWhen 就像您习惯的 shouldComponentUpdate 一样,它为您提供了很多控制权。
| 归档时间: |
|
| 查看次数: |
10170 次 |
| 最近记录: |