Flutter type 'Future<dynamic>' is not a subtype of type 'Stream<PostModel>?'

Issue

I’m trying to create a list using bloc and rxdart but I get an error type ‘Future’ is not a subtype of type ‘Stream?’ I am using rxdart: ^0.27.1. Just want to put the Array response in list.

My List screen

 Column(
      children: [
        StreamBuilder(
          stream: bloc.fetchPosts(),
          builder: (context, AsyncSnapshot<PostModel> snapshot) {
            if (snapshot.hasData) {
              return buildList(snapshot);
            } else if (snapshot.hasError) {
              return Text(snapshot.error.toString());
            }
            return Center(child: CircularProgressIndicator());
          },
        ),
      ],
    ),

PostBloc bloc
Maybe the error is here when using stream but i’m unable to find the error.

 class PostBloc {
    final _repository = PostRepository();
    final _postsFetcher = PublishSubject<PostModel>();

    Stream<PostModel> get allPosts => _postsFetcher.stream;

    fetchPosts() async {
    PostModel itemModel = await _repository.fetchAllPosts();
    _postsFetcher.sink.add(itemModel);
     }

     dispose() {
    _postsFetcher.close();
     }
    }

final bloc = PostBloc();

Post Repository

    class PostRepository {
    final postApiProvider = PostApiProvider();
    Future<PostModel> fetchAllPosts() => postApiProvider.getPostList();
    }

Post ApiProvider

class PostApiProvider {
  Client client = Client();

  Future<PostModel> getPostList() async {
    print("entered");
    final response = await client
        .get(Uri.parse("https://jsonplaceholder.typicode.com/posts"));
    print(response.body.toString());
    if (response.statusCode == 200) {

      return PostModel.fromJson(json.decode(response.body));
    } else {
      // If that call was not successful, throw an error.
      throw Exception('Failed to load post');
    }
  }
}

Post Model

class Post {
  late int userId;
  late int id;
  late String title;
  late String body;

  Post(result) {
    userId = result['userId'];
    id = result['id'];
    title = result['title'];
    body = result['body'];
  }

  int get getUserID => userId;

  int get getID => id;

  String get getTitle => title;

  String get getBody => body;

}

class PostModel {
  List<Post> results = [];

  PostModel.fromJson(Map<String, dynamic> parsedJson) {
    List<Post> temp = [];
    for (int i = 0; i < parsedJson.length; i++) {
      Post result = Post(parsedJson[i]);
      temp.add(result);
    }
    results = temp;
  }

  List<Post> get getResults => results;
}

Sample Response

[
    {
        "userId": 1,
        "id": 1,
        "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
        "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
    },
    {
        "userId": 1,
        "id": 2,
        "title": "qui est esse",
        "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
    }
]

Solution

The basic concept of BLoC is first you have to put data in stream with the help of sink and then you can get data from stream with help of Stream.

In your code, You’re using sink function as a StreamBuilder's stream. Which is incorrect. You should call stream like below,

  StreamBuilder(
      stream: bloc.allPosts, /// THIS IS STREAM OF DATA
      builder: (context, AsyncSnapshot<PostModel> snapshot) {
        if (snapshot.hasData) {
          return buildList(snapshot);
        } else if (snapshot.hasError) {
          return Text(snapshot.error.toString());
        }
        return Center(child: CircularProgressIndicator());
      },
    );

Call your sink function in initState or wherever you want like this

bloc.fetchPosts(); /// THIS WILL TRIGGER YOUR API

Second issue is in model, It’s about datatype. The response you’re getting from API is List<dynamic> and you have declared Map<String, dynamic>. Which is incorrect. Define as below

class PostModel {
  List<Post> results = [];

  PostModel.fromJson(List<dynamic> parsedJson) {
    List<Post> temp = [];
    for (int i = 0; i < parsedJson.length; i++) {
      Post result = Post(parsedJson[i]);
      temp.add(result);
    }
    results = temp;
  }

  List<Post> get getResults => results;
} 

And one last thing, You forgot to return your model in fetchPosts() function

Future<PostModel> fetchPosts() async {
    PostModel itemModel = await _repository.fetchAllPosts();
    _postsFetcher.sink.add(itemModel);
    return itemModel;
  }

Answered By – Hemal Moradiya

Answer Checked By – Marie Seifert (FlutterFixes Admin)

Leave a Reply

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