通过API调用使用FutureBuilder的无限循环 [英] Infinite loop on using FutureBuilder with API call
问题描述
我试图用API的结果填充ListView.从共享首选项中检索值之后,必须进行API调用.但是在执行时,我的API调用函数会运行无限循环,并且UI不会呈现.我通过调试语句跟踪了此行为.
I am trying to populate my ListView with the result from an API. The API call must take place after the values have been retrieved from Shared Preference. However on execution my function for API call runs an infinite loop and the UI doesn't render. I tracked this behaviour through debug statements.
未来"构建器构建UI时应显示的圆形指示器也未显示.
The circular indicator that should be shown when Future builder is building UI is also not showing.
我该如何解决?
我的代码:
class _MyHomePageState extends State<MyHomePage>{
@override MyHomePage get widget => super.widget;
String userID = "";
String authID = "";
//Retrieving values from Shared Preferences
Future<List<String>> loadData() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
List<String> l= new List<String>();
if(prefs.getString("ID") == null){
l.add("null");
}
else{
l.add(prefs.getString("ID"));
}
if(prefs.getString("authID") == null){
l.add("null");
}
else{
l.add(prefs.getString("authID"));
}
return l;
}
//Setting values retrieved from Shared Pref
setData() async{
await loadData().then((value) {
setState(() {
userID = value[0];
print('the user ID is' + userID);
authID = value[1];
print('the authID is' + authID);
});
// getAllTasks(userID, authID);
});
print("Set data execution completed ");
}
//FUNCTION to use values from Shared Pref and make API Call
Future<List<Task>> getAllTasks() async{
await setData();
//Waiting for Set Data to complete
print('Ive have retrived the values ' + userID + authID );
List<Task> taskList;
await getTasks(userID, authID, "for_me").then((value){
final json = value;
if(json!="Error"){
Tasks tasks = tasksFromJson(json); //of Class Tasks
taskList = tasks.tasks; //getting the list of tasks from class
}
});
if(taskList != null) return taskList;
else {
print('Tasklist was null ');
throw new Exception('Failed to load data ');
}
}
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context){
_signedOut(){
widget.onSignedOut();
}
//To CREATE LIST VIEW
Widget createTasksListView(BuildContext context, AsyncSnapshot snapshot) {
var values = snapshot.data;
return ListView.builder(
itemCount: values == null ? 0 : values.length,
itemBuilder: (BuildContext context, int index) {
return values.isNotEmpty ? Ink(....
) : CircularProgressIndicator();
},
);
}
//MY COLUMN VIEW
Column cardsView = Column(
children: <Widget>[
....
Expanded(
child: FutureBuilder(
future: getAllTasks(),
initialData: [],
builder: (context, snapshot) {
return createTasksListView(context, snapshot);
}),
),
],
);
return Scaffold(
body: cardsView,
);
}
}
而不是一次被调用...我的setData函数被重复调用..我该如何解决..请帮助
Instead of being called once... my setData function is being called repeatedly.. How can I resolve this..please help
推荐答案
您将在每次重新构建小部件时创建Future
对象.而且,由于您要在setData
方法内调用setState
,因此它将以递归方式触发重建.
You're creating Future
object on every rebuild of the widget. And since you're calling setState
inside your setData
method, it triggers a rebuild recursively.
要解决此问题,您必须保留对Future
对象的引用.并将该引用用于FutureBuilder
,则它可以理解它是以前使用过的.
To solve this problem you have to keep a reference to the Future
object. And use that reference for the FutureBuilder
then it can understand that it is the previously used one.
例如:
Future<List<Task>> _tasks;
@override
void initState() {
_tasks = getAllTasks();
super.initState();
}
然后在小部件树中像这样使用它:
And in your widget tree use it like that:
Expanded(
child: FutureBuilder(
future: _tasks,
initialData: [],
builder: (context, snapshot) {
return createTasksListView(context, snapshot);
}),
),
这篇关于通过API调用使用FutureBuilder的无限循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!