在 API 调用中使用 FutureBuilder 的无限循环

Man*_*el 7 flutter

我正在尝试使用 API 的结果填充我的 ListView。API 调用必须在从共享首选项中检索到值之后进行。但是,在执行时,我的 API 调用函数会运行一个无限循环,并且 UI 不会呈现。我通过调试语句跟踪了这种行为。

Future builder 构建 UI 时应该显示的圆形指示器也没有显示。

我该如何解决这个问题?

我的代码:



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,
     );
 }
}

Run Code Online (Sandbox Code Playgroud)

而不是被调用一次......我的 setData 函数被重复调用......我该如何解决这个......请帮忙

Gun*_*han 14

Future在每次重建小部件时都在创建对象。并且由于您在方法setState内部调用setData,因此它会递归地触发重建。

要解决此问题,您必须保留对Future对象的引用。并使用该参考FutureBuilder然后它可以理解它是以前使用的。

例如:

Future<List<Task>> _tasks;
@override
  void initState() {
    _tasks = getAllTasks();
    super.initState();
  }
Run Code Online (Sandbox Code Playgroud)

在你的小部件树中,像这样使用它:

Expanded(
          child: FutureBuilder(
              future: _tasks,
              initialData: [],
              builder: (context, snapshot) {
                return createTasksListView(context, snapshot);
              }),
        ),
Run Code Online (Sandbox Code Playgroud)