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

After the successful login its being directed to to this home page. I want to load the users name on the appbar title, but it always trigger the loading statement and not load the name till I close the app and load it again. When you reopen the app you get directed to home page if the user previously logged in. I'm new to flutter and this has been my 2nd week working with it and any useful tips and advice would be much appreciated.

ישו אוהב אותך
  • 28,609
  • 11
  • 78
  • 96

3 Answers3

1

imho, using FutureBuilder for your case is a bit overkill.

You can use then method instead of using await. see https://api.flutter.dev/flutter/dart-async/Future/then.html.

So, change your initState() like the following code:

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

Now, you can simply using the name variable for your AppBar title:

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

    ...
  );
}
ישו אוהב אותך
  • 28,609
  • 11
  • 78
  • 96
  • im getting the red screen error on the ui saying "data!=null:null:A non-null Sting must be provided to a Text widget" even. when i set String name =" "; with a spacing as well – user14733716 Feb 16 '21 at 01:19
  • i dont know if its the redirect code after the validation of login is causing the problem , this is the code i use in a if statement to redirect to home screen " Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (BuildContext context) => HomePage()), (Route route) => false);" – user14733716 Feb 16 '21 at 01:34
  • That is because `res.getString("useFullName");` can return null. You need to check for it, something like `res.getString("useFullName")??"";`. See my edit. – ישו אוהב אותך Feb 16 '21 at 06:17
  • same thing only when app is quit and re open it shows the name, if it set to a condition to send black space it will return that instead of the actual data. – user14733716 Feb 16 '21 at 09:19
  • It's probably because SharedPreferences haven't finished saving the string yet when you not `await`-ing the setString method. Try changing it to something like `await sharedPreferences.setString("useFullName", "text");` – ישו אוהב אותך Feb 16 '21 at 09:58
0

Change the code of loadPref() method

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");
            }
          },
        )
Priyesh
  • 1,266
  • 5
  • 17
  • still the same, it only load if i quit and load the app again – user14733716 Feb 15 '21 at 06:15
  • Updating my answer, And this will definitely work Please try it and let me know – Priyesh Feb 15 '21 at 06:19
  • same issue ,now i have to close the app multiple times to get the name loading , for more clarification do you want FutureBuilder to go like this correct ?" title: FutureBuilder(....) " – user14733716 Feb 16 '21 at 01:48
  • What exactly are you doing to show title, I mean what is flow? – Priyesh Feb 16 '21 at 04:50
  • so first load it will check for the SharedPrefence for a token . if its null show the login screen if not pass to home screen. In the login screen as soon as the authentication is validate im sending another http request to collect user info from the api and save token and user info (User Full name , Id, Role ) in shared preference. Then in home screen im trying to show the the users full name on the app bar using the saved data in the SharedPreference – user14733716 Feb 16 '21 at 05:27
  • https://github.com/sudaraka93/FlutterApp i have uploaded the dart files to the github ,hope this will help you understand what i have done or trying to do . – user14733716 Feb 16 '21 at 05:41
0
  Future <String> loadPref()async{
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return Future.delayed(Duration(seconds: 1),()async{
  return await sharedPreferences.getString("useFullName");
});

}

wrapping the return with a delay made it work , but i have absolutely no idea why it worked now but not before and credit for Priyesh suggested code i modified that to get it running. and if any one know why it didn't work please do let me know! thank you .