通过API调用使用FutureBuilder的无限循环 [英] Infinite loop on using FutureBuilder with API call

查看:223
本文介绍了通过API调用使用FutureBuilder的无限循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆