【问题标题】:(Flutter Futurebuilder) the appbar title won't load as soon as the page changes(Flutter Futurebuilder)页面更改后,应用栏标题不会立即加载
【发布时间】:2021-02-15 04:50:21
【问题描述】:
import 'dart:convert';
import 'package:flutter/widgets.dart';
import 'package:flutter_app/home_page.dart';
import 'package:flutter_app/login_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:geolocator/geolocator.dart';

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}


class _HomePageState extends State<HomePage> {
String name;
  @override
  void initState() {
    super.initState();
  }

Future <void>loadPref()async{
  SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
  return Future.delayed(Duration(seconds: 1),(){
    return name=sharedPreferences.getString("useFullName");
  });

}


logout()async{
  SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
  sharedPreferences.clear();
  sharedPreferences.commit();
  Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (BuildContext context) => LoginPage()), (Route<dynamic> route) => false);
}


 var locationMessege= "";

  void getCurrentLocation()async{
    var position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
    var lastPosition=await Geolocator.getLastKnownPosition();
    print(lastPosition);

    setState(() {
      locationMessege="$position.latitude,$position.longitude";
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor:Colors.orangeAccent,
        title: FutureBuilder(
          future: loadPref(),
          builder: (context, snapshot) {
            if(name==null){
              return Text("Loading");
            }else{
              return Text("$name");
            }
          },
        ),
        actions: <Widget>[
          FlatButton(
            onPressed: () {
              logout();
            },
            child: Text("Log Out", style: TextStyle(color: Colors.white)),
          ),
        ],
      ),
      body: Container(
        decoration: BoxDecoration(
            image: DecorationImage(
                image: AssetImage("assets/bg1.png"), fit: BoxFit.cover)),
        child: Center(
          child: Container(
            padding: EdgeInsets.all(30),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [

                Column(
                  children:<Widget>  [
                    Container(
                        width: 130.0,
                        height: 130.0,
                        decoration: BoxDecoration(
                            image: DecorationImage(
                                image: AssetImage("assets/solalogo2.png"), fit: BoxFit.cover))
                    ),
                    Text("GPS Location",style: TextStyle(
                        color: Colors.black,
                        fontSize: 30.0,
                        fontWeight: FontWeight.bold)),
                    Icon(Icons.location_on,
                    size: 46,
                    color: Colors.yellow,),

                    Text("Position:$locationMessege",style:TextStyle(
                        color: Colors.black,
                        fontSize: 20.0,
                        fontWeight: FontWeight.bold)),
                    FlatButton(onPressed:(){
                      getCurrentLocation();
                    },
                    color: Colors.orange,
                        child: Text("Get New Location",
                        style: TextStyle(
                          color: Colors.black,
                        ),))
                  ],
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

成功登录后,它被定向到这个主页。我想在appbar 标题上加载用户名,但它总是触发加载语句并且在我关闭应用程序并再次加载之前不加载名称。当您重新打开应用程序时,如果用户之前登录,您将被定向到主页。我是 Flutter 的新手,这是我使用它的第二周,任何有用的提示和建议将不胜感激。

【问题讨论】:

  • 欢迎,用户登录后是否可以将用户名带到主屏幕?
  • 它是否符合您的要求。?那就更好了。

标签: flutter user-interface flutter-futurebuilder


【解决方案1】:

恕我直言,在您的情况下使用 FutureBuilder 有点矫枉过正。

您可以使用then 方法代替await。见https://api.flutter.dev/flutter/dart-async/Future/then.html

所以,像以下代码一样更改您的initState()

class _HomePageState extends State<HomePage> {
  String name = ""; // Defaulting to empty 
 
  @override
  void initState() {
    super.initState();

    SharedPreferences.getInstance().then((res) {
      setState(() {
        // Return string of "useFullName"
        // or return empty string if "userFullName" is null
        name = res.getString("useFullName")?? '';
      });
    });
  }
}

现在,您可以简单地将 name 变量用于您的 AppBar 标题:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      backgroundColor:Colors.orangeAccent,
      title: Text(name),
    ),

    ...
  );
}

【讨论】:

  • 我在 ui 上出现红屏错误,提示“data!=null:null:A non-null Sting must be provided to a Text widget”,甚至。当我设置字符串名称=“”;也有间距
  • 我不知道登录验证后的重定向代码是否导致问题,这是我在 if 语句中使用的代码以重定向到主屏幕“Navigator.of(context).pushAndRemoveUntil (MaterialPageRoute(builder: (BuildContext context) => HomePage()), (Route route) => false);"
  • 那是因为res.getString("useFullName");可以返回null。您需要检查它,例如res.getString("useFullName")??"";。查看我的编辑。
  • 只有当应用程序退出并重新打开时才会显示名称,如果它设置为发送黑色空间的条件,它将返回该名称而不是实际数据。
  • 这可能是因为当你没有await-ing setString 方法时,SharedPreferences 还没有完成保存字符串。尝试将其更改为 await sharedPreferences.setString("useFullName", "text");
【解决方案2】:

更改loadPref()方法的代码

Future <String> loadPref()async{
  SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
  return await sharedPreferences.getString("useFullName");

}

        FutureBuilder(
          future: loadPref(),
          builder: (context, snapshot) {
            if(snapshot.hasData){
              return Text("${snapshot.data}");
            }else{
              return Text("Loading");
            }
          },
        )

【讨论】:

  • 还是一样,只有退出再加载应用才会加载
  • 更新我的答案,这肯定会奏效请尝试并告诉我
  • 同样的问题,现在我必须多次关闭应用程序才能加载名称,为了更清楚地说明您是否希望 FutureBuilder 像这样正确?" 标题:FutureBuilder(....)"
  • 你到底在做什么来显示标题,我的意思是什么是流量?
  • 所以首先加载它会检查 SharedPrefence 的 token 。如果它的 null 显示登录屏幕,如果不传递到主屏幕。在验证身份验证后立即在登录屏幕中发送另一个 http 请求以从 api 收集用户信息并将令牌和用户信息(用户全名、ID、角色)保存在共享首选项中。然后在主屏幕中,我尝试使用 SharedPreference 中保存的数据在应用栏上显示用户全名
【解决方案3】:
  Future <String> loadPref()async{
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return Future.delayed(Duration(seconds: 1),()async{
  return await sharedPreferences.getString("useFullName");
});

}

延迟包装返回使其工作,但我完全不知道为什么它现在工作但之前没有工作,并且归功于 Priyesh 建议的代码,我修改了它以使其运行。如果有人知道为什么它不起作用,请告诉我!谢谢。

【讨论】:

    猜你喜欢
    • 2013-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多