简体   繁体   中英

Could not find the correct Provider<Movies> above this MyApp Widget

So, I'm using BLoC and Provider packages in one app. In my 'moviesprovider.dart' I am fetching some data from my API which returns a json, when app is opening first time. How can I get access to Provider.of(context) from main.dart in MultiProvider? Basically, I want to get access to the same instance of List movies, but don't know how.

The error I'm getting:


Error: Could not find the correct Provider above this MyApp Widget

This happens because you used a BuildContext that does not include the provider of your choice.


Code: Main.dart

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

class MyApp extends StatelessWidget {
  MyApp({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider.value(
          value: Movies(),
        ),
        Provider<SwipeBloc>(create: (_) {
          SwipeBloc()
            ..add(
              LoadMoviesEvent(
                movies: context.read<Movies>().movies,
              ),
            );
        }),
        ChangeNotifierProvider.value(
          value: User(),
        ),
        ChangeNotifierProvider.value(
          value: Auth(),
        ),
      ],
      child: ...
  }
}

movies_provider.dart

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:movies_recomendations/constants.dart';
import 'package:http/http.dart' as http;

import './single_movie_provider.dart';

class Movies with ChangeNotifier {
  String plotText = "";

  List<Movie> _movies = [];

  List<Movie> get movies {
    return <Movie>[..._movies];
  }

  .....

  Future<void> fetchAndSetMovies() async {
    const url = 'http://192.168.1.142:8000/Desktop/textData.json';

    try {
      final response = await http.get(
        Uri.parse(url),
      );
      String source = Utf8Decoder().convert(response.bodyBytes);

      final extractedData =
          List<Map<String, dynamic>>.from(json.decode(source));
      final List<Movie> loadedMovies = [];

      extractedData.forEach(
        ((movieInfo) => {
              loadedMovies.add(Movie(
                id: movieInfo['id'],
                age: 12,
                countries: List<String>.from(movieInfo['country']),
                description: movieInfo['descriprion'],
                frames: movieInfo['frames'],
                genre: movieInfo['genre'],
                poster: movieInfo['poster'],
                premiereWorld: movieInfo['date'].toString(),
                ratingIMDb: movieInfo['ratingIMDb'],
                ratingKinopoisk: movieInfo['ratingKinopoisk'],
                title: movieInfo['title'][1],
                ifSeries: movieInfo['ifSeries'],
                dateTo: movieInfo['dateTo'].toString(),
                isFavourite: true,
                seasons: movieInfo['seasons'],
              )),
            }),
      );
      _movies = loadedMovies;
      notifyListeners();
    } on Exception catch (e) {
      print('error');
      print(e.toString());
    }
  }
}

Swipe_event.dart

part of 'swipe_block.dart';

abstract class SwipeEvent extends Equatable {
  const SwipeEvent();

  @override
  List<Object> get props => [];
}

class LoadMoviesEvent extends SwipeEvent {
  final List<Movie> movies ;

  LoadMoviesEvent({
    required this.movies,
  });

  @override
  List<Object> get props => [movies];
}

class SwipeLeftEvent extends SwipeEvent {
  final Movie movie;

  SwipeLeftEvent({
    required this.movie,
  });

  @override
  List<Object> get props => [movie];
}

class SwipeRightEvent extends SwipeEvent {
  final Movie movie;

  SwipeRightEvent({
    required this.movie,
  });

  @override
  List<Object> get props => [movie];
}

You probably need to move the code calling Provider.of(context) into its own widget. As the error implies you can't use Provider to retrieve dependencies within the same BuildContext you used to set the Provider scope. Creating a new widget will also generate a new BuildContext.

If you really need to use Provider.of(context) in the same class you define MultiProvider you could use the Builder widget to generate a new context.

So, to solve this problem you should NOT use BlocProvider in main.dart. You should use it in that direct widget where BLoC Provider will be implemented. So I use it in one screen - recomendations, so I write it there like this

class RecomendationsScreen extends StatelessWidget {
  static const routeName = '/recomendations';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: kBackgroundColor,
      body: BlocProvider(
        create: (_) => SwipeBloc()
          ..add(
            LoadMoviesEvent(
              movies: Provider.of<Movies>(context).movies,
            ),
          ),
        child: RecomendationsBody(),
      ),
    );
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM