Flutter Retrieve Data from Firebase - firebase

I tried this tutorial
https://www.youtube.com/watch?v=ZiagJJTqnZQ
but my data didn't show, the length is still showing 0
This is my firebase https://i.imgur.com/D6kBpp8.png
Code
questions.dart
class Questions {
String question, questioner, status;
Questions(this.question, this.questioner, this.status);
}
timeline.dart
import 'package:flutter/material.dart';
import 'questions.dart';
import 'package:firebase_database/firebase_database.dart';
class TimeLine extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _TimeLineState();
}
}
class _TimeLineState extends State<TimeLine> {
final primaryColor = const Color(0xFF006FB9);
final bgColor = const Color(0xFFFEFEFE);
List<Questions> questionsList = [];
#override
void initState() {
super.initState();
DatabaseReference questionsRef = FirebaseDatabase.instance.reference().child("Questions");
questionsRef.once().then((DataSnapshot snap)
{
var KEYS = snap.value.keys;
var DATA = snap.value;
questionsList.clear();
for(var individualKey in KEYS) {
Questions questi = new Questions(
DATA[individualKey]['question'],
DATA[individualKey]['questioner'],
DATA[individualKey]['status'],
);
questionsList.add(questi);
}
setState(() {
print('Length : $questionsList.length');
});
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 1,
title: Text('Discover'),
backgroundColor: primaryColor,
),
backgroundColor: bgColor,
body: Container(
child: Text(
questionsList.length.toString()
)
/*questionsList.length == 0 ? new Text("No Blog Post Available") : new ListView.builder(
itemCount: questionsList.length,
itemBuilder: (_, index) {
return QuestionsGrid(questionsList[index].question, questionsList[index].questioner, questionsList[index].status);
}
),*/
),
);
}
Widget QuestionsGrid(String question, String questioner, String status) {
return new Container(
height: 1000,
width: 1000,
child: Text(
question
),
);
}
}

Your code is perfect but you have to change in to your firebase code line like
DatabaseReference questionsRef = FirebaseDatabase.instance.reference().child("questions");
Instand of
DatabaseReference questionsRef = FirebaseDatabase.instance.reference().child("Questions");
Thanks

Related

Stream Provider / Provider.of returning null when data is present

I was following a tutorial of sorts and got to a section where we print out what we have in the firestore database. However for some reason my Provider.of seems to be returning null when there is at least one data entry.
home.dart and MemoryList:
class Home extends StatelessWidget {
final AuthService _auth = AuthService();
#override
Widget build(BuildContext context) {
return StreamProvider<List<Person>>.value (
value: DatabaseService().memories,
initialData:[],
child: Scaffold(
backgroundColor: Colors.lightBlueAccent[50],
appBar: AppBar(
title: Text('Memory Bank'),
backgroundColor: Colors.deepPurple[300],
elevation: 0.0,
actions: <Widget>[
TextButton.icon(
icon: Icon(Icons.person),
label: Text('logout'),
onPressed: ()async{
await _auth.signOut();
},
),//textbutton
],//widget[]
),//appbar
body: MemoryList(),
)//scaffold
);//streamProvider.value
}
}
class MemoryList extends StatefulWidget {
#override
_MemoryListState createState() => _MemoryListState();
}
class _MemoryListState extends State<MemoryList> {
#override
Widget build(BuildContext context) {
final memories = Provider.of<List<Person>>(context);
print("current data:");
print(memories);
if(memories != null){
memories.forEach((element) {
print(element.name);
//print(element.name.events);
//print(element.name.likes);
});
}
return ListView.builder(
itemCount: memories.length,
itemBuilder: (context,index){
return MemoryTile(person: memories[index]);
}
);
}
}
For here the Provider.of<List>(context) returns with nothing.
The stream is:
final CollectionReference memoryCollection = FirebaseFirestore.instance.collection('memories');
Stream<List<Person>> get memories {
Stream<QuerySnapshot> snapshot_stream = memoryCollection.snapshots();
print("getting memories: ");
//print(snapshot_stream.first);
//print(snapshot_stream.first.toString());
return memoryCollection.snapshots().map(_memoryListFromSnapshot);
}
With a simple Person model with just a name:
class Person{
final String name;
Person({required this.name});
}
Any help would be appreciated!

Undefined class 'AllCoursesSnapshot'

I am trying to retrieve data from firebase database and display it on my UI. This is the code written :
class AllCourses {
String courseName;
String teacher;
String category;
AllCourses(this.courseName, this.teacher, this.category);
}
import 'package:creators_club/firestore/courses.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
class BusinessPage extends StatefulWidget {
#override
_BusinessPageState createState() => _BusinessPageState();
}
class _BusinessPageState extends State<BusinessPage> {
List<AllCourses> coursesList = [];
#override
void initState(){
super.initState();
DatabaseReference referenceAllCourses = FirebaseDatabase.instance.reference().child('AllCourses');
referenceAllCourses.once().then(((AllCoursesSnapshot allCoursesSnapshot){
coursesList.clear();
var keys = allCoursesSnapshot.value.keys;
var values = allCoursesSnapshot.value;
for(var key in keys){
AllCourses allCourses = new AllCourses(
values [key]["courseName"],
values [key]["teacher"],
values [key]["category"],
);
coursesList.add(allCourses);
}
setState(() {
//HERE
});
}));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.white),),
title: Text("Creator's Club"),
backgroundColor: Color(0xff2657ce),
elevation: 0,),
body: coursesList.length == 0 ? Center(child: Text("No Data Avail", style: TextStyle(fontSize: 15),)): ListView.builder(
itemCount: coursesList.length,
itemBuilder: (_,index){
return CardUI(coursesList[index].courseName, coursesList[index].teacher, coursesList[index].category);}
)
);
}
}
}
Why isn't the AllCoursesSnapshot being recognized? It says that it is "Type: Null Function(dynamic)".
Here is a picture of the database table in Realtime Database: (https://imgur.com/a/xDZy1SW).
It is not recognized because there is no class called AllCoursesSnapshot. The once() method belongs to the firebase_database plugin, and it returns a Future<DataSnapshot>, therefore you have to do the following:
referenceAllCourses.once().then((DataSnapshot dataSnapshot){
Also replace allCoursesSnapshot with dataSnapshot in the other parts of your code.

Can't get value of a List<Text> in container Flutter Firebase

I am trying to print the documentIDs of the documents present in my 'Menu' collection. But seems like the Widget is not getting the value of documentIDs List<Text> list. When I print the list in the addDocId function it does print the content of documentIDs but in the build widget if I print the list it only outputs - ('[]'). I can't figure out why it is getting docIds empty. Kindly help me out.
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
class Category extends StatefulWidget {
#override
_CategoryState createState() => _CategoryState();
}
class _CategoryState extends State<Category> {
bool _initialized = false;
bool _error = false;
initializeFlutterFire() async {
try {
await Firebase.initializeApp();
setState(() {
_initialized = true;
});
} catch (e) {
setState(() {
_error = true;
});
}
}
#override
void initState() {
initializeFlutterFire();
super.initState();
}
Widget somethingWentWrong() {
return AlertDialog(
title: Text('Something Went Wrong'),
content: Icon(
Icons.error,
color: Colors.red,
size: 40.0,
),
);
}
Widget loading() {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.black,
valueColor: new AlwaysStoppedAnimation<Color>(Colors.black),
),
);
}
List<Text> docIds = [];
void addDocId(String s) {
docIds.add(Text(s));
print(docIds);
}
#override
Widget build(BuildContext context) {
if (_error) {
return somethingWentWrong();
}
if (!_initialized) {
return loading();
}
FirebaseFirestore.instance
.collection('Menu')
.get()
.then((QuerySnapshot querySnapshot) => {
querySnapshot.docs.forEach((doc) {
addDocId(doc.id);
})
});
print(docIds);
return Container(
margin: EdgeInsets.fromLTRB(
50.0,
100.0,
50.0,
100.0,
),
// color: Colors.blueAccent,
child: Center(
child: ListView(
children: docIds,
),
));
}
}
Since Text is only recognized in Flutter, it doesn't work for Firebase. Try using a String with the Text's value instead or create a map with each independent variable in Text such as the font size.

Flutter. My UI is not updated when I receive a value from a Future Function

My problem is that when I receive information from Firestore, I see it in the console that it prints but my UI does not update. But until I press the icon that shows my screen again. The screen where my list of widgets is contained in a BottomNavigationBar.
What I hope will happen with the code is that when I select the tab that will contain my screen in the BottomNavigationBar, the list of Widgets appears with the names of the DocumentIDs. Well, currently I must select the tab again so that they appear.
I attach my code.
class PruebasVarias extends StatefulWidget {
#override
_PruebasVariasState createState() => _PruebasVariasState();
}
class _PruebasVariasState extends State<PruebasVarias> {
List<String> myData = [];
List<Widget> myListWidget = [];
#override
void initState() {
super.initState();
getallDocument();
}
Future getallDocument()async{
final QuerySnapshot result = await Firestore.instance
.collection("Users")
.getDocuments();
final List<DocumentSnapshot> documentos = result.documents;
documentos.forEach((data) {
myData.add(data.documentID);
print(myData);
});
for (int i = 0; i < (myData.length); i++){
myListWidget.add(Text("${myData[i]}"));
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
title: Text("Documents"),
actions: <Widget>[
],
),
body: Center(
child:
Column(children: myListWidget),
)
);
}
}
An easy fix : use then to call a callback function and inside callback function use setState to update the UI.
class PruebasVarias extends StatefulWidget {
#override
_PruebasVariasState createState() => _PruebasVariasState();
}
class _PruebasVariasState extends State<PruebasVarias> {
List<String> myData = [];
List<Widget> myListWidget = [];
#override
void initState() {
super.initState();
getallDocument().then(()=>updateUI()).catchError((error)=>print(error));
}
Future<void> getallDocument()async{
final QuerySnapshot result = await Firestore.instance
.collection("Users")
.getDocuments();
final List<DocumentSnapshot> documentos = result.documents;
documentos.forEach((data) {
myData.add(data.documentID);
print(myData);
});
for (int i = 0; i < (myData.length); i++){
myListWidget.add(Text("${myData[i]}"));
}
}
void updateUI()
{
setState((){});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
title: Text("Documents"),
actions: <Widget>[
],
),
body: Center(
child:
Column(children: myListWidget.isEmpty?[Text("Waiting...")]:myListWidget),
)
);
}
}
You can fix this by calling setState(() {}) method; setState
Notify the framework that the internal state of this object has changed.
Future getallDocument() async {
final QuerySnapshot result =
await Firestore.instance.collection("Users").getDocuments();
final List<DocumentSnapshot> documentos = result.documents;
documentos.forEach((data) {
myData.add(data.documentID);
print(myData);
});
for (int i = 0; i < (myData.length); i++) {
myListWidget.add(Text("${myData[i]}"));
}
setState(() {});
}

not able to update list after http call ( flutter)

i'm new to flutter
i try to do an http call and then populate a list. The problem is that the http call works fine but the UI doesn't refresh.
i think that the problem is that the framework create ui with the list before the http call is finish. Than when the http call is finished i'm unable to update the ui.
i've search but i didn't find anything.
EDIT--FOUND SOLUTION IN Listview.Builder code here
http call
static Future<Map> getData() async {
try{
http.Response res = await http.get("http://....");
Map data = JSON.decode(res.body);
print(res.body);
return data;
}
catch(exception){
//todo
}
}
main
class _MyHomePageState extends State<MyHomePage> {
List<Widget> _items = new List<GithubCardItem>();
#override
void initState() {
super.initState();
print("start download");
_downloadData();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text(widget.title)),
body: new ListView.builder(
itemBuilder: (BuildContext context, int index) => _items[index],
itemExtent: 128.0,
itemCount: _items.length,
),
floatingActionButton: new FloatingActionButton(
child: new Icon(Icons.add),
onPressed: (){
_downloadData();
},
)
);
}
GithubCard _extractDataFromJson(Map githubCard){
GithubCard card = new GithubCard(githubCard["name"], githubCard["avatar_url"], githubCard["description"], githubCard["stargazers_count"], githubCard["open_issued_count"]);
return card;
}
void _downloadData(){
MyHttpCall.getData().then((jsonData) {
//check if i have card to display
if(jsonData["items"] != null){
for(var githubCard in jsonData["items"]){
setState(() {
GithubCard card = _extractDataFromJson(githubCard);
this._items.add(new GithubCardItem(card));
});
print("adding elements");
}
}
});
}
}
the GithubCardItem is a simple stateless widget that return a text.
There are different ways to use ListView as well as get data from network
here is the sample code for your problem
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List list = new List();
void fetchData() {
getData().then((res) {
setState(() {
list.addAll(res);
});
});
}
#override
void initState() {
super.initState();
fetchData();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new ListView.builder(
itemCount: list.length,
itemBuilder: ((BuildContext _context, int position) {
return new ListTile(
title: new Text( list[position]['login'].toString()),
subtitle: new Text(list[position]['url']),
leading: new Image.network(list[position]['avatar_url']),
);
}),
),
),
floatingActionButton: new FloatingActionButton(
onPressed: fetchData,
tooltip: 'Increment',
child: new Icon(Icons.add),
),
);
}
Future<List> getData() async {
var url = "https://api.github.com/users";
List data = new List();
var httpClient = new HttpClient();
var request = await httpClient.getUrl(Uri.parse(url));
var response = await request.close();
if (response.statusCode == HttpStatus.OK) {
var jsonString = await response.transform(utf8.decoder).join();
data = json.decode(jsonString);
return data;
}else{
return data;
}
}
}
Try this:
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {----------- }
class MyHomePage extends StatefulWidget {-----------}
class _MyHomePageState extends State<MyHomePage> {
List data;
Future<String> getData() async {
var response = await http.get(
Uri.encodeFull("https://api.github.com/users"),
headers: {"Accept": "application/json"});
this.setState(() {
data = json.decode(response.body);
});
return "Success!";
}
#override
void initState() {
this.getData();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Listviews"),
),
body: new ListView.builder(
itemCount: data == null ? 0 : data.length,
itemBuilder: (BuildContext context, int position) {
return new ListTile(
title: new Text(data[position]['login'].toString()),
subtitle: new Text(data[position]['url']),
leading: new Image.network(data[position]['avatar_url']),
);
},
),
);
}
}
Made bit more simple and it's working. Check the sample here

Resources