当用户向上滚动listview时,我正在尝试实现更多加载功能。我正在使用BloC模式,并且正在尝试使用通知侦听器。
我有以下代码:
home.dart
import 'package:flutter/material.dart';
import '../models/news_model.dart';
import '../blocs/news_bloc.dart';
import '../utils/helpers.dart';
import '../utils/constants.dart';
import 'package:html_unescape/html_unescape.dart';
import 'package:flutter_web_browser/flutter_web_browser.dart';
import 'package:intl/intl.dart';
class Home extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return HomeState();
}
}
class HomeState extends State<Home> {
ItemLoadMoreStatus loadMoreStatus = ItemLoadMoreStatus.STABLE;
int currentPageNumber = 0;
List news = new List();
final ScrollController scrollController = new ScrollController();
@override
void initState() {
super.initState();
bloc.fetchHomeNews(currentPageNumber);
}
@override
void dispose() {
bloc.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xfff0f0f0),
appBar: AppBar(
title: Text('Home'),
),
body: StreamBuilder(
stream: bloc.allHomeNews,
builder: (context, AsyncSnapshot<NewsModel> snapshot) {
if (snapshot.hasData) {
return buildList(snapshot);
} else if (snapshot.hasError) {
return Text(snapshot.error.toString());
}
return Center(child: CircularProgressIndicator());
},
),
);
}
Widget buildList(AsyncSnapshot<NewsModel> snapshot) {
news = snapshot.data.results;
var unescape = new HtmlUnescape();
return NotificationListener(
onNotification: onNotification,
child: new ListView.builder(
itemCount: news.length,
padding: new EdgeInsets.only(top: 5.0),
controller: scrollController,
itemBuilder: (context, index) {
return Card(
margin: new EdgeInsets.all(5.0),
child: ListTile(
isThreeLine: true,
leading: CircleAvatar(
backgroundColor: Color(0xfff0f0f0),
foregroundColor: Constants.primaryColor,
child: const Icon(Constants.iconHome),
),
title: Text(
unescape.convert(news[index].title),
style: TextStyle(fontSize: 14.0 ,fontWeight: FontWeight.w500, color: Color(0xff333333))
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text(
Helpers.truncateString(unescape.convert(news[index].summary), 100),
style: TextStyle(fontSize:13.0, color: Color(0xff333333)),
),
Container(
padding: EdgeInsets.only(top: 5.0),
child: Text(
'Published on: '+DateFormat("yyyy-MM-dd kk:mm").format(DateTime.parse(news[index].published)),
style: TextStyle(fontSize: 11.0, color: Color(0xff777777)),
textAlign: TextAlign.left,
),
),
],
),
onTap: () {
FlutterWebBrowser.openWebPage(url: news[index].link, androidToolbarColor: Constants.primaryColor);
},
),
);
}),
);
}
bool onNotification(ScrollNotification notification) {
if (notification is ScrollUpdateNotification) {
if (scrollController.position.maxScrollExtent > scrollController.offset &&
scrollController.position.maxScrollExtent - scrollController.offset <=
50) {
if (loadMoreStatus != null &&
loadMoreStatus == ItemLoadMoreStatus.STABLE) {
//print("UPDATE LIST ON NOTIFICATION");
loadMoreStatus = ItemLoadMoreStatus.LOADING;
var newPage = currentPageNumber+1;
currentPageNumber = newPage;
setState(() {
news.addAll(bloc.fetchHomeNews(newPage));
});
}
}
}
return true;
}
}
Bloc文件 news_bloc.dart
import '../resources/repository.dart';
import 'package:rxdart/rxdart.dart';
import '../models/news_model.dart';
//import '../models/home_model.dart';
class NewsBloc {
final _repository = Repository();
final _newsFetcher = PublishSubject<NewsModel>();
final _homeFetcher = PublishSubject<NewsModel>();
final _appFetcher = PublishSubject<NewsModel>();
final _reviewsFetcher = PublishSubject<NewsModel>();
Observable<NewsModel> get allNews => _newsFetcher.stream;
Observable<NewsModel> get allAppNews => _appFetcher.stream;
Observable<NewsModel> get allReviews => _reviewsFetcher.stream;
Observable<NewsModel> get allHomeNews => _homeFetcher.stream;
fetchAllNews() async {
NewsModel newsModel = await _repository.fetchAllNews();
_newsFetcher.sink.add(newsModel);
}
fetchHomeNews(pageNumber) async {
NewsModel newsModel = await _repository.fetchHomeNews(pageNumber);
_homeFetcher.sink.add(newsModel);
}
fetchAppNews() async {
NewsModel newsModel = await _repository.fetchAppNews();
_appFetcher.sink.add(newsModel);
}
fetchReviews() async {
NewsModel newsModel = await _repository.fetchReviews();
_reviewsFetcher.sink.add(newsModel);
}
dispose() {
_newsFetcher.close();
_homeFetcher.close();
_appFetcher.close();
_reviewsFetcher.close();
}
}
final bloc = NewsBloc();
和新闻模型 news_model.dart
import '../utils/helpers.dart';
class NewsModel{
List<_Result> _results = [];
NewsModel.fromJson(feed) {
List<_Result> temp = [];
for (int i = 0; i < feed.length; i++) {
_Result result = _Result(feed[i]);
temp.add(result);
}
_results = temp;
}
List<_Result> get results => _results;
}
class _Result {
String _title;
String _link;
String _published;
String _summary;
_Result(result) {
_title = result.title;
_link = result.id;
_published = result.published;
_summary = Helpers.removeAllHtmlTags(result.summary);
}
String get published => _published;
String get title => _title;
String get link => _link;
String get summary => _summary;
}
问题
不幸的是,这似乎不起作用。有人可以帮我解决我做错的地方吗?
更新
如何使用NotificationListener
来做到这一点?
答案 0 :(得分:0)
我认为您需要将ScrollController放在initState()中。
例如,这就是我所拥有的,并且有效:
@override
void initState() {
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
getMoreData();
}
});
super.initState();
}