You can use something similar to BloC pattern to implement Firebase Realtime Database on a StreamBuilder.
Create a model for your Card Info first. You can also include the json parser on the same class.
class CardInfo{
String? cvv;
String? cardHolder;
String? number;
String? expiry;
CardInfo({this.cvv, this.cardHolder,
this.number, this.expiry});
factory CardInfo.fromJson({required Map<dynamic,dynamic> json}){
return CardInfo(
cvv: json['CVV'],
cardHolder: json['Card Holder'],
number: json['Credit Card Number'],
expiry: json['Expiry Date'],
);
}
}
Add your Streams on a Bloc class
class Bloc {
final _repository = Repository();
final _cardInfoFetcher = StreamController<CardInfo>.broadcast();
/// The Stream that will be used on StreamBuilder
Stream<CardInfo> get userCardInfo => _cardInfoFetcher.stream;
fetchUserThreads(String? userId) async {
var cardInfo = CardInfo();
/// Query user card details
var userCardDetails = FirebaseDatabase.instance.reference().child('Users').child(userId)
.child('Card Info');
/// Fetch user card details once
var snapshot = await userCardDetails.once();
Map<dynamic, dynamic> userCardSnapshot = snapshot.value;
_cardInfoFetcher.sink.add(CardInfo.fromJson(json: userCardSnapshot));
}
/// Dispose Stream when not in use
dispose() {
_cardInfoFetcher.close();
}
}
final bloc = Bloc();
Every time bloc.fetchUserThreads(String) is called, StreamBuilder should do a widget rebuild.
StreamBuilder<CardInfo>(
stream: bloc.userCardInfo,
builder: (BuildContext context,
AsyncSnapshot<CardInfo> snapshot) {
if (!snapshot.hasData)
debugPrint('Snapshot empty');
else {
debugPrint('Card Holder: ${snapshot.data!.cardHolder}');
}
/// You can now populate child widget with CardInfo data from the snapshot
return Container();
}
)