Data From multiple FutureBuilders in flutter - flutter

I'm fetching data from an api source , the data is fetched properly , then i store the data in sqflite , so basically after doing both , i need to check if there is connection so that i show data from internet other than that i get data back from database , now since i'm using futurebuilder which return internet async operation result , how would i be also to get list of data from database , any help is appreciated guys and thank you in advance.
This is what i have tried so far
#override
void initState() {
super.initState();
dbHelper = DbHelper();
}
#override
Widget build(BuildContext context) {
return Scaffold (
appBar: AppBar(
title: Text("News Application"),
centerTitle: true,
backgroundColor: Colors.black,
titleTextStyle: TextStyle(color: Colors.white),
),
body: FutureBuilder (
future: Future.wait([getEverything(),dbHelper.getAllNews()]),
builder: (BuildContext context, AsyncSnapshot<List<dynamic>> snapshot) {
if(snapshot.hasError) {
// So basically here if there is an error , i woul like to show data from database
// i tried to get data from snapshot like this : snapshot.data[0]...and snapshot.data[1]
// but no data is returned..
return new Center(
child: new CircularProgressIndicator(
backgroundColor: Colors.black,
),
);
} else {
if(snapshot.connectionState == ConnectionState.done){
return new Container(
color: Colors.black,
child: GridView.count(
padding: const EdgeInsets.all(20),
crossAxisCount: 2,
children: List.generate(snapshot.data.articles.length, (index) {
return new GestureDetector(
onTap: (){
Navigator.push(
context,
MaterialPageRoute(builder: (context) => DetailsScreen(
image: snapshot.data.articles[index].urlToImage,
author: snapshot.data.articles[index].author,
title: snapshot.data.articles[index].title,
description: snapshot.data.articles[index].description,
publishedAt: snapshot.data.articles[index].publishedAt,
content: snapshot.data.articles[index].content,
))
);
},
child: Card(
elevation: 12,
child: new Column(
children: [
Image.network(snapshot.data.articles[index].urlToImage,
width: 250,),
Text(snapshot.data.articles[index].description)
],
),
),
);
}
)));
}
}
return new Center(
child: Visibility(
visible: true,
child: CircularProgressIndicator(
backgroundColor: Colors.black,
),
),
);
},
),
);
}

Related

Class '_JsonDocumentSnapshot' has no instance getter 'docs'. Receiver: Instance of '_JsonDocumentSnapshot' Tried calling: docs

#override
Widget build(BuildContext context) {
File? myImage;
User? user = FirebaseAuth.instance.currentUser;
return Scaffold(
appBar: AppBar(
title: const Text('Settings Page'),
centerTitle: true,
backgroundColor: Colors.blueGrey,),
body: Center(
child: FutureBuilder(
future: FirebaseFirestore.instance.collection('users').doc(user!.uid).get(),
builder: (context,AsyncSnapshot snapshot) {
if(snapshot.hasData) {
var emmi = snapshot.data;
return ListView.builder(
itemCount: emmi.docs.length,
itemBuilder: (context,index) {
return Column(
children: [
ListTile(
leading: ClipRRect(
borderRadius: BorderRadius.circular(80),
child: CachedNetworkImage(
imageUrl:emmi['image'],
height:120,
),
),
),
SizedBox(height: 15,),
ElevatedButton(onPressed: selectFile, child: const Text("select file")),
ElevatedButton(onPressed: uploadFile, child: const Text("upload file")),
],
);
});
}
return Center(
child: Text("error"),
);
},
),
),
);
}
}
I'm doing a settings page and i'm trying to pull current user's image from firestore and then update the user's image.
i have been searching solutions for the problem but unfortunately i try every solution i found for the similiar error but error didnt go away.I appreciate if you have any answers.
i figured it out how to pull user's image and if anyone wants to do same thing here my solution
Widget build(BuildContext context) {
final user = FirebaseAuth.instance.currentUser;
return Scaffold(
appBar: AppBar(
title: const Text('Settings Page'),
centerTitle: true,
backgroundColor: Colors.blueGrey,),
body: StreamBuilder(
stream: FirebaseFirestore.instance.collection('users').where('uid', isEqualTo: user!.uid).snapshots(),
builder: (context,AsyncSnapshot snapshot) {
if(snapshot.hasData) {
if(snapshot.data.docs.length > 0) {
var snap = snapshot.data;
return ListView.builder(
itemCount: snap.docs.length,
itemBuilder: (context,index) {
var snaps = snapshot.data.docs[index];
return ListTile(
leading: ClipRRect(
borderRadius: BorderRadius.circular(150),
child: CachedNetworkImage(
imageUrl:snaps['image'],
placeholder: (conteext,url)=>CircularProgressIndicator(),
errorWidget: (context,url,error)=>Icon(Icons.error,),
height: 150,
),
),
);
});
}
} return Center(child: CircularProgressIndicator(),);
},
),
);
}

I cannot get the data from the firestore into my application

I am new to programming and while i was trying to create a small TODO app, i was able to save the data into cloud firestore but the problems ocurred when i tried to retrieve the data using Streambuilder. I was following old tutorials before null safety , so i suspect that issues are regarding the null safety.
The code works without any errors in android studio but the data from firestore can't be retrieved.
The code is as follows:
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class AddTODOlist extends StatelessWidget {
static String id = 'add_todolist';
final TextEditingController _controller = TextEditingController();
void _addUser(){
FirebaseFirestore.instance.collection("Todos").add({"title" : _controller.text});
_controller.text = "";
}
Widget _buildList(QuerySnapshot? snapshot){
return ListView.builder(
itemCount: snapshot!.docs.length,
itemBuilder: (context, index){
final doc = snapshot.docs[index];
final map = (doc.data()as dynamic)['title'];
return ListTile(
title: Text(map,style: TextStyle(color: Colors.black),),
);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Loan System',),
centerTitle: true,
),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Row(
children: [
Expanded(
child: TextField(
controller: _controller,
decoration: InputDecoration(
hintText: 'Add new user',
),
),
),
TextButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(Colors.blue),
),
onPressed:(){
_addUser();
},
child: Text('Add',
style: TextStyle(
color: Colors.white,
),),
),
],
),
StreamBuilder<QuerySnapshot?>(
stream: FirebaseFirestore.instance.collection('todos').snapshots(),
builder: (context, snapshot){
if(!snapshot.hasData) return LinearProgressIndicator();
else {
return Expanded(
child: _buildList(snapshot.data),
);
}
}
),
],
),
),
),
);
}
}
You have an error in the spelling of the collection name. Remember that Firestore is case sensitive
Todos vs todos
FirebaseFirestore.instance.collection("Todos").add({"title" : _controller.text});
and here:
stream: FirebaseFirestore.instance.collection('todos').snapshots(),
Let me know if this does not help

Displaying main screen to old user and an info screen to a new user before the main screen

So I have a main screen that I want to display straight away to an old user of the app (Meaning token has been set) but to a new user, I want to display a column with some information etc. first and after the user presses the button it will open the main screen. However, the below code doesn't work as I wish (this doesn't change the view in any way). What would be the correct approach to this problem?
#override
Widget build(BuildContext context) {
return FutureBuilder<bool>(
future: getPrefs(),
builder: (context, AsyncSnapshot<bool> snapshot) {
if (snapshot.hasData) {
if(token == null){
return Column(
verticalDirection: VerticalDirection.up,
children: [
ElevatedButton(
onPressed: (){
return mainScreen();
},
),
],
);
}
else{
return mainScreen();
}
} else {
return CircularProgressIndicator();
}
}
);
Widget mainScreen(){
return Scaffold(
appBar: AppBar(
title: Text('Feed planner',
style: TextStyle(fontSize: 17),
),
toolbarHeight: 50,
actions: [
IconButton(icon: icon, onPressed: _pushSettings),
],
),
body: Center(
child: Column(
children: [
Expanded(child: _buildGrid()),
]
)
)
);
}
Edit 1, after OP provided more info:
Make your homescreen widget like this:
Widget mainScreen(bool token){
return Scaffold(
appBar: AppBar(
title: Text('Feed planner',
style: TextStyle(fontSize: 17),
),
toolbarHeight: 50,
actions: [
IconButton(icon: icon, onPressed: _pushSettings),
],
),
body: Center(
child: Column(
children: [
token == null ? Text('Add your text or widget here for new users') : Container()
Expanded(child: _buildGrid()),
]
)
)
);
}
And your Future builder like this:
FutureBuilder<bool>(
future: getPrefs(),
builder: (context, AsyncSnapshot<bool> snapshot) {
if (snapshot.hasData) {
return mainScreen(snapshot); //or the token you are getting
}
else {
return CircularProgressIndicator();
}
})
The problem is here:
ElevatedButton(
onPressed: (){
return mainScreen();
},
)
You should use:
ElevatedButton(
onPressed: (){
Navigator.pushNamed(context, '/mainScreen'); //or whatever the name of your home screen is in routes.
},
)

How can I access the innermost documents in nested collection structures?

As seen in the picture, there is a collection structure within the firestore. I want to show it with a listview by reaching the document information at the end. But I can't view it on the screen.
Code here:
#override
Widget build(BuildContext context) {
randevular = databaseRef
.collection(
'kuaforumDB/$_salonID/BekleyenRandevular/')
.snapshots();
return StreamBuilder<QuerySnapshot>(
stream: randevular,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if(!snapshot.hasData) {
return Column(
children:<Widget> [
SizedBox(
height: 100,
),
Center(
child: Image.asset("assets/images/icons/fon.webp",matchTextDirection: true,
height: 140.0,
width: 140.0,
),),
SizedBox(
height: 20
),
Center(
child: new Text('Henüz bir randevu oluşturmadınız.')
)
],
);
}
else if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: new Center(
child: new CircularProgressIndicator(
value: null,
strokeWidth: 7.0,
),
)
);
} else {
return ListView(
children: snapshot.data.documents
.map((document) {
var query = databaseRef
.collection('kuaforumDB/')
.document('$_salonID')
.collection('BekleyenRandevular')
.document(document.documentID)
.collection('get')
.snapshots();
return StreamBuilder<QuerySnapshot> (
stream: query,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot2){
if (!snapshot2.hasData) return Text("Loading...");
return ListView(
children: snapshot2.data.documents
.map((DocumentSnapshot doc) => Card(
child: ListTile(
leading: IconButton(
tooltip: '',
icon: const Icon(Icons.check_circle, color: Colors.red,),
color: doc['randevuTarih']
.toDate()
.isBefore(DateTime.now())
? Colors.green
: Colors.orangeAccent,
iconSize: 30,
onPressed: () {},
),
title: Text(AppConstants.formatter
.format((doc['randevuTarih'].toDate())
.add(Duration(hours: 0)))
.toString()),
subtitle: Text('Randevu Onay Bekleniyor.'),
trailing: Icon(Icons.keyboard_arrow_right,
color: Colors.grey, size: 30.0),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (content) => MyPendingDetailPage(
salonID: _salonID.toString(),
userID: mPhone,
randevuID:
doc.documentID.toString(),
randevuTarih: AppConstants
.formatter
.format((doc['randevuTarih']
.toDate())
.add(Duration(hours: 0)))
.toString(),
randevuHizmet: doc['hizmetler'],
randevuFiyat:
doc['fiyat'].toString(),
randevuSure:
doc['sure'].toString(),
randevuFavori:
doc['favori'] == null
? false
: doc['favori'],
randevuBittimi:
doc['randevuTarih']
.toDate()
.isBefore(
DateTime.now())
? true
: false,
ayBasi: startofmonth,
sonrandevu : doc['randevuTarih'],
)));
}, )))
.toList(),
);
},
);
}).toList());
}
});
}
Using nested Listview in the code above may have caused a question. But I don't know how to solve this. When I check it, I see that I can actually pull the data, but I can't show it on the screen.

Problem pageview reload first page after setState ( Flutter )

I have a code, this code create a pageview about some user, data is get from firebase
return new Scaffold(
appBar: new AppBar(
title: new Text("Carousel"),
),
body: StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('users').snapshots(),
builder:
(BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) return new Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return new CircularProgressIndicator();
default:
return new PageView(
onPageChanged: _onPageViewChange,
controller: _controller,
scrollDirection: Axis.horizontal,
children:
snapshot.data.documents.map((DocumentSnapshot document) {
return new Column(
children: <Widget>[
new Container(
child: new ClipOval(
child: new CachedNetworkImage(
width: 150.0,
height: 150.0,
imageUrl: document['img'],
fit: BoxFit.fill,
placeholder: (context, url) =>
CircularProgressIndicator(),
errorWidget: (context, url, error) =>
Icon(Icons.error),
)),
),
new ListTile(
title: new Text(
isPerson
? 'My name is'
: (isPlace
? 'My favourite is'
: (isNote
? 'I am from'
: (isPhone
? 'My phone is'
: (isLock ? '' : '')))),
textAlign: TextAlign.center),
subtitle: new Text(
isPerson
? document['name']
: (isPlace
? document['place']
: (isNote
? document['note']
: (isPhone
? document['phone']
: (isLock
? document['lock'].toString()
: "")))),
textAlign: TextAlign.center,
),
),
buildButton1(Icons.person)
],
);
}).toList(),
);
}
},
));
}
this is fuction buildButton1()
Widget buildButton1(IconData icon) {
return new Column(
children: <Widget>[
new Container(
padding: EdgeInsets.only(left: 10.0, right: 10.0, top: 20.0),
child: new IconButton(
icon: Icon(icon),
onPressed: () {
setState(() {
//isChecked ? true : false;
isPerson = true;
isNote = false;
isPlace = false;
isPhone = false;
isLock = false;
});
},
iconSize: 32.0,
color: isPerson ? Colors.green : Colors.grey,
),
)
],
);
}
When I press a button to set variable then Pageview reload and show firstpage. How can I solved this problem. This is example picture https://imgur.com/nKC358E
................................................................................................
The issue comes from the _onPageViewChange function.
The last page doesn't return an integer value. If you have 3 pages, than the last returned index will be 1.99999999999... and not 2.
I solved the problem like this
onPageChanged: (index){
setState(() {
if (index > 1.99){
lastPage=true;
}else{
lastPage=false;
}
});
}