type 'Future<dynamic>' is not a subtype of type 'Stream<dynamic>' getting data from Firebase - flutter

I'm retrieving data from Firebase Storage and Firestore, to show the items in a list with the icon (if the item is a file) or the image (if is image). The problem is, If I get all the images in one time it doesn't load all.. It loads at maximum 20 and crashes due to memory leaking. So My idea is to do a list which gets 10 elements by time, and when the user scroll down to the bottom of the results, it loads more 10 and subsequently. But, I was using Future builder and with it I cant update the list when I need and the problem continues, so now, I'm trying to get in a stream and show with a StreamBuilder to be able to update the list dynamically.
this is my controller:
loadList(String submenu, [int limit]) async {
var parts = submenu.split('/');
var pathSlashless = parts[0].trim();
var subPathSlashless = parts.sublist(1).join('/').trim();
var snapshot = await _storage.ref().child("/${submenu}");
var retorno = await snapshot.listAll();
List<ItemLab> conteudo = [];
if(subPathSlashless.isEmpty || subPathSlashless == null){
retorno.prefixes.forEach((element) {
conteudo.add(
ItemLab(
tipo: 'PASTA',
elemento: element,
),
);
});
}
for(int i = 0; i < retorno.items.length ; i++){
var url = await retorno.items[i].getDownloadURL();
conteudo.add(
ItemLab(
tipo: 'FILE',
elemento: retorno.items[i],
imageUrl: url,
),
);
if(limit != null){
if(conteudo.length > limit){
hasMore = true;
return Stream.value(conteudo);
}else{
hasMore = false;
print("less than 9");
}
}
}
try {
if(subPathSlashless.isNotEmpty){
print(subPathSlashless);
List items;
await databaseReference
.collection("lab_${pathSlashless}_url")
.snapshots().forEach((element) {
element.docs.forEach((f) {
if(f.data()['videos'] != null){
items == null ? items = f.data()['videos'] :
items.addAll(f.data()['videos']);
};
print("ITEMS :::: >>> ${items}");
});
});
for(int i = 0; i < items.length; i ++){
//print(items[i]);
conteudo.add(
ItemLab(
tipo: 'VIDEO',
elemento: null,
video: items[i],
),
);
}
}else{
await databaseReference
.collection("lab_${pathSlashless}_url")
.snapshots().forEach((element) {
element.docs.forEach((f) {
if(f.data().isNotEmpty){
print(f.data());
if(f.data().keys.contains("videos")){
conteudo.add(
ItemLab(
tipo: 'PASTA',
pastaVideo: findFolderName(f.reference.path)
),
);
}else{
conteudo.add(
ItemLab(
tipo: 'VIDEO',
elemento: null,
video: f.data(),
),
);
}
}
});
});
}
}catch(e){
print(e);
}
pathSlashless = null;
subPathSlashless = null;
conteudo = checkDuplicateFolder(conteudo, submenu);
return Stream.value(conteudo);
}
And here my list:
return StreamBuilder(
stream: ctrl.loadList(submenu),
builder: (ctx, snapshot) {
But, if I run this code it throws this error:
type 'Future' is not a subtype of type 'Stream'
How Can I handle that to be able to update the list dynamically using a stream instead of a Future

You can't await .snapshots(), as it returns stream, you can change it to get. Also learn more about flutter firebase realtime and normal use case, check the flutter fire docs
loadList(String submenu, [int limit]) async {
var parts = submenu.split('/');
var pathSlashless = parts[0].trim();
var subPathSlashless = parts.sublist(1).join('/').trim();
var snapshot = await _storage.ref().child("/${submenu}");
var retorno = await snapshot.listAll();
List<ItemLab> conteudo = [];
if(subPathSlashless.isEmpty || subPathSlashless == null){
retorno.prefixes.forEach((element) {
conteudo.add(
ItemLab(
tipo: 'PASTA',
elemento: element,
),
);
});
}
for(int i = 0; i < retorno.items.length ; i++){
var url = await retorno.items[i].getDownloadURL();
conteudo.add(
ItemLab(
tipo: 'FILE',
elemento: retorno.items[i],
imageUrl: url,
),
);
if(limit != null){
if(conteudo.length > limit){
hasMore = true;
return Stream.value(conteudo);
}else{
hasMore = false;
print("less than 9");
}
}
}
try {
if(subPathSlashless.isNotEmpty){
print(subPathSlashless);
List items;
(await databaseReference
.collection("lab_${pathSlashless}_url")
.get()).docs.forEach((f) {
if(f.data()['videos'] != null){
items == null ? items = f.data()['videos'] :
items.addAll(f.data()['videos']);
};
print("ITEMS :::: >>> ${items}");
});
for(int i = 0; i < items.length; i ++){
//print(items[i]);
conteudo.add(
ItemLab(
tipo: 'VIDEO',
elemento: null,
video: items[i],
),
);
}
}else{
(await databaseReference
.collection("lab_${pathSlashless}_url")
.get()).docs.forEach((f) {
if(f.data().isNotEmpty){
print(f.data());
if(f.data().keys.contains("videos")){
conteudo.add(
ItemLab(
tipo: 'PASTA',
pastaVideo: findFolderName(f.reference.path)
),
);
}else{
conteudo.add(
ItemLab(
tipo: 'VIDEO',
elemento: null,
video: f.data(),
),
);
}
}
});
}
}catch(e){
print(e);
}
pathSlashless = null;
subPathSlashless = null;
conteudo = checkDuplicateFolder(conteudo, submenu);
return conteudo;
}
And the list
return FutureBuilder(
future: ctrl.loadList(submenu),
builder: (ctx, snapshot) {

Related

How to print the notification content in the terminal - Flutter

I am trying to print the content of the notification that comes through PHP (topics) How to print the content of the notification in the terminal using Flutter?
code:
class PushNotificationService {
late BuildContext context;
PushNotificationService({required this.context});
Future initialise() async {
FirebaseMessaging.instance.subscribeToTopic('TopicToListen');
print('firebase_token->initialize===${messaging == null}==');
iOSPermission();
print('firebase_token->initialize=///');
messaging.getToken();
print('firebase_token->initialize==**');
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('ic_launcher');
/* const IOSInitializationSettings initializationSettingsIOS = IOSInitializationSettings();
const MacOSInitializationSettings initializationSettingsMacOS = MacOSInitializationSettings();*/
final DarwinInitializationSettings initializationSettingsIOS =
DarwinInitializationSettings(
requestAlertPermission: false,
requestBadgePermission: false,
requestSoundPermission: false,
onDidReceiveLocalNotification:
(int id, String? title, String? body, String? payload) async {
/* didReceiveLocalNotificationStream.add(
ReceivedNotification(
id: id,
title: title,
body: body,
payload: payload,
),
);*/
},
);
/*const InitializationSettings initializationSettings =
InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS,
macOS: initializationSettingsMacOS);*/
final InitializationSettings initializationSettings =
InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS,
);
/*flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: (String? payload) async {
print("payload*****$payload");
selectNotificationPayload(payload);
});*/
await flutterLocalNotificationsPlugin.initialize(
initializationSettings,
onDidReceiveNotificationResponse:
(NotificationResponse notificationResponse) {
switch (notificationResponse.notificationResponseType) {
case NotificationResponseType.selectedNotification:
selectNotificationPayload(notificationResponse.payload!);
break;
case NotificationResponseType.selectedNotificationAction:
print(
"notification-action-id--->${notificationResponse.actionId}==${notificationResponse.payload}");
break;
}
},
onDidReceiveBackgroundNotificationResponse: backgroundMessage,
);
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
if (message.data != null) {
var data = message.data;
var notif = message.notification;
if (data['type'] == "default" || data['type'] == "category") {
var title = data['title'].toString();
var body = data['message'].toString();
var image = data['image'];
var payload = data["news_id"];
if (payload == null) {
payload = "";
} else {
payload = payload;
}
if (image != null && image != "") {
if (notiEnable!) {
generateImageNotication(title, body, image, payload);
}
} else {
if (notiEnable!) {
generateSimpleNotication(title, body, payload);
}
}
} else {
//Direct Firebase Notification
var title = notif?.title.toString();
var msg = notif?.body.toString();
var img = notif?.android?.imageUrl.toString();
if (notiEnable!) {
(img != null)
? generateImageNotication(title!, msg!, img, '')
: generateSimpleNotication(title!, msg!, '');
}
}
}
});
messaging.getInitialMessage().then((RemoteMessage? message) async {
bool back = await getPrefrenceBool(ISFROMBACK);
print("message******$message");
if (message != null && back) {
var data = message.data;
var notif = message.notification;
if (data['type'] == "default" || data['type'] == "category") {
var title = data['title'].toString();
var body = data['message'].toString();
var image = data['image'];
var payload = data["news_id"];
if (payload == null) {
payload = "";
} else {
payload = payload;
}
if (image != null && image != "") {
if (notiEnable!) {
generateImageNotication(title, body, image, payload);
}
} else {
if (notiEnable!) {
generateSimpleNotication(title, body, payload);
}
}
} else {
//Direct Firebase Notification
var title = notif?.title.toString();
var msg = notif?.body.toString();
var img = notif?.android?.imageUrl.toString();
if (notiEnable!) {
(img != null)
? generateImageNotication(title!, msg!, img, '')
: generateSimpleNotication(title!, msg!, '');
}
}
setPrefrenceBool(ISFROMBACK, false);
}
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async {
print("message******$message");
if (message.data != null) {
var data = message.data;
var notif = message.notification;
if (data['type'] == "default" || data['type'] == "category") {
var title = data['title'].toString();
var body = data['message'].toString();
var image = data['image'];
var payload = data["news_id"];
if (payload == null) {
payload = "";
} else {
payload = payload;
}
if (image != null && image != "") {
if (notiEnable!) {
generateImageNotication(title, body, image, payload);
}
} else {
if (notiEnable!) {
generateSimpleNotication(title, body, payload);
}
}
} else {
//Direct Firebase Notification
var title = notif?.title.toString();
var msg = notif?.body.toString();
var img = notif?.android?.imageUrl.toString();
if (notiEnable!) {
(img != null)
? generateImageNotication(title!, msg!, img, '')
: generateSimpleNotication(title!, msg!, '');
}
}
}
setPrefrenceBool(ISFROMBACK, false);
});
}
void iOSPermission() async {
await messaging.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
}
//when open dynamic link news index and id can used for fetch specific news
Future<void> getNewsById(
String id,
String index,
) async {
var param = {
NEWS_ID: id,
ACCESS_KEY: access_key,
// ignore: unnecessary_null_comparison
USER_ID: CUR_USERID != null && CUR_USERID != "" ? CUR_USERID : "0",
LANGUAGE_ID: CUR_LANGUAGE_ID
};
var apiName = getNewsByIdApi;
http.Response response = await http
.post(Uri.parse(apiName), body: param, headers: headers)
.timeout(Duration(seconds: timeOut));
var getdata = json.decode(response.body);
String error = getdata["error"];
if (error == "false") {
var data = getdata["data"];
List<News> news = [];
news = (data as List).map((data) => new News.fromJson(data)).toList();
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => NewsDetails(
model: news[0],
index: int.parse(index),
id: news[0].id,
isDetails: true,
news: [],
)));
}
}
selectNotificationPayload(String? payload) async {
if (payload != null && payload != "") {
debugPrint('notification payload: $payload');
getNewsById(payload, "0");
} else {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MyApp()),
);
}
}
}
I searched so much in the firebase documentation and couldn't find anything that could help me with the issue.
I would appreciate your help
I inserted the following line into the main.dart file
And I got the notification content in the terminal.
Hope this helps people in the future
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
print('Handling a background message ${message.notification?.body}');
}

Flutter: Need to load values and then make a firebase query for Futurebuilder caused RangeError (index)

I'm trying to load the geo location first. Then I use this value to start a query which events are in a certain radius from this location.
I want to display these events in a FutureBuilder.
My problem:
I have to initialize Future<List> futureEvents in the onInit state, otherwise Flutter complains. At the time he didn't have the location yet.
So I call the function again at the end.
So it happens that the error "RangeError (index): Invalid value: Valid value range is empty :1" is thrown until the method is called again after receiving the geo-location and I get the data.
Sorry for bad coding. One of my first Projects
The InitState:
class _LocationPageState extends State<LocationPage> {
String? _currentAddress;
Position? _currentPosition;
late Future<List<Events>> futureEvents;
double locationRadius = 5;
#override
void initState() {
super.initState();
_getCurrentPosition();
futureEvents = _getEvents();
}
The called functions:
Future<void> _getCurrentPosition() async {
final hasPermission = await _handleLocationPermission();
if (!hasPermission) return;
await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high)
.then((Position position) {
setState(() => _currentPosition = position);
_getAddressFromLatLng(_currentPosition!);
}).catchError((e) {
debugPrint(e);
});
}
Future<void> _getAddressFromLatLng(Position position) async {
await placemarkFromCoordinates(
_currentPosition!.latitude, _currentPosition!.longitude)
.then((List<Placemark> placemarks) {
Placemark place = placemarks[0];
setState(() {
_currentAddress = ' ${place.postalCode} ${place.locality} ';
});
currentPLZ = place.postalCode.toString();
futureEvents = _getEvents() as Future<List<Events>>;
}).catchError((e) {
debugPrint(e);
});
}
Future<List<Events>> _getEvents() async {
// get all PLZ in a radius
final response = await http.get(Uri.parse(
'https://www.suche-postleitzahl.org/geo-api.json?action=plz-umkreis&subaction=umkreis-osm&plz=' +
currentPLZ +
'&radius=' + locationRadius.toString()));
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
var jsondataPlz = jsonDecode(response.body);
List<PLZData> plzdataList = [];
for (var u in jsondataPlz) {
PLZData plzData = PLZData(u['postal_code'], u['name'], u['distance']);
plzdataList.add(plzData);
}
print(plzdataList.length);
print(plzdataList[1].name +
" Distanz:" +
plzdataList[1].distance +
" PLZ only" +
plzdataList[1].postal_code);
// get all events in the radius
List<Events> events = [];
if (plzdataList.isNotEmpty) {
for (var i = 0; plzdataList.length > i; i++) {
var singleEvent = await FirebaseFirestore.instance
.collection('Events')
.where('postCode', isEqualTo: plzdataList[i].postal_code)
.get();
if (singleEvent.docs.isNotEmpty) {
var singleEventList =singleEvent.docs.map((d) => Events.fromJson(d.data())).toList();
//add distance and regionname
for(var j = 0; singleEventList.length > j; j++){
singleEventList[j].distance = plzdataList[i].distance;
singleEventList[j].regionName = plzdataList[i].name;
}
events = events + singleEventList;
if (events[0].userID != null) {
print(events[0].userID);
print(events[i].distance);
}
}
}
}
//get userdata to the events
if (events.isEmpty) {
print("Es wurden keine Events gefunden");
} else {
for (var i = 0; events.length > i; i++) {
var userInformationSnap = await FirebaseFirestore.instance
.collection('users')
.where('__name__', isEqualTo: events[i].userID)
.get();
events[i].userInformation = userInformationSnap.docs
.map((d) => UsersForPosts.fromJson(d.data()))
.toList();
print(events[i].userInformation[0].username);
}
}
return events;
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load');
}
}
The FutureBuilder
FutureBuilder<List<Events>>(
future: futureEvents,
builder: (context, snapshot) {
if (snapshot.hasData &&
snapshot.connectionState == ConnectionState.done) {
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(), //<--here
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return Eventcard(
userPhoto: snapshot.data?[index].userInformation[0]
.userPhoto ?? "keine Info",
age: snapshot.data?[index].userInformation[0].age ??
"keine Info",
username: snapshot.data?[index].userInformation[0]
.username ?? "keine Info",
gender: snapshot.data?[index].userInformation[0]
.gender ?? "keine Info",
meetState: snapshot.data?[index].meetState ??
"keine Info",
postCode: snapshot.data?[index].postCode ??
"keine Info",
distance: snapshot.data?[index].distance ??
"keine Info",
regionName: snapshot.data?[index].regionName ??
"keine Info",
comment: snapshot.data?[index].comment ??
"keine Info",
headline: snapshot.data?[index].headline ??
"keine Info",
);
},
);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
} else {
// By default, show a loading spinner.
return const CircularProgressIndicator();
}
},
),
Have you tried to just put the _getEvents() Future inside the FutureBuilder directly instead of using it as a late variable? I’m also confused by this format… why use a Future and a FutureBuilder? It seems like you could just create an empty list events = [] then in the initState call a new async function where you fetch the events from Firestore and use that data to update the events list through setState. Then take away the FutureBuilder and just use a ListView.builder. Just search how to create a ListView from a list, it’s very simple.

How to put code with if in a separate method?

I'm using app navigation but I'm facing a problem that I can't put the if (initialLink != null)... code in a separate method so that I can then duplicate this method in different parts of the code, can you tell me how can I put this code in a separate method?
class AppRouter {
final BuildContext context;
AppRouter(this.context);
RouteMap buildRouteMap(PendingDynamicLinkData? initialLink) {
return RouteMap(
onUnknownRoute: (route) => const Redirect('/'),
routes: {
'/': (route) {
bool loggedIn =
Provider.of<AppState>(context, listen: false).isLoggedIn;
if (initialLink != null) {
String code;
final Uri deepLink = initialLink.link;
final String deeplinkString = deepLink.toString();
code = deepLink.queryParameters['code'] ?? 'No code';
var start = deeplinkString.lastIndexOf('/') + 1;
var end = deeplinkString.indexOf('?');
var extract = deeplinkString.substring(start, end);
if (extract == 'password-reset') {
return Redirect(
'/login/forgot-password',
queryParameters: {
'isSendEmail': 'true',
'code': code,
},
);
}
}
return const MaterialPage(
child: PhoneNumberPage(),
);
},
'/map': (route) {
bool loggedIn =
Provider.of<AppState>(context, listen: false).isLoggedIn;
if (loggedIn) {
return const Redirect('/home');
}
return const MaterialPage(
child: MapPage(
isUserAuth: false,
),
);
},
code to be placed in a separate function
if (initialLink != null) {
String code;
final Uri deepLink = initialLink.link;
final String deeplinkString = deepLink.toString();
code = deepLink.queryParameters['code'] ?? 'No code';
var start = deeplinkString.lastIndexOf('/') + 1;
var end = deeplinkString.indexOf('?');
var extract = deeplinkString.substring(start, end);
if (extract == 'password-reset') {
return Redirect(
'/login/forgot-password',
queryParameters: {
'isSendEmail': 'true',
'code': code,
},
);
}
}
try this.
void commonFunction(){
if (initialLink != null) {
String code;
final Uri deepLink = initialLink.link;
final String deeplinkString = deepLink.toString();
code = deepLink.queryParameters['code'] ?? 'No code';
var start = deeplinkString.lastIndexOf('/') + 1;
var end = deeplinkString.indexOf('?');
var extract = deeplinkString.substring(start, end);
if (extract == 'password-reset') {
return Redirect(
'/login/forgot-password',
queryParameters: {
'isSendEmail': 'true',
'code': code,
},
);
}
}
}
then call commonFunction() every where you need.
You use initialLink as the judgement of if..else condition. When you extract them you need to provide that parameter. Otherwise the code cannot find initialLink.
void commonFunction(PendingDynamicLinkData? initialLink){
if (initialLink != null) {
String code;
final Uri deepLink = initialLink.link;
final String deeplinkString = deepLink.toString();
code = deepLink.queryParameters['code'] ?? 'No code';
var start = deeplinkString.lastIndexOf('/') + 1;
var end = deeplinkString.indexOf('?');
var extract = deeplinkString.substring(start, end);
if (extract == 'password-reset') {
return Redirect(
'/login/forgot-password',
queryParameters: {
'isSendEmail': 'true',
'code': code,
},
);
}
}
}

StreamBuilder doesn't updating items when I get more

I have a list with all the items from that folder, and I'm retrieving the data with 10 items per time (first load 10, when user reach the list finish, it loads more 10). The problem Is, when list have to be updated, it is not.
It doesn't add the new items in the list.
This is the method I get data from firebase:
Future<void> loadnovo(
{String submenu,
int limit = 10,
bool cls = false,
bool initialLoad = false,
int lastIndex}) async {
if (cls) {
conteudo.clear();
hasMore = true;
}
if (_isLoading || !hasMore) {
return Future.value();
}
_isLoading = true;
var parts = submenu.split('/');
var pathSlashless = parts[0].trim();
var subPathSlashless = parts.sublist(1).join('/').trim();
var snapshot = await _storage.ref().child("/${submenu}");
var retorno = await snapshot.listAll();
if (subPathSlashless.isEmpty || subPathSlashless == null) {
retorno.prefixes.forEach((element) {
conteudo.add(
ItemLab(
tipo: 'PASTA',
elemento: element,
),
);
_streamController.add(conteudo);
});
}
for (int i = lastIndex; i < lastIndex + limit; i++) {
var url = await retorno.items[i].getDownloadURL();
conteudo.add(
ItemLab(
tipo: 'FILE',
elemento: retorno.items[i],
imageUrl: url,
),
);
print(conteudo);
print(conteudo.length);
_streamController.add(conteudo);
}
hasMore = true;
}
This is my Screen with the Stream builder, a gridView (which show the items) and the scrollListener:
LabController ctrlLab;
final lab = LabMdScreen();
inal scrollController = ScrollController();
int lastIndex = 0;
scrollListener() async {
if (scrollController.position.maxScrollExtent == scrollController.offset) {
lastIndex += 10;
ctrlLab.loadList(submenu: "ph/Res", lastIndex: lastIndex);
}
}
#override
void initState() {
ctrlLab = LabController();
ctrlLab.loadList(submenu: "ph/Res", lastIndex: lastIndex,cls: true, initialLoad: true);
scrollController.addListener(scrollListener);
super.initState();
}
#override
void dispose() {
scrollController.removeListener(scrollListener);
super.dispose();
}
loadBasicStructureDetail(submenu ,callback, context, deviceSize){
return StreamBuilder(
stream: ctrlLab.stream,
builder: (ctx, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.error != null) {
print(snapshot.error);
return Center(child: Text('Ocorreu um erro!'));
}else {
return GridView.builder(
padding: EdgeInsets.all(10.0),
controller: scrollController,
itemCount: snapshot.data.length +1,
itemBuilder: (ctx, i) {
path = callback;
if (i < snapshot.data.length) {
ItemLab item = snapshot.data[i];
>>>> here my code to format the tiles...
What I'm missing here
Try removing
if (_isLoading || !hasMore) {
return Future.value();
}

How to transform a Future method in a Stream method to feed a list

I have this method to feed my list, but with it i'm not able to change items dynamically ( add items, drop it...) :
loadLab(String submenu, [int limit]) async {
var parts = submenu.split('/');
var pathSlashless = parts[0].trim();
var subPathSlashless = parts.sublist(1).join('/').trim();
var snapshot = await _storage.ref().child("/${submenu}");
var retorno = await snapshot.listAll();
List<ItemLab> conteudo = [];
if(subPathSlashless.isEmpty || subPathSlashless == null){
retorno.prefixes.forEach((element) {
conteudo.add(
ItemLab(
tipo: 'PASTA',
elemento: element,
),
);
});
}
if(limit != null){
if(conteudo.length > limit){
hasMore = true;
return Stream.value(conteudo);
}else{
hasMore = false;
print("menor quen ove");
}
}
}
try {
if(subPathSlashless.isNotEmpty){
print(subPathSlashless);
List items;
await databaseReference
.collection("lab_${pathSlashless}_url")
.snapshots().forEach((element) {
element.docs.forEach((f) {
if(f.data()['videos'] != null){
items == null ? items = f.data()['videos'] :
items.addAll(f.data()['videos']);
};
print("ITEMS :::: >>> ${items}");
});
});
}catch(e){
print(e);
}
pathSlashless = null;
subPathSlashless = null;
conteudo = checkDuplicateFolder(conteudo, submenu);
print(conteudo);
return Stream.value(conteudo);
}
and the list>
return StreamBuilder(
stream: ctrlLab.loadLab(submenu),
throw this error:
type 'Future' is not a subtype of type 'Stream'
What I need to do to Make the return a Stream instead of a Future