refact: flutter, ChangeNotifier, reduce rebuild (#9392)

Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
fufesou 2024-09-19 18:48:01 +08:00 committed by GitHub
parent 88a99211f3
commit c6e3f60a6b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 21 additions and 7 deletions

View File

@ -250,6 +250,9 @@ class _PeerCardState extends State<_PeerCard>
color: Colors.transparent, color: Colors.transparent,
elevation: 0, elevation: 0,
margin: EdgeInsets.zero, margin: EdgeInsets.zero,
// to-do: memory leak here, more investigation needed.
// Continious rebuilds of `Obx()` will cause memory leak here.
// The simple demo does not have this issue.
child: Obx( child: Obx(
() => Container( () => Container(
foregroundDecoration: deco.value, foregroundDecoration: deco.value,

View File

@ -108,7 +108,7 @@ class _PeerTabPageState extends State<PeerTabPage>
Widget build(BuildContext context) { Widget build(BuildContext context) {
final model = Provider.of<PeerTabModel>(context); final model = Provider.of<PeerTabModel>(context);
Widget selectionWrap(Widget widget) { Widget selectionWrap(Widget widget) {
return model.multiSelectionMode ? createMultiSelectionBar() : widget; return model.multiSelectionMode ? createMultiSelectionBar(model) : widget;
} }
return Column( return Column(
@ -362,8 +362,7 @@ class _PeerTabPageState extends State<PeerTabPage>
.toList()); .toList());
} }
Widget createMultiSelectionBar() { Widget createMultiSelectionBar(PeerTabModel model) {
final model = Provider.of<PeerTabModel>(context);
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
@ -381,7 +380,7 @@ class _PeerTabPageState extends State<PeerTabPage>
Row( Row(
children: [ children: [
selectionCount(model.selectedPeers.length), selectionCount(model.selectedPeers.length),
selectAll(), selectAll(model),
closeSelection(), closeSelection(),
], ],
) )
@ -512,8 +511,7 @@ class _PeerTabPageState extends State<PeerTabPage>
); );
} }
Widget selectAll() { Widget selectAll(PeerTabModel model) {
final model = Provider.of<PeerTabModel>(context);
return Offstage( return Offstage(
offstage: offstage:
model.selectedPeers.length >= model.currentTabCachedPeers.length, model.selectedPeers.length >= model.currentTabCachedPeers.length,

View File

@ -167,6 +167,9 @@ class _PeersViewState extends State<_PeersView>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// We should avoid too many rebuilds. MacOS(m1, 14.6.1) on Flutter 3.19.6.
// Continious rebuilds of `ChangeNotifierProvider` will cause memory leak.
// Simple demo can reproduce this issue.
return ChangeNotifierProvider<Peers>( return ChangeNotifierProvider<Peers>(
create: (context) => widget.peers, create: (context) => widget.peers,
child: Consumer<Peers>(builder: (context, peers, child) { child: Consumer<Peers>(builder: (context, peers, child) {
@ -245,6 +248,9 @@ class _PeersViewState extends State<_PeersView>
: Container(child: visibilityChild); : Container(child: visibilityChild);
} }
// We should avoid too many rebuilds. Win10(Some machines) on Flutter 3.19.6.
// Continious rebuilds of `ListView.builder` will cause memory leak.
// Simple demo can reproduce this issue.
final Widget child = Obx(() => stateGlobal.isPortrait.isTrue final Widget child = Obx(() => stateGlobal.isPortrait.isTrue
? ListView.builder( ? ListView.builder(
itemCount: peers.length, itemCount: peers.length,

View File

@ -184,10 +184,17 @@ class PeerTabModel with ChangeNotifier {
notifyListeners(); notifyListeners();
} }
// `notifyListeners()` will cause many rebuilds.
// So, we need to reduce the calls to "notifyListeners()" only when necessary.
// A better way is to use a new model.
setCurrentTabCachedPeers(List<Peer> peers) { setCurrentTabCachedPeers(List<Peer> peers) {
Future.delayed(Duration.zero, () { Future.delayed(Duration.zero, () {
final isPreEmpty = _currentTabCachedPeers.isEmpty;
_currentTabCachedPeers = peers; _currentTabCachedPeers = peers;
notifyListeners(); final isNowEmpty = _currentTabCachedPeers.isEmpty;
if (isPreEmpty != isNowEmpty) {
notifyListeners();
}
}); });
} }