在main.dart中使用FutureBuilder

时间:2020-04-01 13:02:28

标签: flutter sharedpreferences

下面的代码始终在显示MyHomePage之后总是显示OnboardingScreen一点时间(可能是几毫秒)。我相信你们都知道我要做什么。我正在使用FutureBuilder检查getString方法是否有数据。我怎么了或任何其他最佳方式?

saveString() async {
  final prefs = await SharedPreferences.getInstance();
  prefs.setString('firstOpen', '1');
}

getString()方法始终返回字符串。

getString() async {
  final prefs = await SharedPreferences.getInstance();
  String txt = prefs.getString('firstOpen');
  return txt;
}

main.dart

home: new FutureBuilder(
            future: getString(),
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return MyHomePage();
              } else {
                return OnboardingScreen();
              }
            })

2 个答案:

答案 0 :(得分:1)

来自FutureBuilder class documentation

将来一定要早一些,例如在State.initState,State.didUpdateConfig或State.didChangeDependencies中。构造FutureBuilder时,不得在State.build或StatelessWidget.build方法调用期间创建它。如果future与FutureBuilder同时创建,则每次FutureBuilder的父级重建时,异步任务都将重新启动。

因此,您需要创建一个新的有状态小部件以将该Future的状态存储为State。在此状态下,您可以检查要显示的页面。如建议的那样,您可以使用initState方法开始将来的工作:

class FirstPage extends StatefulWidget {

  _FirstPageState createState() => _FirstPageState();
}

class _FirstPageState extends State<FirstPage> {
final Future<String> storedFuture;

  @override
  void initState() {
      super.initState();
      storedFuture = getString();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
            future: storedFuture,
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return MyHomePage();
              } else {
                return OnboardingScreen();
              }
            });
  }
}

因此在您的房屋财产中,您可以将其称为“第一页”:

home: FirstPage(),

您的错误是在build方法中调用getString(),每次重建屏幕时,该方法都会重新启动异步调用。

答案 1 :(得分:1)

通常,我使用的是另一条路线,而不是FutureBuilder。因为futurebuilder每次热重装都会重置futureBuilder。

在加载数据之前总是会有一些延迟,因此您需要在加载数据之前先显示一些东西。

Snapshot.hasData仅显示已解决的将来的返回数据。

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: SplashScreen(),
    );
  }
}

class SplashScreen extends StatefulWidget {
  @override
  _SplashScreenState createState() => _SplashScreenState();
}

const isOnboardingFinished = 'isOnboardingFinished';

class _SplashScreenState extends State<SplashScreen> {
  Timer timer;
  bool isLoading = true;

  @override
  void initState() {
    _checkIfFirstOpen();
    super.initState();
  }

  Future<void> _checkIfFirstOpen() async {
    final prefs = await SharedPreferences.getInstance();
    var hasOpened = prefs.getBool(isOnboardingFinished) ?? false;

    if (hasOpened) {
      _changePage();
    } else {
      setState(() {
        isLoading = false;
      });
    }
  }

  _changePage() {
    Navigator.of(context).pushReplacement(
      // this is route builder without any animation
      PageRouteBuilder(
        pageBuilder: (context, animation1, animation2) => HomePage(),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return isLoading ? Container() : OnBoarding();
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(child: Text('homePage'));
  }
}

class OnBoarding extends StatelessWidget {
  Future<void> handleClose(BuildContext context) async {
    final prefs = await SharedPreferences.getInstance();
    prefs.setBool(isOnboardingFinished, true);
    Navigator.of(context).pushReplacement(
      MaterialPageRoute(
        builder: (_) => HomePage(),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Center(
        child: RaisedButton(
          onPressed: () => handleClose(context),
          child: Text('finish on bording and never show again'),
        ),
      ),
    );
  }
}