0

I am trying to fetch data i wanna fetch post data using bloc in a statefulWidget the data is ready i won't fetch it from api the data is ready in the list posts i just want to show it in a stateful widget using bloc how can i do it i'm a new to bloc i tried searching a lot but all solutions fetch data from api?
// this is post class

 class Post  {
      final User user;
      final String caption;
      final String timeAgo;
      final String imageUrl;
      final int likes;
      final int comments;
      final int shares;
      const Post({
        required this.user,
        required this.caption,
        required this.timeAgo,
        required this.imageUrl,
        required this.likes,
        required this.comments,
        required this.shares,
      });
    }

// and this is data

 final List<Post> posts = 
    [
      Post(
        user: currentUser,
        caption: 'Check out these cool puppers',
        timeAgo: '58m',
        imageUrl: 'https://images.unsplash.com/photo-1525253086316-d0c936c814f8',
        likes: 1202,
        comments: 184,
        shares: 96,
      ),
      Post(
        user: onlineUsers[5],
        caption:
        'Please enjoy this placeholder text: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
        timeAgo: '3hr',
        imageUrl: 'null',
        likes: 683,
        comments: 79,
        shares: 18,
      ),
      Post(
        user: onlineUsers[4],
        caption: 'This is a very good boi.',
        timeAgo: '8hr',
        imageUrl:
        'https://images.unsplash.com/photo-1575535468632-345892291673?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80',
        likes: 894,
        comments: 201,
        shares: 27,
      ),
      Post(
        user: onlineUsers[3],
        caption: 'Adventure ',
        timeAgo: '15hr',
        imageUrl:
        'https://images.unsplash.com/photo-1573331519317-30b24326bb9a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80',
        likes: 722,
        comments: 183,
        shares: 42,
      ),
      Post(
        user: onlineUsers[0],
        caption:
        'More placeholder text for the soul: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
        timeAgo: '1d',
        imageUrl: 'null',
        likes: 482,
        comments: 37,
        shares: 9,
      ),
      Post(
        user: onlineUsers[9],
        caption: 'A classic.',
        timeAgo: '1d',
        imageUrl:
        'https://images.unsplash.com/reserve/OlxPGKgRUaX0E1hg3b3X_Dumbo.JPG?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80',
        likes: 1523,
        shares: 129,
        comments: 301,
      )
    ];

1 Answers1

2

For bloc there are actually different strategies of how you can post and retrieve data. The best practice is to make a layer of data providers and repositories and then ofcourse use logic layer to process the data and yield states. For the initial step you can use something like a bloc extension that is available on VScode by Felix. Just right-click on the lib folder and there you would see new Bloc (after installing extension). Once you are done with it you can make another layer called Data provider in which you can set up your API how you like (e.g with http or dio).

An example data provider would be.

something_repo.dart

import 'dart:convert';

import 'package:flutter/material.dart';

import 'package:http/http.dart' as http;



class SomethingApiClient {
  final http.Client? httpClient;
  SomethingApiClient({
    @required this.httpClient,
  }) : assert(httpClient != null);
  Future<SomthingModel> fetchSomething() async {
    final url = '${baseUrl}api/v1/whatyouwannacall';
    final response = await http.get(Uri.parse(url), headers: {
      //any header that is required.
    });

    if (response.statusCode != 200) {
      throw new Exception('error getting products');
    }

 
    return somthingFromJson(response.body);
  }
}

then you can make some event into events.dart This will also help you sent the data into the bloc as well when working with logic and yielding. For e.g I am only passing string, but you can pass a model if required like you said. some_event.dart

part of 'products_bloc.dart';

abstract class ProductsEvent extends Equatable {
  const ProductsEvent();
}

class FetchProducts extends ProductsEvent {
  final String? product;
  const FetchProducts({this.product});

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

Then it comes the states like if the bloc should throw error or success based on your scenario. I am using equatable to compare the values to eliminate unnecessary UI builds.

part of 'products_bloc.dart';

abstract class ProductsState extends Equatable {
  const ProductsState();

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

class ProductsInitial extends ProductsState {}

class ProductsEmpty extends ProductsState {}

class ProductsLoading extends ProductsState {
  get products => null;
}

class ProductsLoaded extends ProductsState {
  final Products? products;

  const ProductsLoaded({this.products}) : assert(products != null);

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

class ProductsError extends ProductsState {}

And finally then you would have to write some bloc code for logic implementation.

import 'dart:async';

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

part 'dummy_bloc_event.dart';
part 'dummy_bloc_state.dart';

class DummyBlocBloc extends Bloc<DummyBlocEvent, DummyBlocState> {
  DummyBlocBloc() : super(DummyBlocInitial());

  @override
  Stream<DummyBlocState> mapEventToState(
    DummyBlocEvent event,
  ) async* {
    if(event is YourDesiredEvent)
    {
      yield DummyLoadingState();
      try{
        //try your api here
        final DummyModel products = await repository!.fetchdummy();
        yield ProductsLoaded(products: products);
      }
      catch (error, stacktrace) {
        print('$error $stacktrace');
        yield DummyError();
      }
    }
  }
}

There is also a respitory that you would need to set when using blocProvider for initializing like in generatedroutes.

Something like this

import 'dart:async';

import 'package:kind_app_admin/APImodels/categoriesModel.dart';
import 'package:kind_app_admin/DataProviders/categoriesDataProvider.dart';
import 'package:meta/meta.dart';

class DummyRepository {
  final DummyApiClient? dummyApiClient;

  DummyRepository({@required this.dummyApiClient})
      : assert(dummyApiClient != null);

  Future<Categories> fetchDummy() async {
    return await dummyApiClient!.fetchDummy();
  }
}

You can initialize this repository in app generated routes or where you wanna initialize like

final ProductUpdateRepository _productUpdateRepository =
    ProductUpdateRepository(
  productUpdateApiClient: ProductUpdateApiClient(
    httpClient: http.Client(),
  ),
);

And then use bloc provider with instance or you can use multiBlocProviders if you wanna provider more than one instance of bloc.

BlocProvider(
                      create: (context) =>
                         DummyBloc(dummyRepository: _dummyRepository),
                    ),
child: SomeScreen(),
Raza Shabbir
  • 146
  • 5