i have RefreshIndicator
and inside it ListView
so that RefreshIndicator
work swipe down gesture on ListView
, also i have set GlobalKey<RefreshIndicatorState>()
to RefreshIndicator
so that i can show indicator on button tap.
all is wokring but in _onRefresh
i am calling showSnackBar
but snakbar showing twice i dont know why
final _refreshIndicatorKey = GlobalKey<RefreshIndicatorState>();
@override
Widget build(BuildContext context) {
return RefreshIndicator(
key: _refreshIndicatorKey,
onRefresh: _onRefresh,
child: buidlListView(snapshot),
);
}
Widget buidlListView(AsyncSnapshot<List<Model>> snapshot) {
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
return buildModelList(snapshot);
}
return buildNoModelList();
}
Widget buildNoModelList() {
return ListView(
children: [
ElevatedButton(
onPressed: _onRefresh,
child: const SizedBox(
width: double.infinity,
child: Text('Refresh', textAlign: TextAlign.center),
),
],
);
}
Widget buildModelList(
AsyncSnapshot<List<Model>> snapshot,
) {
final modelList = snapshot.data!;
return ListView.separated(
padding: const EdgeInsets.all(16),
itemCount: modelList.length,
separatorBuilder: (context, index) => const SizedBox(height: 16),
itemBuilder: (context, index) {
final model = modelList[index];
return ModelCard(
key: ValueKey(model),
model: model,
);
},
);
}
Future<void> _onRefresh() async {
// ignore: unawaited_futures
_refreshIndicatorKey.currentState?.show();
final isModelExist = await loadModels();
// not returning this because i want to show snack bar after indicator hides
Future<void>.delayed(const Duration(seconds: 3));
if (!isModelExist) {
showSnackBar();
}
return Future.value();
}
void showSnackBar() {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
behavior: SnackBarBehavior.floating,
content: Text('No Model Found'),
),
);
}
Future<bool> loadModels() async {
final snapshot = await modelCollectionRef().get();
if (snapshot.size > 0) {
//...
return true;
}
return false;
}
CodePudding user response:
Please refer to below example
I have used below mentioned plugin for refresh indicator
pull_to_refresh: ^2.0.0
import 'package:flutter/material.dart';
import 'package:flutter_app_modal_sheet/ProviderModel/ProviderCNModel.dart';
import 'package:provider/provider.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
void main() {
runApp(
MyApp(),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
/*Controllers*/
final RefreshController _refreshController =
RefreshController(initialRefresh: false);
@override
void initState() {
super.initState();
}
@override
void dispose() {
_refreshController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: SmartRefresher(
controller: _refreshController,
enablePullDown: true,
header: MaterialClassicHeader(),
onRefresh: () async {
await Future.delayed(const Duration(seconds: 3), () {});
_refreshController.refreshCompleted();
showSnackBar();
},
child: ListView.builder(
itemCount: 100,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: Text("Index Value: $index"),
);
},
),
),
);
}
void showSnackBar() {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
behavior: SnackBarBehavior.floating,
content: Text('No Model Found'),
),
);
}
}
CodePudding user response:
Solved the problem in is _refreshIndicatorKey.currentState?.show();
which i was calling on _onRefresh()
and using this method this on button tap so when its first trigger ths refresh process but then in _onRefresh()
we are calling _refreshIndicatorKey.currentState?.show();
which tell RefreshIndicator
run call back onRefresh
which also refrenced to _onRefresh()
so thats why _onRefresh()
triggred two times and snakcbar showed two times so to solve this i just call _refreshIndicatorKey.currentState?.show();
on button tap and then RefreshIndicator
it self run _onRefresh()
callback.
Widget buildNoModelList() {
return ListView(
children: [
ElevatedButton(
onPressed: () {
_refreshIndicatorKey.currentState?.show();
},
child: const SizedBox(
width: double.infinity,
child: Text('Refresh', textAlign: TextAlign.center),
),
],
);
}
Future<void> _onRefresh() async {
final isModelExist = await loadModels();
// not returning this because i want to show snackbar after indicator hides
await Future<void>.delayed(const Duration(seconds: 3));
if (!isModelExist) {
showSnackBar();
}
return;
}