added a controller and more robust behavior

This commit is contained in:
shilangyu 2020-09-18 23:24:58 +02:00
parent 60dcf07001
commit 0fb53e3314
2 changed files with 39 additions and 6 deletions

View File

@ -0,0 +1,6 @@
import 'package:flutter_hooks/flutter_hooks.dart';
import '../widgets/infinite_scroll.dart';
InfiniteScrollController useInfiniteScrollController() =>
useMemoized(() => InfiniteScrollController());

View File

@ -3,11 +3,27 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import '../hooks/ref.dart';
class InfiniteScrollController {
Function() clear;
InfiniteScrollController() {
usedBeforeCreation() => throw Exception(
'Tried to use $runtimeType before it being initialized');
clear = usedBeforeCreation;
}
void dispose() {
clear = null;
}
}
class InfiniteScroll<T> extends HookWidget {
final int batchSize;
final Widget loadingWidget;
final Widget Function(T data) builder;
final Future<List<T>> Function(int page, int batchSize) fetchMore;
final InfiniteScrollController controller;
InfiniteScroll({
this.batchSize = 10,
@ -15,16 +31,28 @@ class InfiniteScroll<T> extends HookWidget {
const ListTile(title: Center(child: CircularProgressIndicator())),
this.builder,
this.fetchMore,
this.controller,
}) : assert(builder != null),
assert(fetchMore != null);
assert(fetchMore != null),
assert(batchSize > 0);
@override
Widget build(BuildContext context) {
final page = useState(1);
final data = useState<List<T>>([]);
final hasMore = useRef(true);
final isFetching = useRef(false);
useEffect(() {
if (controller != null) {
controller.clear = () => data.value = [];
return controller.dispose;
}
return null;
}, []);
final page = data.value.length ~/ batchSize + 1;
return ListView.builder(
// +1 for the loading widget
itemCount: data.value.length + 1,
@ -39,14 +67,13 @@ class InfiniteScroll<T> extends HookWidget {
// if it's already fetching more, skip
if (!isFetching.current) {
isFetching.current = true;
fetchMore(page.value, batchSize).then((value) {
fetchMore(page, batchSize).then((newData) {
// if got less than the batchSize, mark the list as done
if (value.length < batchSize) {
if (newData.length < batchSize) {
hasMore.current = false;
}
// append new data and increment page count
data.value.addAll(value);
page.value++;
data.value = [...data.value, ...newData];
}).whenComplete(() => isFetching.current = false);
}