I'm following the tutorial about shared preferences and I'm stuck with _CastError (Null check operator used on a null value)
. I've already found a few solutions but they are not perfect for my case or I just simply can't implement them properly :(
On the screen, you can see where this error appears:
My files below:
main.dart
import 'package:day08_user_settings/preferences_service.dart';
import 'package:flutter/material.dart';
import 'models.dart';
void main() {
runApp(
MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyApp(),
),
);
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final _preferencesService = PreferencesService();
final _usernameController = TextEditingController();
var _selectedGender = Gender.FEMALE;
final _selectedLanguages = Set<ProgrammingLanguage>();
var _isEmployed = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('User settings'),
),
body: ListView(
children: [
ListTile(
title: TextField(
controller: _usernameController,
decoration: const InputDecoration(labelText: 'Username'),
),
),
RadioListTile(
title: const Text('Female'),
value: Gender.FEMALE,
groupValue: _selectedGender,
onChanged: (newValue) =>
setState(() => _selectedGender = newValue!)),
RadioListTile(
title: const Text('Male'),
value: Gender.MALE,
groupValue: _selectedGender,
onChanged: (newValue) =>
setState(() => _selectedGender = newValue!)),
RadioListTile(
title: const Text('Other'),
value: Gender.OTHER,
groupValue: _selectedGender,
onChanged: (newValue) =>
setState(() => _selectedGender = newValue!)),
CheckboxListTile(
title: const Text('Dart'),
value: _selectedLanguages.contains(ProgrammingLanguage.DART),
onChanged: (_) {
setState(() {
_selectedLanguages.contains(ProgrammingLanguage.DART)
? _selectedLanguages.remove(ProgrammingLanguage.DART)
: _selectedLanguages.add(ProgrammingLanguage.DART);
});
},
),
CheckboxListTile(
title: const Text('JavaScript'),
value: _selectedLanguages.contains(ProgrammingLanguage.JAVASCRIPT),
onChanged: (_) {
setState(() {
_selectedLanguages.contains(ProgrammingLanguage.JAVASCRIPT)
? _selectedLanguages.remove(ProgrammingLanguage.JAVASCRIPT)
: _selectedLanguages.add(ProgrammingLanguage.JAVASCRIPT);
});
},
),
CheckboxListTile(
title: const Text('Kotlin'),
value: _selectedLanguages.contains(ProgrammingLanguage.KOTLIN),
onChanged: (_) {
setState(() {
_selectedLanguages.contains(ProgrammingLanguage.KOTLIN)
? _selectedLanguages.remove(ProgrammingLanguage.KOTLIN)
: _selectedLanguages.add(ProgrammingLanguage.KOTLIN);
});
},
),
CheckboxListTile(
title: const Text('Swift'),
value: _selectedLanguages.contains(ProgrammingLanguage.SWIFT),
onChanged: (_) {
setState(() {
_selectedLanguages.contains(ProgrammingLanguage.SWIFT)
? _selectedLanguages.remove(ProgrammingLanguage.SWIFT)
: _selectedLanguages.add(ProgrammingLanguage.SWIFT);
});
},
),
SwitchListTile(
title: const Text('Is Employed'),
value: _isEmployed,
onChanged: (newValue) => setState(
() => _isEmployed = newValue,
),
),
TextButton(
onPressed: _saveSettings,
child: const Text('Save Settings'),
)
],
),
);
}
void _saveSettings() {
final newSettings = Settings(
username: _usernameController.text,
gender: _selectedGender,
programmingLanguages: _selectedLanguages,
isEmployed: _isEmployed,
);
print(newSettings);
_preferencesService.saveSettings(newSettings);
}
}
models.dart
enum Gender { FEMALE, MALE, OTHER }
enum ProgrammingLanguage { DART, JAVASCRIPT, KOTLIN, SWIFT }
class Settings {
String? username;
Gender? gender;
Set<ProgrammingLanguage>? programmingLanguages;
bool? isEmployed;
Settings({
required String username,
required Gender gender,
required Set<ProgrammingLanguage> programmingLanguages,
required bool isEmployed,
});
}
preferences-service.dart
import 'package:day08_user_settings/models.dart';
import 'package:shared_preferences/shared_preferences.dart';
class PreferencesService {
Future saveSettings(Settings settings) async {
final preferences = await SharedPreferences.getInstance();
await preferences.setString('username', settings.username ?? '');
await preferences.setBool('isEmployed', settings.isEmployed ?? false);
await preferences.setInt('Gender', settings.gender?.index ?? 0);
await preferences.setStringList(
'ProgrammingLanguages',
settings.programmingLanguages!
.map((lang) => lang.index.toString())
.toList(),
);
print('Save Settings');
}
}
Please help with this because I don't have any idea at this point and I'm still learning.
CodePudding user response:
As you can see from the error setting.programmingLanguages
is null. What do you want to do if the list is empty?
- If you want to remove whatever is in preferences from before use
remove('ProgrammingLanguages')
. - You can just skip
setString()
ifsetting.programmingLanguages==null
P.S. I advice you to have keys as constant values at the top of the file, so you don't have to copy paste and less chance for a typo. Like const programLang = 'ProgrammingLanguages'
CodePudding user response:
The _CastError (Null check operator used on a null value)
error is triggered because you tried to use a null-valued variable. When you enter "!" in settings.programmingLanguages!.map((lang) => lang.index.toString()).toList(),
, in theory you are ensuring that the value of programmingLanguages
is not null. I suggest you do a check first to verify that the value is not null, and only then use the "!" in your variable.