Flutter Bloc: difference between RepositoryProvider and RepositoryProvider.value

Issue

I know the difference between RepositoryProvider and RepositoryProvider.value: the first one creates the repository for you and the second one receives a repository that is already created.

Please see the difference between the 2 code blocks – the first one is okay, the second one gives the following error.

RepositoryProvider.of() called with a context that does not contain a repository of type AuthRepository.

No ancestor could be found starting from the context that was passed to RepositoryProvider.of<AuthRepository>().

This can happen if the context you used comes from a widget above the RepositoryProvider.

The context used was: HomeScreen(dirty)

I don’t understand why code 2 gives an error.

Code 1: success

class MyApp {

  void main() {

    // 1) Let the RepositoryProvider create the AuthRepository
    runApp(RepositoryProvider(
      crate: (context) => AuthRepository(),
        child: BlocProvider(
        create: (context) => AuthCubit(authRepository: RepositoryProvider.of<AuthRepository>(context)),
          child: const MaterialApp(
            // 2) Show HomeScreen that will access the AuthRepository instance
            home: HomeScreen()
          )
        )
    )

  }

}

class HomeScreen extends StatelessWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final authCubit = BlocProvider.of<AuthCubit>(context);

    // 3) This will succeed
    final authRepo = RepositoryProvider.of<AuthRepository>(context);
    return Scaffold(
      body: BlocBuilder<AuthCubit, AuthState>(
        builder: (context, state) {
          return const Text(state.toString());
        },
      ),
    );

  }

}

Code 2: error

class MyApp {

  void main() {

    // 1) Create a repository instance of AuthRepository
    final authRepo = AuthRepository();

    // 2) Add this AuthRepository instance to the RepositoryProvider.value
    runApp(RepositoryProvider.value(
      value: (context) => authRepo,
        child: BlocProvider(
        create: (context) => AuthCubit(authRepository: authRepo),
          child: const MaterialApp(
            // 3) Show HomeScreen that will access the AuthRepository instance
            home: HomeScreen()
          )
        )
    )

  }

}

class HomeScreen extends StatelessWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final authCubit = BlocProvider.of<AuthCubit>(context);

    // 4) This will fail
    final authRepo = RepositoryProvider.of<AuthRepository>(context);
    return Scaffold(
      body: BlocBuilder<AuthCubit, AuthState>(
        builder: (context, state) {
          return const Text(state.authenticationStatus.toString());
        },
      ),
    );

  }
  
}

Solution

The value should be a repository not a function.

Instead of

runApp(RepositoryProvider.value(
      value: (context) => authRepo,

try

runApp(RepositoryProvider.value(
      value: authRepo,

Answered By – Peter Bagyinszki

Answer Checked By – Willingham (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *