FlutterのStreamBuilderでローディングしているかどうかを補足したい
現在Flutterの勉強としてStreamBuilderを使用して簡単なRSSリーダーを作成しています。
StreamBuilderを使用してRSSフィードを取得(http.getによって取得)してリスト表示するところまではできました。
また、画面をオーバースクロールすることで新しいフィードを取得してリストに追加することもできました。
しかし、オーバースクロールして新しいフィードを取得している時にローディング画面を出すことができずにいます。具体的には、オーバースクロールすることで新しいフィードの取得は開始されますが、このフィードの取得状態(取得処理中なのか、取得処理完了なのか)をどのようにして補足できるのかがわかりません。
当初はconnectionStateがwaitingであるかどうかで補足できると考えておりましたが、
connectionStateは常にactive状態になっており、思う動作を実現できませんでした。
Flutter、Streamについて理解が不足している部分が多々あるため、質問自体が不明瞭かもしれませんが、何かしらヒントや解決策、読むべきドキュメント等あればご教示頂きたいです。
よろしくお願いします。
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:./entry_model.dart';
class EntryList extends StatefulWidget {
@override
_EntryListState createState() => _EntryListState();
}
class _EntryListState extends State<EntryList>
with
AutomaticKeepAliveClientMixin<EntryList> {
EntriesModel entriesModel;
StreamController _itemsController;
final GlobalKey<ScaffoldState> scaffoldkey = new GlobalKey<ScaffoldState>();
final formatter = DateFormat('yyyy/MM/dd(E) HH:mm', 'ja_JP');
Future fetchEntries() async {
final response = await entriesModel.getEntries();
return response;
}
Future fetchNewEntries() async {
final response = await entriesModel.getNewEntries();
return response;
}
loadEntries() async {
fetchEntries().then((res) async {
_itemsController.add(res);
return res;
});
}
loadNewEntries() async {
fetchNewEntries().then((res) async {
_itemsController.add(res);
return res;
});
}
@override
bool get wantKeepAlive => true;
@override
void initState() {
entriesModel = EntriesModel();
_itemsController = StreamController();
loadEntries();
super.initState();
}
@override
void dispose() {
_itemsController.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
var numberOfItem = 0;
return Scaffold(
key: scaffoldkey,
backgroundColor: Colors.white,
body: Column(
children: <Widget>[
Expanded(
flex: 1,
child: // オーバースクロールで新しいフィードを取得中にここでローディング中であるメッセージを表示したい。,
),
Expanded(
flex: 20,
child: StreamBuilder(
stream: _itemsController.stream,
builder: (context, snapshot) {
if (snapshot.hasData) {
numberOfItem = snapshot.data.length as int;
return numberOfItem == 0
? Center(child: const Text('Empty'))
: RefreshIndicator(
onRefresh: () => _onRefresh(),
child: ListView.builder(
itemCount: snapshot.data == null
? 0
: numberOfItem,
itemBuilder: (context, index) {
final item = snapshot.data[index] as Entry;
return _buildCard(item, index, context)
})
);
} else {
return const Text('No data');
}
},
),
)
],
),
);
}
Future<void> _onRefresh() async {
await loadNewEntries();
}
}
Card _buildCard(Entry item, int index, BuildContext context) {
return Card( // 各フィードをCard形式で表示
);
}
上記のコード内のEntriesModelがフィードを扱うモデルで、getEntries()でSQLiteに保存しているフィードを読み込んで、getNewEntries()でhttp.getを使って新しいフィードを読み込んでいます。