From 77be0b6189b0072d24c9711d6de3291a991b0691 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Fri, 17 Jan 2020 23:42:11 +0900 Subject: [PATCH] info: keep alive info page (by metadata sliver) but only fetch metadata when necessary --- lib/widgets/fullscreen/fullscreen_page.dart | 13 ++++++- lib/widgets/fullscreen/info/info_page.dart | 8 +++- .../fullscreen/info/metadata_section.dart | 39 +++++++++++++++++-- 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/lib/widgets/fullscreen/fullscreen_page.dart b/lib/widgets/fullscreen/fullscreen_page.dart index 680c6b113..5e29bed43 100644 --- a/lib/widgets/fullscreen/fullscreen_page.dart +++ b/lib/widgets/fullscreen/fullscreen_page.dart @@ -299,6 +299,7 @@ class FullscreenVerticalPageView extends StatefulWidget { class _FullscreenVerticalPageViewState extends State { bool _isInitialScale = true; ValueNotifier _backgroundColorNotifier = ValueNotifier(Colors.black); + ValueNotifier _infoPageVisibleNotifier = ValueNotifier(false); @override void initState() { @@ -343,8 +344,12 @@ class _FullscreenVerticalPageViewState extends State scrollDirection: Axis.vertical, controller: widget.verticalPager, physics: _isInitialScale ? const PageScrollPhysics() : const NeverScrollableScrollPhysics(), - onPageChanged: widget.onVerticalPageChanged, + onPageChanged: (page) { + widget.onVerticalPageChanged(page); + _infoPageVisibleNotifier.value = page == FullscreenBodyState.infoPage; + }, children: [ + // fake page for opacity transition between collection and fullscreen views const SizedBox(), ImagePage( collection: widget.collection, @@ -359,7 +364,11 @@ class _FullscreenVerticalPageViewState extends State if (notification is BackUpNotification) widget.onImagePageRequested(); return false; }, - child: InfoPage(collection: widget.collection, entry: widget.entry), + child: InfoPage( + collection: widget.collection, + entry: widget.entry, + visibleNotifier: _infoPageVisibleNotifier, + ), ), ], ), diff --git a/lib/widgets/fullscreen/info/info_page.dart b/lib/widgets/fullscreen/info/info_page.dart index 6aaf2f8f6..4aa4ecc55 100644 --- a/lib/widgets/fullscreen/info/info_page.dart +++ b/lib/widgets/fullscreen/info/info_page.dart @@ -14,11 +14,13 @@ import 'package:tuple/tuple.dart'; class InfoPage extends StatefulWidget { final ImageCollection collection; final ImageEntry entry; + final ValueNotifier visibleNotifier; const InfoPage({ Key key, @required this.collection, @required this.entry, + this.visibleNotifier, }) : super(key: key); @override @@ -97,7 +99,11 @@ class InfoPageState extends State { ), SliverPadding( padding: horizontalPadding, - sliver: MetadataSectionSliver(entry: entry, columnCount: split ? 2 : 1), + sliver: MetadataSectionSliver( + entry: entry, + columnCount: split ? 2 : 1, + visibleNotifier: widget.visibleNotifier, + ), ), SliverPadding( padding: EdgeInsets.only(bottom: 8 + mqViewInsetsBottom), diff --git a/lib/widgets/fullscreen/info/metadata_section.dart b/lib/widgets/fullscreen/info/metadata_section.dart index 5d3fdf2cd..21b93206f 100644 --- a/lib/widgets/fullscreen/info/metadata_section.dart +++ b/lib/widgets/fullscreen/info/metadata_section.dart @@ -10,34 +10,56 @@ import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; class MetadataSectionSliver extends StatefulWidget { final ImageEntry entry; final int columnCount; + final ValueNotifier visibleNotifier; const MetadataSectionSliver({ @required this.entry, @required this.columnCount, + this.visibleNotifier, }); @override State createState() => _MetadataSectionSliverState(); } -class _MetadataSectionSliverState extends State { +class _MetadataSectionSliverState extends State with AutomaticKeepAliveClientMixin { Map _metadata; + String _loadedMetadataUri; + + bool get isVisible => widget.visibleNotifier.value; @override void initState() { super.initState(); + _registerWidget(widget); _getMetadata(); } @override void didUpdateWidget(MetadataSectionSliver oldWidget) { super.didUpdateWidget(oldWidget); + _unregisterWidget(oldWidget); + _registerWidget(widget); _getMetadata(); } + @override + void dispose() { + _unregisterWidget(widget); + super.dispose(); + } + + void _registerWidget(MetadataSectionSliver widget) { + widget.visibleNotifier.addListener(_getMetadata); + } + + void _unregisterWidget(MetadataSectionSliver widget) { + widget.visibleNotifier.removeListener(_getMetadata); + } + @override Widget build(BuildContext context) { - debugPrint('$runtimeType build'); + super.build(context); final directoryNames = (_metadata?.keys?.toList() ?? [])..sort(); return SliverStaggeredGrid.countBuilder( crossAxisCount: widget.columnCount, @@ -57,10 +79,19 @@ class _MetadataSectionSliverState extends State { } Future _getMetadata() async { - debugPrint('$runtimeType _getMetadata'); - _metadata = await MetadataService.getAllMetadata(widget.entry); + if (_loadedMetadataUri == widget.entry.uri) return; + if (isVisible) { + _metadata = await MetadataService.getAllMetadata(widget.entry); + _loadedMetadataUri = widget.entry.uri; + } else { + _metadata = null; + _loadedMetadataUri = null; + } if (mounted) setState(() {}); } + + @override + bool get wantKeepAlive => true; } class _Directory extends StatelessWidget {