Reputation: 51
Hope Well,
I am using firebase realtime database on my flutter app (similar social media app). i have feed page and feed state page. i wanna show 10 posts first and after scroll bottom, load again 10 posts. i tried some methods but not working.
my codes
feed page code
Widget build(BuildContext context) {
var authstate = Provider.of<AuthState>(context, listen: false);
return Consumer<FeedState>(
builder: (context, state, child) {
final List<FeedModel> list = state.getPostList(authstate.userModel);
return CustomScrollView(
slivers: <Widget>[
child,
state.isBusy && list == null
? SliverToBoxAdapter(
child: Container(
height: fullHeight(context) - 135,
child: CustomScreenLoader(
height: double.infinity,
width: fullWidth(context),
backgroundColor: Colors.white,
),
),
)
: !state.isBusy && list == null
? SliverToBoxAdapter(
child: EmptyList(
'Follow someone',
subTitle:
'goto search page to find & follow Someone.\n When they added new post,\n they\'ll show up here.',
),
)
: SliverList(
delegate: SliverChildListDelegate(
list.map(
(model) {
return Container(
color: Colors.white,
child: Post(
model: model,
trailing: PostBottomSheet().PostOptionIcon(
context,
model: model,
type: PostType.Post,
scaffoldKey: scaffoldKey),
),
);
},
).toList(),
),
)
],
);
},
feed state code
List<FeedModel> get feedlist {
if (_feedlist == null) {
return null;
} else {
return List.from(_feedlist.reversed);
}
}
List<FeedModel> getPosttList(UserModel userModel) {
if (userModel == null) {
return null;
}
return feedlist;
}
Upvotes: 0
Views: 779
Reputation: 2229
I modified your code and use a ScrollController
to load more data when the user reaches the end of the loaded data. (The data provider is hard-coded but you should be able to relate it to your scenario.) Note that I changed your code to use SliverChildBuilderDelegate
which is more efficient.
import 'package:flutter/material.dart';
class ScrollTest extends StatefulWidget {
@override
_ScrollTestState createState() => _ScrollTestState();
}
class _ScrollTestState extends State<ScrollTest> {
bool isLoading = false;
bool isEnd = false;
final List<FeedModel> list = [];
ScrollController _controller;
_scrollListener() async {
var position = _controller.offset /
(_controller.position.maxScrollExtent -
_controller.position.minScrollExtent);
if (position > 0.5 && !_controller.position.outOfRange) {
await _getMoreData(list.length);
}
}
@override
void initState() {
super.initState();
_controller = ScrollController();
_controller.addListener(_scrollListener);
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
_getMoreData(list.length);
}
Future<void> _getMoreData(int index) async {
if (!isLoading) {
setState(() {
isLoading = true;
});
var tlist = await Feed.getPostList(index);
setState(() {
if (tlist.length == 0) {
isEnd = true;
} else {
list.addAll(tlist);
index = list.length;
}
isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
return CustomScrollView(
controller: _controller,
slivers: <Widget>[
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
color: Colors.white,
height: 300,
child: Text(list[index].text),
);
},
childCount: list.length,
),
),
SliverFillRemaining(
child: Center(
child: isEnd ? Text('End') : CircularProgressIndicator(),
)),
],
);
}
}
// Dummy FeedModel
class FeedModel {
final String text;
FeedModel(this.text);
}
// Dummy Feed provider
class Feed {
static final data = [
FeedModel('1'),FeedModel('2'),FeedModel('3'),FeedModel('4'),
FeedModel('5'),FeedModel('6'),FeedModel('7'),FeedModel('8'),
FeedModel('9'),FeedModel('10'),FeedModel('11'),FeedModel('12'),
FeedModel('13'),
];
static Future<List<FeedModel>> getPostList(int index) async {
List<FeedModel> l = [];
for (var i = index; i < index + 5 && i < data.length; i++) {
l.add(data[i]);
}
await Future.delayed(Duration(seconds: 1));
return l;
}
}
Upvotes: 1