[UserListView] Use LazyLoadScrollView for pagination rather than listening scroll controller

This commit is contained in:
xsahil03x
2020-11-24 21:45:42 +05:30
parent a0afe4d091
commit 2ee8b72a31
2 changed files with 119 additions and 48 deletions
+81
View File
@@ -0,0 +1,81 @@
import 'package:flutter/widgets.dart';
enum LoadingStatus { LOADING, STABLE }
/// Signature for EndOfPageListeners
typedef EndOfPageListenerCallback = void Function();
/// A widget that wraps a [Widget] and will trigger [onEndOfPage] when it
/// reaches the bottom of the list
class LazyLoadScrollView extends StatefulWidget {
/// The [Widget] that this widget watches for changes on
final Widget child;
/// Called when the [child] reaches the end of the list
final EndOfPageListenerCallback onEndOfPage;
/// The offset to take into account when triggering [onEndOfPage] in pixels
final int scrollOffset;
/// Used to determine if loading of new data has finished. You should use set this if you aren't using a FutureBuilder or StreamBuilder
final bool isLoading;
LazyLoadScrollView({
Key key,
@required this.child,
@required this.onEndOfPage,
this.isLoading = false,
this.scrollOffset = 100,
}) : assert(onEndOfPage != null),
assert(child != null),
super(key: key);
@override
State<StatefulWidget> createState() => _LazyLoadScrollViewState();
}
class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
LoadingStatus _loadMoreStatus = LoadingStatus.STABLE;
@override
void didUpdateWidget(LazyLoadScrollView oldWidget) {
super.didUpdateWidget(oldWidget);
if (!widget.isLoading) {
_loadMoreStatus = LoadingStatus.STABLE;
}
}
@override
Widget build(BuildContext context) {
return NotificationListener(
child: widget.child,
onNotification: _onNotification,
);
}
bool _onNotification(Notification notification) {
if (notification is ScrollUpdateNotification) {
if (notification.metrics.maxScrollExtent > notification.metrics.pixels &&
notification.metrics.maxScrollExtent - notification.metrics.pixels <=
widget.scrollOffset) {
if (_loadMoreStatus != null &&
_loadMoreStatus == LoadingStatus.STABLE) {
_loadMoreStatus = LoadingStatus.LOADING;
widget.onEndOfPage();
}
}
return true;
}
if (notification is OverscrollNotification) {
if (notification.overscroll > 0) {
if (_loadMoreStatus != null &&
_loadMoreStatus == LoadingStatus.STABLE) {
_loadMoreStatus = LoadingStatus.LOADING;
widget.onEndOfPage();
}
}
return true;
}
return false;
}
}
+11 -21
View File
@@ -2,6 +2,7 @@ import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:stream_chat/stream_chat.dart'; import 'package:stream_chat/stream_chat.dart';
import 'package:stream_chat_flutter/src/lazy_load_scroll_view.dart';
import 'package:stream_chat_flutter/src/users_bloc.dart'; import 'package:stream_chat_flutter/src/users_bloc.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart';
@@ -144,8 +145,6 @@ class UserListView extends StatefulWidget {
class _UserListViewState extends State<UserListView> class _UserListViewState extends State<UserListView>
with WidgetsBindingObserver { with WidgetsBindingObserver {
final ScrollController _scrollController = ScrollController();
bool get _isListView => widget.crossAxisCount == 1; bool get _isListView => widget.crossAxisCount == 1;
@override @override
@@ -158,14 +157,6 @@ class _UserListViewState extends State<UserListView>
pagination: widget.pagination, pagination: widget.pagination,
options: widget.options, options: widget.options,
); );
_scrollController.addListener(() {
usersBloc.queryUsersLoading.first.then((loading) {
if (!loading) {
_listenUserPagination(usersBloc);
}
});
});
} }
@override @override
@@ -327,10 +318,10 @@ class _UserListViewState extends State<UserListView>
); );
} }
if (_isListView) { final child = _isListView
return ListView.separated( ? ListView.separated(
physics: AlwaysScrollableScrollPhysics(), physics: AlwaysScrollableScrollPhysics(),
controller: _scrollController, // controller: _scrollController,
itemCount: items.isNotEmpty ? items.length + 1 : items.length, itemCount: items.isNotEmpty ? items.length + 1 : items.length,
separatorBuilder: (_, index) { separatorBuilder: (_, index) {
if (widget.separatorBuilder != null) { if (widget.separatorBuilder != null) {
@@ -341,19 +332,22 @@ class _UserListViewState extends State<UserListView>
itemBuilder: (context, index) { itemBuilder: (context, index) {
return _listItemBuilder(context, index, items); return _listItemBuilder(context, index, items);
}, },
); )
} : GridView.builder(
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: widget.crossAxisCount, crossAxisCount: widget.crossAxisCount,
), ),
itemCount: items.isNotEmpty ? items.length + 1 : items.length, itemCount: items.isNotEmpty ? items.length + 1 : items.length,
physics: AlwaysScrollableScrollPhysics(), physics: AlwaysScrollableScrollPhysics(),
controller: _scrollController,
itemBuilder: (context, index) { itemBuilder: (context, index) {
return _gridItemBuilder(context, index, items); return _gridItemBuilder(context, index, items);
}, },
); );
return LazyLoadScrollView(
onEndOfPage: () => _listenUserPagination(usersBlocState),
child: child,
);
}, },
); );
} }
@@ -488,9 +482,6 @@ class _UserListViewState extends State<UserListView>
} }
void _listenUserPagination(UsersBlocState usersProvider) { void _listenUserPagination(UsersBlocState usersProvider) {
if (_scrollController.position.maxScrollExtent ==
_scrollController.offset &&
_scrollController.offset != 0) {
usersProvider.queryUsers( usersProvider.queryUsers(
filter: widget.filter, filter: widget.filter,
sort: widget.sort, sort: widget.sort,
@@ -500,7 +491,6 @@ class _UserListViewState extends State<UserListView>
options: widget.options, options: widget.options,
); );
} }
}
@override @override
void didUpdateWidget(UserListView oldWidget) { void didUpdateWidget(UserListView oldWidget) {