Cl0ud-l3ss
Cl0ud-l3ss

Reputation: 185

Non-nullable instance field must be initialized and Unhandled error LateInitializationError

I'm trying to create a database and store an API token for user login but I keep getting an error when the app builds/compiles:

Non-nullable instance field '_database' must be initialized

I've tried adding a late modifier as suggested which then throws:

E/flutter ( 6894): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: Unhandled error LateInitializationError: Field '_database@637109567' has not been initialized. occurred in Instance of 'AuthenticationBloc'.

my user_db.dart

import 'dart:io';

import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';

final userTable = 'userTable';



class DatabaseProvider {
  static final DatabaseProvider dbProvider = DatabaseProvider();
  //non nullable error on _database
  Database _database;

  Future <Database> get database async {

    print('before condition');
    if (_database != null){
      return _database;
    }
    _database = await createDatabase();
    return _database;
  }

  createDatabase() async {
    Directory documentsDirectory = await getApplicationDocumentsDirectory();
    String path = join(documentsDirectory.path, "User.db");

    var database = await openDatabase(
      path,
      version: 1,
      onCreate: initDB,
      onUpgrade: onUpgrade,
    );
    return database;
  }

  void onUpgrade(
      Database database,
      int oldVersion,
      int newVersion,
      ){
    if (newVersion > oldVersion){}
  }

  void initDB(Database database, int version) async {
    await database.execute(
        "CREATE TABLE $userTable ("
            "id INTEGER PRIMARY KEY, "
            "username TEXT, "
            "token TEXT "
            ")"
    );
  }
}

my AuthBloc.dart

import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';
import 'package:equatable/equatable.dart';

import 'package:times/repository/user_repository.dart';
import 'package:times/model/user_model.dart';

part 'authentication_event.dart';
part 'authentication_state.dart';

class AuthenticationBloc
    extends Bloc<AuthenticationEvent, AuthenticationState> {

  AuthenticationBloc({required this.userRepository})
      : super(AuthenticationUnauthenticated())
  ;

  final UserRepository userRepository;

  @override
  Stream<AuthenticationState> mapEventToState(
    AuthenticationEvent event,
  ) async* {
    if (event is AppStarted) {

      final bool hasToken = await userRepository.hasToken();

      if (hasToken) {
        yield AuthenticationAuthenticated();
      } else {
        yield AuthenticationUnauthenticated();
      }
    }

    if (event is LoggedIn) {
      yield AuthenticationLoading();

      await userRepository.persistToken(
        user: event.user
      );
      yield AuthenticationAuthenticated();
    }

    if (event is LoggedOut) {
      yield AuthenticationLoading();

      await userRepository.deleteToken(id: 0);

      yield AuthenticationUnauthenticated();
    }
  }
}

Upvotes: 0

Views: 3831

Answers (1)

Nisanth Reddy
Nisanth Reddy

Reputation: 6395

The problem is being caused by this line

if (_database != null) {

You can't directly apply null check on a non-nullable variable and since it is a late variable and you didn't initialize it, the null check will always keep throwing the error.

One way to fix this would be to make your _database Nullable and instantiate it to null, like this

Database? _database = null;

In order to avoid using the Nullable type everywhere in code, you could modify your function to use the bang operator (!) like this,

Future <Database> get database async {
  if (_database != null){
    return _database!;
  }
  _database = await createDatabase();
  return _database!;
}

Upvotes: 1

Related Questions