Home > other >  Flutter : Attaching Stream data returned from Firestore stream function to flutter bloc
Flutter : Attaching Stream data returned from Firestore stream function to flutter bloc

Time:08-17

How to attach Stream data returned from Firestore stream function to flutter bloc ? how to attach this repository in bloc ?

class FirebaseChatApi{

Stream<List<ChatContactModel>>getChatContacts(){
FirebaseFirestore firestore = FirebaseFirestore.instance;
final FirebaseAuth auth = FirebaseAuth.instance;
return firestore.collection('users')
    .doc(auth.currentUser!.uid)
    .collection('chats')
    .snapshots().asyncMap((event)async{
  List<ChatContactModel>contacts = [];
  for(var document in event.docs){
    var chatContact = ChatContactModel.fromJson(document.data());
    //var userData = await firestore.collection('users').doc(chatContact.contactId).get();
    //ar user = UserModel.fromJson(userData.data()!);
    contacts.add(ChatContactModel(
        name: chatContact.name,
        profilePic: chatContact.profilePic,
        contactId: chatContact.contactId,
        timeSent: chatContact.timeSent,
        lastMessage: chatContact.lastMessage));
  }
  return contacts;
});

}

CodePudding user response:

If you use layered approach then in the infrastructure layer you can have repository class containing method:

class MyRepository implements IRepository{

@override
  Stream<List<MyObject>>> watchStream() async* {
    final doc = await _firestore.userDocument();
    yield* doc.myCollection
        .snapshots()
        .map(
          (snapshot) => List<MyObject>(
            snapshot.documents
                .map((doc) => converterIfNeeded(doc))
                .toImmutableList(),
          ),
        // do error checking here
        );
  }
//...
}

Then in the application layer you would have a file with a bloc

class MyBloc extends Bloc<MyEvent, MyState> {
  final IRepository _repository;

  MyBloc(this._repository) : super(Mytate.initial()) {
    on<_WatchMessages>((_onWatchMessages));
  }

  void _onWatchMessages(_WatchMessages event, Emitter<MyState> emit) async {
    await emit.forEach(_repository.watchMessages(),
        onData: ((List<MyObject> messages) {
      return state.copyWith(messages: List.from(messages));
    }));
  }
  // ...
  }

This example assumes the use of IRepository interface to get rid of application layer dependence on infrastructure layer.
It also assumes MyState class has a copyWith method which for example freezed can generate for you.

Example of MyState implementation:

@freezed
class MyState with _$MyState {
  const factory MyState({required List<MyObject> messages
// other properties of state here
}) = _MyState;

  factory MyState.initial() => const MyState(messages: []);
}

or something like this:

@freezed
class MyState with _$MyState {
  const factory MyState.initial() = Initial;
  const factory MyState.messageReceived(List<MyObject> messages) = MessageReceived;
  const factory MyState.failure(Failure f) = Failure;
}

CodePudding user response:

//My Bloc
part 'chat_contact_event.dart';
part 'chat_contact_state.dart';

class ChatContactBloc extends Bloc<ChatContactEvent,ChatContactState> {
ChatContactBloc() :super(LoadingChatContactState()) {
on<WatchChatContactsEvent>(_onWatchChatContactsEvent);
}

void _onWatchChatContactsEvent(
  WatchChatContactsEvent event,
  Emitter<ChatContactState> emit) async {
  await emit.forEach(FirebaseChatApi().getChatContacts(),
    onData:(List<ChatContactModel>chatContacts){
      return LoadedChatContactState(chatContacts:chatContacts);
});

}
}

//My Event

part of 'chat_contact_bloc.dart';

class ChatContactEvent extends Equatable {
const ChatContactEvent();

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

class WatchChatContactsEvent extends ChatContactEvent{ }

//My State

part of 'chat_contact_bloc.dart';


class ChatContactState extends Equatable {
const ChatContactState();
@override
List<Object?> get props => [];
}
class LoadingChatContactState extends ChatContactState{}

class LoadedChatContactState extends ChatContactState{
final List<ChatContactModel>chatContacts;
const LoadedChatContactState( { required this.chatContacts,});



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

//My Widget

Widget build(BuildContext context) {
return Scaffold(
extendBody: false,
backgroundColor: Colors.transparent,
appBar: AppBar(
  backgroundColor: Colors.black,
  centerTitle: true,
  title: const Text('Messages',style: TextStyle(color:Colors.white),),
),
body:  BlocBuilder<ChatContactBloc,ChatContactState>(
  builder: (context, state) {
    if(state is LoadingChatContactState){
      return const Center(
          child: CircularProgressIndicator());
    }
    else if(state is LoadedChatContactState){
      return ListView.builder(
        shrinkWrap: true,
        itemCount: state.chatContacts.length,
        itemBuilder: (context, index) {
          var chatContactData = state.chatContacts[index];
          return Column(
            children: [
              InkWell(
                onTap: () {
                  
                },
                child: Padding(
                  padding: const EdgeInsets.only(bottom: 8.0),
                  child: ListTile(
                    title: Text(
                      chatContactData.name,
                      //'Janam',
                      style: const TextStyle(
                        fontSize: 18,
                      ),
                    ),
                    subtitle: Padding(
                      padding: const EdgeInsets.only(top: 6.0),
                      child: Text(
                        //chatContactData.lastMessage
                        'LastMessage',
                        style: const TextStyle(fontSize: 15),
                      ),
                    ),
                    leading: CircleAvatar(
                      backgroundImage: NetworkImage(
                        // chatContactData.profilePic
                        '',
                      ),
                      radius: 30,
                    ),
                    trailing: Text(
                      '12:04',
                      //DateFormat.Hm().format(chatContactData.timeSent),
                      style: const TextStyle(
                        color: Colors.grey,
                        fontSize: 13,
                      ),
                    ),
                  ),
                ),
              ),
              const Divider(color: dividerColor, indent: 85),
            ],
          );
        },
      );
    }
    else{
      return Container();
    }

  }
  )

  );
}
  • Related