【问题标题】:FutureBuilder keep loadingFutureBuilder 继续加载
【发布时间】:2021-08-09 04:39:10
【问题描述】:

我的应用程序中到处都是FutureBuilders,问题是当打开页面时,屏幕上到处都会出现 CircularProgressIndicators,并且每当页面重建自身时,CircularProgressIndicators 就会再次显示。我想到了 2 个解决方案。

1- 在用户打开页面之前从 API 加载数据。 2- 在应用生命周期内加载一次数据。

我在article 的帮助下尝试了第二个,但没有用

ApiService.dart

  Future getUserData() async {
String token = await AuthProvider().getToken();
String userID = await AuthProvider().getUserId();

final response = await Dio().get(
  '$apiUrl/$userID',
  options: Options(headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'Authorization': 'Bearer $token',
  }),
);

if (response.statusCode == 200) {
  await Future.delayed(Duration(seconds: 5));
  return response.data;
} else {
  throw Exception('Failed to load data');
}
}

这就是我所说的

class Budget extends StatefulWidget {
final int budget;

Budget({@required this.budget});

@override
_BudgetState createState() => _BudgetState();
 }

class _BudgetState extends State<Budget> {
  Future<User> getUserData;
 ApiService apiService;
 SharedPreferences sharedPreferences;

@override
void initState() {
apiService = ApiService();
apiService.getUserData();
super.initState();
}

 @override
 Widget build(BuildContext context) {
return LayoutBuilder(
  builder: (context, constratints) => Container(
    child: FutureBuilder(
      future: apiService.getUserData(),
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        if (snapshot.hasError) {
          return Center(
            child: Text(
                "Something wrong with message: ${snapshot.error.toString()}"),
          );
        } else if (snapshot.connectionState == ConnectionState.done) {
          return Center(
            child: RichText(
              textAlign: TextAlign.center,
              text: TextSpan(
                style: TextStyle(
                  color: kDarkTextColor,
                  fontFamily: "Poppins",
                ),
                children: [
                  TextSpan(
                    text: "Your budget is\n",
                    style: TextStyle(
                      fontSize: constratints.maxWidth * .06,
                      fontWeight: FontWeight.normal,
                    ),
                  ),
                  TextSpan(
                    text: snapshot.data['budget'],
                    style: TextStyle(
                      fontSize: constratints.maxWidth * .2,
                      height: 1,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ],
              ),
            ),
          );
        } else {
          return Center(
            child: CircularProgressIndicator(),
          );
        }
      },
    ),
   ),
  );
 }
   }

提前致谢!

【问题讨论】:

  • 我使用选项 2 是我的应用程序。我有一个持久化数据的类,并且可以使用 Provider 访问它。当未来的构建器第一次访问数据提供者时,数据被加载并存储在内存中。然后返回。之后的任何时候,我都会简单地返回缓存的数据。可以工作,但我没有您遇到的进度指示器。建议寻找供应商。
  • @Kent 好的,这实际上很好,你有什么参考吗?将不胜感激。

标签: flutter dart flutter-futurebuilder


【解决方案1】:

问题是每次重新构建页面时,都会调用apiService.getUserData() 并导致重新加载。为避免这种情况,您需要在initState 中调用apiService.getUserData() 并将结果设置为变量(不带await);

所以最小的解决方案是:

class _BudgetState extends State<Budget> {
 future<dynamic> userDataFuture; 

 @override
   void initState() {
     userDataFuture = apiService.getUserData();
     super.initState();
   }
}

那么您需要使用刚刚设置为的变量而不是设置Future: apiService.getUserData():FutureBuilder 小部件中的Future: userDataFuture

如果你真的需要重新加载数据,你可以再次设置状态:

setState(() => userDataFuture = apiService.getUserData());

【讨论】:

  • 它给了我一个错误说The method 'getUserData' was called on null. Receiver: null Tried calling: getUserData()
猜你喜欢
  • 2011-03-13
  • 2019-04-22
  • 2019-12-18
  • 1970-01-01
  • 2017-09-20
  • 2019-09-11
  • 2015-09-03
  • 2015-01-19
  • 1970-01-01
相关资源
最近更新 更多