flutter - 在 main.dart 中使用 FutureBuilder

标签 flutter sharedpreferences

下面的代码总是显示 OnboardingScreen 一段时间(可能是几毫秒),然后显示 MyHomePage。我相信你们都明白我想做什么。我正在使用 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;
}

主飞镖

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

最佳答案

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

数据加载前总会有一些延迟,因此您需要在数据加载前显示一些内容。

Snapshot.hasData 仅显示已解析 future 的返回数据。

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

关于flutter - 在 main.dart 中使用 FutureBuilder,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60971491/

相关文章:

java - 帮助设置和 Android 动态壁纸

java - Android:无法调用没有参数的私有(private) android.net.Uri()

java - 在方法中获取 SharedPreferences 的上下文

flutter - 错误 : The getter 'length' was called on null

unit-testing - flutter 单元测试 :Invalid argument (string): Contains invalid characters

flutter - 又抛出异常: A AppNotifier was used after being disposed

dart - 限制选中复选框的数量

design-patterns - 选择正确的 Flutter 设计模式

android - 将 ProtoBuf 对象存储在 SharedPreferences 中

Android 填充文本字段