Ramón, miembro de nuestro staff, nos ha hecho el favor de crear esta sección ya que conoce perfectamente el tema.
Solución:
Ejemplo básico
A continuación se muestra una clase de estado de StatefulWidget, donde:
- a
ListView
está envuelto en unRefreshIndicator
words
variable de estado es su fuente de datos
onRefresh
llamadas_pullRefresh
función para actualizar ListView_pullRefresh
es una función asíncrona, que no devuelve nada (unaFuture
)- Cuándo
_pullRefresh
Se completa la solicitud de datos de ejecución prolongada,words
la variable miembro/estado se actualiza en unsetState()
llamar a reconstruirListView
para mostrar nuevos datos
import 'package:english_words/english_words.dart';
class _PullToRefreshPageState extends State
List words = generateWordPairs().take(5).toList();
@override
Widget build(BuildContext context)
return RefreshIndicator(
onRefresh: _pullRefresh,
child: ListView.builder(
itemCount: words.length,
itemBuilder: (context, index)
return ListTile(
title: Text(words[index].asPascalCase),
);
,),
);
Future _pullRefresh() async
List freshWords = await WordDataSource().getFutureWords(delay: 2);
setState(()
words = freshWords;
);
// why use freshWords var? https://stackoverflow.com/a/52992836/2301224
class WordDataSource
Future> getFutureWords(int size = 5, int delay = 5) async
await Future.delayed(Duration(seconds: delay));
return generateWordPairs().take(5).toList();
notas
- Si tu asíncrono
onRefresh
función se completa muy rápidamente, es posible que desee agregar unawait Future.delayed(Duration(seconds: 2));
después, solo para que la UX sea más agradable. - Esto le da tiempo al usuario para completar un gesto de deslizar/desplegar hacia abajo y para que el indicador de actualización se muestre/anime/gire indicando que se han obtenido los datos.
Ejemplo de FutureBuilder
Aquí hay otro ejemplo, usando un FutureBuilder, que es común cuando se obtienen datos de una base de datos o una fuente HTTP.
class _PullToRefreshFuturePageState extends State
Future> futureWords;
@override
void initState()
super.initState();
futureWords = WordDataSource().getFutureWords(delay: 2);
@override
Widget build(BuildContext context)
return FutureBuilder>(
//initialData: [],
future: futureWords,
builder: (context, snapshot)
return RefreshIndicator(
child: _listView(snapshot),
onRefresh: _pullRefresh,
);
,
);
Widget _listView(AsyncSnapshot snapshot)
if (snapshot.hasData)
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index)
return ListTile(
title: Text(snapshot.data[index].asPascalCase),
);
,);
else
return Center(
child: Text('Loading data...'),
);
Future _pullRefresh() async
List freshFutureWords = await WordDataSource().getFutureWords(delay: 2);
setState(()
futureWords = Future.value(freshFutureWords);
);
notas
getFutureWords()
La función es la misma que en el Ejemplo básico arriba, pero los datos están envueltos en unFuture.value()
ya que FutureBuilder espera unFuture
- según Rémi, Collin y otros semidioses de Dart/Flutter, es una buena práctica actualizar las variables de miembro de Stateful Widget en el interior
setState()
(futureWords
en el ejemplo de FutureBuilder &words
en el ejemplo básico), después sus funciones de obtención de datos asincrónicos de larga ejecución se han completado.- https://stackoverflow.com/a/52992836/2301224
- si intentas hacer setState
async
obtendrás una excepción - actualizando variables miembro fuera de
setState
y tener un vacíosetState
cierre, puede dar lugar a advertencias de análisis de códigos/bofetadas en el futuro
No estoy seguro acerca de los futuros, pero para el indicador de actualización debe devolver un void así que usa algo como
RefreshIndicator(
onRefresh: () async
await getData().then((lA)
if (lA is Future)
setState(()
reportList = lA;
);
return;
else
setState(()
//error
);
return;
);
return;
,
¡Intenta eso y dejame saber!
EDITAR:
Bueno, entonces prueba esto dentro de tu método de actualización
setState(()
reportList = getReport();
);
return reportList;
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)