Search code examples
fluttersharedpreferences

shared_preferences _CastError


The supplied example works

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

void main() {
  runApp(MaterialApp(
    home: Scaffold(
      body: Center(
      child: RaisedButton(
        onPressed: _incrementCounter,
        child: Text('Increment Counter'),
        ),
      ),
    ),
  ));
}

_incrementCounter() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  int counter = (prefs.getInt('counter') ?? 0) + 1;
  print('Pressed $counter times.');
  await prefs.setInt('counter', counter);
}

, but say I want to load data before runApp. Just move _incrementCounter() like this

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

void main() {
 _incrementCounter(); 
  runApp(MaterialApp(
    home: Scaffold(
      body: Center(
      child: RaisedButton(
        onPressed: _incrementCounter,
        child: Text('Increment Counter'),
        ),
      ),
    ),
  ));
}

_incrementCounter() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  int counter = (prefs.getInt('counter') ?? 0) + 1;
  print('Pressed $counter times.');
  await prefs.setInt('counter', counter);
}

but now I get an "_CastError (Null check operator used on a null value)".

It would be real nice to have a init() before runApp, but it seems that at least shared_preferences somehow relies of something going on in runApp.

If not before runApp, then where should initialization using shared_preferences be put?


Solution

  • Just add the WidgetsFlutterBinding.ensureInitialized(); inside the main function:

    import 'package:flutter/material.dart';
    import 'package:shared_preferences/shared_preferences.dart';
    
    Future<void> main() async {
     WidgetsFlutterBinding.ensureInitialized(); // Add this
    
     await _incrementCounter(); // Also, add await here since the function is async
    
      runApp(MaterialApp(
        home: Scaffold(
          body: Center(
          child: RaisedButton(
            onPressed: _incrementCounter,
            child: Text('Increment Counter'),
            ),
          ),
        ),
      ));
    }
    
    Future<void> _incrementCounter() async {
      SharedPreferences prefs = await SharedPreferences.getInstance();
      int counter = (prefs.getInt('counter') ?? 0) + 1;
      print('Pressed $counter times.');
      await prefs.setInt('counter', counter);
    }
    

    The thing is, SharedPreferences uses a native platform code to initialize the storage. Flutter platform channels are used for this communication, so you need to ensure that Flutter engine binding is initialized.