flutterdartflutter-change-notifierflutter-change-notifier-provider

_TypeError thrown building LandingPage(dirty,dependencies:[_InheritedProviderScope<AppState?>]) type _Type is not a subtype of type String in typecast


I am new to flutter and trying to develop a login screen, I am facing issue while implementing ChangeNotifierProvider. I tried using both MultiProvider and ChangeNotifierProvider widgets and both produces same exception.

Exception

The following _TypeError was thrown building LandingPage(dirty, dependencies: [_InheritedProviderScope<AuthState?>]):
type '_Type' is not a subtype of type 'String' in type cast

The relevant error-causing widget was:
    LandingPage LandingPage:file:///Users/hatimtai/Flutter%20Projects/myapp/lib/main.dart:32:21

When the exception was thrown, this was the stack:
#0      new AuthState (package:myapp/states/auth_state.dart:4:27)
#1      MyApp.build.<anonymous closure> (package:myapp/main.dart:23:53)
#2      _CreateInheritedProviderState.value (package:provider/src/inherited_provider.dart:736:36)
#3      _InheritedProviderScopeElement.value (package:provider/src/inherited_provider.dart:590:33)
#4      Provider.of (package:provider/src/provider.dart:303:37)
#5      LandingPage.build (package:myapp/main.dart:43:32)
#6      StatelessElement.build (package:flutter/src/widgets/framework.dart:5541:49)
#7      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5471:15)
#8      Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#9      ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:5453:5)
#10     ComponentElement.mount (package:flutter/src/widgets/framework.dart:5447:5)
...     Normal element mounting (220 frames)
#230    Element.inflateWidget (package:flutter/src/widgets/framework.dart:4326:16)
#231    MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6871:36)
#232    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6883:32)
...     Normal element mounting (453 frames)
#685    _InheritedProviderScopeElement.mount (package:provider/src/inherited_provider.dart:411:11)
...     Normal element mounting (7 frames)
#692    SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
...     Normal element mounting (7 frames)
#699    _NestedHookElement.mount (package:nested/nested.dart:187:11)
...     Normal element mounting (7 frames)
#706    _InheritedProviderScopeElement.mount (package:provider/src/inherited_provider.dart:411:11)
...     Normal element mounting (7 frames)
#713    SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
...     Normal element mounting (7 frames)
#720    _NestedHookElement.mount (package:nested/nested.dart:187:11)
...     Normal element mounting (7 frames)
#727    SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
...     Normal element mounting (33 frames)
#760    Element.inflateWidget (package:flutter/src/widgets/framework.dart:4326:16)
#761    Element.updateChild (package:flutter/src/widgets/framework.dart:3837:18)
#762    _RawViewElement._updateChild (package:flutter/src/widgets/view.dart:289:16)
#763    _RawViewElement.mount (package:flutter/src/widgets/view.dart:312:5)
...     Normal element mounting (7 frames)
#770    Element.inflateWidget (package:flutter/src/widgets/framework.dart:4326:16)
#771    Element.updateChild (package:flutter/src/widgets/framework.dart:3837:18)
#772    RootElement._rebuild (package:flutter/src/widgets/binding.dart:1334:16)
#773    RootElement.mount (package:flutter/src/widgets/binding.dart:1303:5)
#774    RootWidget.attach.<anonymous closure> (package:flutter/src/widgets/binding.dart:1256:18)
#775    BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2835:19)
#776    RootWidget.attach (package:flutter/src/widgets/binding.dart:1255:13)
#777    WidgetsBinding.attachToBuildOwner (package:flutter/src/widgets/binding.dart:1083:27)
#778    WidgetsBinding.attachRootWidget (package:flutter/src/widgets/binding.dart:1065:5)
#779    WidgetsBinding.scheduleAttachRootWidget.<anonymous closure> (package:flutter/src/widgets/binding.dart:1051:7)
#783    _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)
(elided 3 frames from class _Timer and dart:async-patch)

I am following google codelabs "Your first Flutter app", have gone through it multiple times and am not able to find what is going wrong and hence need your help.

main.dart

import 'package:flutter/material.dart';
import 'package:myapp/states/auth_state.dart';
import 'package:myapp/states/myapp_state.dart';
import 'package:provider/provider.dart';

import 'package:myapp/pages/login_page.dart';
import 'package:myapp/pages/home_page.dart';
import 'package:myapp/utils/login_utils.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (context) => MyAppState()),
        ChangeNotifierProvider(create: (context) => AuthState()),
      ],
      child: MaterialApp(
        title: 'My App',
        theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(
              seedColor: const Color.fromARGB(255, 31, 136, 105)),
          useMaterial3: true,
        ),
        home: const LandingPage(),
      ),
    );
  }
}

class LandingPage extends StatelessWidget {
  const LandingPage({super.key});

  @override
  Widget build(BuildContext context) {
    final authState = Provider.of<AuthState>(context);

    Widget page;
    bool isUserLoggedIn = false;
    isLoggedIn(authState.refreshToken, authState.accessToken)
        .then((value) => isUserLoggedIn = value);

    switch (isUserLoggedIn) {
      case true:
        page = const HomePage();
        break;
      default:
        page = const LoginPage();
    }

    return page;
  }
}

states/auth_state.dart

import 'package:flutter/material.dart';

class AuthState extends ChangeNotifier {
  var refreshToken = Null as String;
  var accessToken = Null as String;

  void setCredentials(String refresh, String access) {
    refreshToken = refresh;
    accessToken = access;
    notifyListeners();
  }
}

states/myapp_state.dart

import 'package:flutter/material.dart';

class MyAppState extends ChangeNotifier {}


Solution

  • var refreshToken = Null as String; is the problem. Null is a type. If you want to set the value to null, use null (small 'n' letter). And you can't cast a null to String. Type-annotate the variable with String? instead.

    String? refreshToken; // No need "= null", nullable variable is null by default
    

    You might want to try the Null safety codelab.


    See also: