I have been having issues retrieving the "username" String saved in Shared Preferences (from the Settings page) for the home page text field (~Line 60 main.dart). I have tried a few methods to retrieve it, but so far I haven't had any luck with trying to grab it. The last attempt I tried was using '$user' (~Line 29), but I still haven't had any luck. I'm still very new to Flutter programming, but I had assumed you could access Shared Preferences data globally as long as you had the Key. So far when I tried using the methods I saw online and in documentation I had no luck transferring the data. Thank you for your help!
main.dart
import 'package:bit/shared_preferences.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:bit/saved_data.dart';
void main() {
runApp(MaterialApp(
title: 'App',
themeMode: ThemeMode.system,
theme: MyThemes.lightTheme,
darkTheme: MyThemes.darkTheme,
home: MyApp(),
));
}
class MyApp extends StatelessWidget {
MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = MediaQuery.of(context).platformBrightness == Brightness.dark
? 'Dark Theme'
: 'Light Theme';
final user = ''; // Empty String Line 29
var scaffold = Scaffold(
appBar: AppBar(
title: const Text('Home'),
),
// Body Home Page Beginning
body: SingleChildScrollView(
child: Center(
child: Text('Hello $theme!'),
)),
// Body Home Page End
drawer: Drawer(
// Drawer Beginning
child: ListView(
children: [
// Drawer Header
DrawerHeader(
decoration: const BoxDecoration(
color: Colors.blue,
),
child: Stack(
children: const [
Align(
alignment: Alignment.centerLeft,
child: CircleAvatar(
backgroundColor: Colors.white,
radius: 50.0,
)),
Align(
alignment: Alignment.centerRight,
child: Text('$user', // Area To Input Text Line 60
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
),
)),
Align(
alignment: Alignment(1, 0.3),
child: Text(
'Supporter',
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
),
))
],
),
),
// Drawer List
ListTile(
title: const Text('Settings'),
subtitle: const Text('Account Info & Settings'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Settings()),
);
},
trailing: const Icon(Icons.arrow_forward_ios_rounded),
),
],
),
),
// Drawer End
);
return MaterialApp(
title: 'App',
themeMode: ThemeMode.system,
theme: MyThemes.lightTheme,
darkTheme: MyThemes.darkTheme,
home: scaffold,
);
}
}
// Settings Page & Account Information
class Settings extends StatefulWidget {
Settings({Key? key}) : super(key: key);
@override
State<Settings> createState() => _SettingsState();
}
class _SettingsState extends State<Settings> {
final _preferencesService = PreferencesService();
final _usernameController = TextEditingController();
void initState() {
super.initState();
_populateFields();
}
void _populateFields() async {
final settings = await _preferencesService.getSettings();
setState(() {
_usernameController.text = settings.username;
});
}
@override
Widget build(BuildContext context) {
final theme = MediaQuery.of(context).platformBrightness == Brightness.dark
? 'Dark Theme'
: 'Light Theme';
return Scaffold(
appBar: AppBar(
title: const Text(
'Settings'), /* actions: <Widget>[
IconButton(
onPressed: () async {
_saveSettings;
},
icon: const Icon(Icons.save),
tooltip: 'Save Settings')
] */
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.fromLTRB(8, 8, 8, 8),
child: Column(
children: [
Column(
// Account
children: [
const Padding(
padding: EdgeInsets.fromLTRB(0, 12, 0, 0),
child: Text('Account Information',
style: TextStyle(
fontSize: 17.0,
))),
Padding(
padding: const EdgeInsets.fromLTRB(12, 0, 12, 12),
child: TextField(
controller: _usernameController,
inputFormatters: [LengthLimitingTextInputFormatter(25)],
decoration: InputDecoration(
hintText: 'Username',
labelText: 'Username',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0)),
),
),
),
],
),
Container(
child: Column(
// App Settings
children: [
// SwitchListTile(value: DarkMode, onChanged: Light => Dark => Light)
// ChangeThemeButtonWidget(),
TextButton(
onPressed: _saveSettings,
child: const Text('Save Settings'),
)
],
),
),
],
),
)));
}
void _saveSettings() {
final newSettings = SettingsModal(
username: _usernameController.text,
);
print(newSettings);
print(_usernameController.text);
_preferencesService.saveSettings(newSettings);
}
}
shared_preferences.dart
import 'package:bit/main.dart';
import 'package:bit/saved_data.dart';
import 'package:shared_preferences/shared_preferences.dart';
class PreferencesService {
Future saveSettings(SettingsModal settings) async {
final preferences = await SharedPreferences.getInstance();
await preferences.setString('username', settings.username);
print('Saved Settings');
}
Future<SettingsModal> getSettings() async {
final preferences = await SharedPreferences.getInstance();
final username = preferences.getString('username')!;
return SettingsModal(
username: username,
);
}
}
saved_data.dart
import 'package:shared_preferences/shared_preferences.dart';
import 'package:bit/main.dart';
class SettingsModal {
final String username;
SettingsModal({
required this.username,
});
}
CodePudding user response:
The issue is coming because, you like to use user
witch is not an constant. While adding const
on Stack's children as Constance, which can be happened in this case, remove const
and it won't show any errors.
child: Stack(
children: [
Align(
alignment: Alignment.centerLeft,
child: CircleAvatar(
backgroundColor: Colors.white,
radius: 50.0,
)),
Align(
alignment: Alignment.centerRight,
child: Text(
user,
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
),
)),
],
),
To receive data from future(SharedPreference
) we need to wait.
You can use FutureBuilder
in this case.
We can provide default value instead of using !
and make it static .
static Future<SettingsModal> getSettings() async {
final preferences = await SharedPreferences.getInstance();
final username = preferences.getString('username') ?? "Not found";
return SettingsModal(
username: username,
);
}
Use PreferencesService.getSettings(),
to get data.
Align(
alignment: Alignment.centerRight,
child: FutureBuilder<SettingsModal>(
future: PreferencesService.getSettings(),
builder: (context, snapshot) {
if (snapshot.hasData &&
snapshot.connectionState ==
ConnectionState.done) {
return Text(
snapshot.data!.username,
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
),
);
}
/// better to handle other cases, included on answer
return CircularProgressIndicator();
},
)),
More about FutureBuilder