Class 'List<DocumentSnapshot>' has no instance getter 'documents' - flutter

I am trying to achieve a functionality where the app displays all the users' details in a grid view except the current user's. I have been trying to assign snapshots to _stream and then apply the _stream value in StreamBuilder(). But it throws an error instead.
Database _database = Database();
Stream _stream;
String currentUserId;
#override
void initState() {
getCurrentUserId(); //currentUserId gets its value here
getAllUsers();
super.initState();
}
getAllUsers() async {
Stream<QuerySnapshot> snapshots = await _database.getAllUsers();
_stream = snapshots.map((querySnapshot) => querySnapshot.documents.where((documentSnapshot)
=> documentSnapshot.data["userId"] != currentUserId
).toList())
}
//..
StreamBuilder(
stream: _stream,
builder: (context, snapshot) {
if (snapshot.data != null)
//..
}
//..
)
NEW: if I add as QuerySnapshot, the snapshot in the StreamBuilder will be null instead of throwing an exception.
// NEW
_stream = snapshots.map((querySnapshot) => querySnapshot.documents.where((documentSnapshot)
=> documentSnapshot.data["userId"] != currentUserId
).toList() as QuerySnapshot);
Database class
getAllUsers() async {
return await _firestore.collection("users").snapshots();
}
Exception
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following NoSuchMethodError was thrown building StreamBuilder<dynamic>(dirty, state: _StreamBuilderBaseState<dynamic, AsyncSnapshot<dynamic>>#6e31f):
Class 'List<DocumentSnapshot>' has no instance getter 'documents'.
Receiver: Instance(length:2) of '_GrowableList'
Tried calling: documents
The relevant error-causing widget was:
StreamBuilder<dynamic> file:///Users/suriantosurianto/AndroidStudioProjects/apui/lib/fragments/home_fragment.dart:66:12
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1 _HomeFragmentState.build.<anonymous closure> (package:apui/fragments/home_fragment.dart:80:42)
#2 StreamBuilder.build (package:flutter/src/widgets/async.dart:509:81)
#3 _StreamBuilderBaseState.build (package:flutter/src/widgets/async.dart:127:48)
#4 StatefulElement.build (package:flutter/src/widgets/framework.dart:4619:28)
...
════════════════════════════════════════════════════════════════════════════════════════════════════

We do not know which line is this error pointing, however if I understand correctly the reason might be type of StreamBuilder property stream that should be of Stream class (reference).
Seems _stream is a list created from stream using toList method (reference). I would try to remove this toList method, and see what will happen.
I hope it will help!

// NEW
_stream = snapshots.map((querySnapshot) => querySnapshot.documents.where((documentSnapshot)
=> documentSnapshot.data["userId"] != currentUserId
).toList() as QuerySnapshot);
here the querySnapshot is a List<DocumentSnapshot>!!!
you are probably have to use querySnapshot.where()

As others point out, querySnapshot is a List<DocumentSnapshot> and not DocumentSnapshot, so you can't use the getter .documents(that getter is for DocumentSnapshot only, not for a List), This is becasue is retrieving the DocumentSnapshot of every user except the current user (a DocumentSnapshot for each user, so a List<DocumentSnapshot>).
If you want to return a Stream of type of List<DocumentSnapshot> then
_stream = snapshots
.map<List<DocumentSnapshot>>((querySnapshot) =>
querySnapshot.where((documentSnapshot) =>
documentSnapshot.data["userId"] != currentUserId)
);

Related

Unhandled Exception: LateInitializationError: Field 'Db' has not been initialized

i am using this DbProvider class in many other files. it throws error:
[ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception:
LateInitializationError: Field 'Db' has not been initialized.
E/flutter (12867): #0 DbProvider.Db (package:sample/src/Db.dart)
E/flutter (12867): #1 Bloc.fetchInfoWithNameOrder
(package:sample/src/bloc.dart:31:24)
E/flutter (12867): #2 NameTiles.build.
(package:sample/src/NameTiles.dart:20:16)
E/flutter (12867): #3 StreamBuilder.build
(package:flutter/src/widgets/async.dart:546:81)
This is DbProvider class
class DbProvider{
late Database Db;
DbProvider(){init();}
init()async{
print("sdsdfaf");
Directory dir = await getApplicationDocumentsDirectory();
final path = join(dir.path, 'AppDb.db');
print(dir.path);
Db = await openDatabase(
path,
version: 1,
onCreate: (Database newDb, int version){
newDb.execute(
"""
create table Names(
id integer primary key,
name text,
Salary integer,
total integer
);
create table Att(
id integer primary key,
name text,
);
"""
);
}
);
print('\n\n\ndb init\n\n\n');
}
}
This is bloc.dart file
class Bloc{
final db = DbProvider();
final _text_field_subject = BehaviorSubject();
final _tile = BehaviorSubject();
Function(String?) get addToTextSubject => _text_field_subject.sink.add;
Stream get text_field_subject => _text_field_subject.stream;
get text_field_subject_value => _text_field_subject.value;
Function get addToTile => _tile.sink.add;
Stream get tile => _tile.stream;
fetchInfo(String arg) async{
print('\nfetchInfo\n');
var ans = await db.Db.query(
"Names",
where: "name = ?",
whereArgs: [arg],
);
print(ans);
addToTile(ans);
}
fetchInfoWithNameOrder()async{
print('\nfetchinfowithorder\n');
var ans = await db.Db.query(
"Names",
orderBy: "name asc",
);
print(ans);
addToTile(ans);
}
}
and here is the NameTiles class with builder:
class NameTiles extends StatelessWidget{
#override
Widget build(BuildContext context) {
print('\n\n\n1\n\n\n');
final db = DbProvider();
print('\n\n\n3\n\n\n');
final bloc = StreamProvider.of(context);
return StreamBuilder(
stream: bloc.tile,
builder: (context, AsyncSnapshot? snapshot){
print('\n\n\nre\n\n\n');
if(snapshot == null || !snapshot.hasData){
print('\n\n\nStarting\n\n\n');
bloc.fetchInfoWithNameOrder();
return Text('loading');
}
print('\n\n\ntween\n\n\n');
return Text('llll');
},
);
}
Widget tiles(info){
return Container(
height: 40,
padding: EdgeInsets.all(5),
clipBehavior: Clip.none,
child: Row(children: [
Text('${info.name}'),
Text('${info.total}'),
],),
);
}
}
You call init in your constructor, but you never wait for it to finish.
So your constructor runs, it trigers the init method, and while that runs, since it's async and has no await to wait for it, your program continues, finally coming to a part where your variable is needed, but not initialized yet, since init is still running.
Some tips:
crank up warnings to a maximum, maybe using a package like pedantic
actually provide return types for your async methods
move your construction of DbProvider out of your build method
instead of having a constructor, create a factory method and make it async, remember to provide a proper return type and call it with an await.
You may want to read up on What is a Future and how do I use it?

The getter 'length' was called on null. fetch from api

I am trying to fetch data from api its splash screen of my app I want user wait 5 second when app is launched and then go to next screen but when I tried fetch data from api I received The getter 'length' was called on null. please help me here is my code I tried resolve it number of other resources but failed to find solution that's why I am posting my question is here please check and help
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_app/main.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
void main() {
runApp(new MaterialApp(
home: new SplashScreen(),
debugShowCheckedModeBanner: false,
routes: <String, WidgetBuilder>{
'/MyHomePage': (BuildContext context) => new MyHomePage()
},
));
}
class SplashScreen extends StatefulWidget {
#override
_SplashScreenState createState() => new _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
startTime() async {
var _duration = new Duration(seconds: 5);
return new Timer(_duration, navigationPage);
}
void navigationPage() {
Navigator.of(context).pushReplacementNamed('/MyHomePage');
}
bool _loading=true;
Map data;
List userData=null;
Future getData() async {
http.Response response = await http.get("https://livinghopemobile.com/public/api/fetch-site-settings?token=123ab_#_#AbCD");
data = json.decode(response.body);
debugPrint(response.body);
setState(() {
userData = data["data"];
_loading=false;
// print(userData[0]['title']);
});
}
#override
void initState() {
super.initState();
//startTime();
getData();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: ListView.builder(
itemCount:userData.length,
itemBuilder: (context, index) {
return Container(
child: Image.network(userData[index]['site_logo']),
);
}
)
);
}
}
Launching lib/ui/SplashScreen.dart on iPhone 11 Pro Max in debug mode...
Running Xcode build...
Xcode build done. 23.8s
Debug service listening on ws://127.0.0.1:60469/bL7bmRYyhoc=/ws
Syncing files to device iPhone 11 Pro Max...
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following NoSuchMethodError was thrown building SplashScreen(dirty, state: _SplashScreenState#5fa75):
The getter 'length' was called on null.
Receiver: null
Tried calling: length
The relevant error-causing widget was:
SplashScreen file:///Users/apple/livinghopev4/livinghope4ios/lib/ui/SplashScreen.dart:10:15
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
#1 _SplashScreenState.build (package:flutter_app/ui/SplashScreen.dart:61:30)
#2 StatefulElement.build (package:flutter/src/widgets/framework.dart:4612:27)
#3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4495:15)
#4 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4667:11)
...
════════════════════════════════════════════════════════════════════════════════════════════════════
flutter: {"status":200,"message":"Data fetched successfully","data":{"id":1,"site_logo":"https:\/\/livinghopemobile.com\/public\/storage\/site_logo\/270421_122025_image.png","site_name":"Living hope","created_at":null,"updated_at":"2021-04-27T07:20:26.000000Z"}}
[VERBOSE-2:ui_dart_state.cc(186)] Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'List<dynamic>'
#0 _SplashScreenState.getData.<anonymous closure> (package:flutter_app/ui/SplashScreen.dart:41:7)
#1 State.setState (package:flutter/src/widgets/framework.dart:1267:30)
#2 _SplashScreenState.getData (package:flutter_app/ui/SplashScreen.dart:40:5)
<asynchronous suspension>
This is because data is not type List, and userData is null hence there is no length to it when you are calling userData.length in ListView.builder.
Change null to [].
{"status":200,"message":"Data fetched successfully","data":{"id":1,"site_logo":"https:\/\/livinghopemobile.com\/public\/storage\/site_logo\/270421_122025_image.png","site_name":"Living hope","created_at":null,"updated_at":"2021-04-27T07:20:26.000000Z"}}
You could append the received data to userData, like: userData.add(data).
You try it:
itemCount:userData.length == null ? 0 : userData.length
Data is returning in Object and you are taking it as List. This is the reason you are getting the error.
Solution:
Don't use Listview.builder as api response is just an object(Map<String, dynamic>).
You can simply use
Image.network(userData['site_logo']),
and everthing will be fine.

Flutter Provider is returning null in initState()

I am getting List of DropdownMenuItem from firebase with stream using provider if I use provider in build it doesn't return null works great but in initstate even if I am setting the listen value false returns null.
Here is the code:
List<DropdownMenuItem<category.List>> dropdownmenuoptions;
DropdownMenuItem<category.List> dropdownMenuItem;
String dropDownValue;
#override
void initState() {
dropdownmenuoptions = Provider.of<List<DropdownMenuItem<category.List>>>(
context,
listen: false);
dropdownMenuItem = dropdownmenuoptions.first;
dropDownValue = dropdownMenuItem.value.name;
super.initState();
}
Here is the error message:
The following NoSuchMethodError was thrown building Builder:
The getter 'first' was called on null.
Receiver: null
Tried calling: first
The relevant error-causing widget was
MaterialApp
lib/main.dart:37
When the exception was thrown, this was the stack
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
#1 _HomeScreenState.initState
package:tobetter/…/home/home_screen.dart:73
#2 StatefulElement._firstBuild
package:flutter/…/widgets/framework.dart:4833
#3 ComponentElement.mount
package:flutter/…/widgets/framework.dart:4649
... Normal element mounting (24 frames)
The direct context inside initState can't be used for everything and specialty with Provider . so, as a solution use didChangeDependencies instead , example:
#override
void didChangeDependencies() {
super.didChangeDependencies();
dropdownmenuoptions = Provider.of<List<DropdownMenuItem<category.List>>>(
context,
listen: false);
dropdownMenuItem = dropdownmenuoptions.first;
dropDownValue = dropdownMenuItem.value.name;
}
if you really need it inside your initState you can use it inside addPostFrameCallback
#override
void initState(){
...
SchedulerBinding.instance.addPostFrameCallback((_) {
dropdownmenuoptions = Provider.of<List<DropdownMenuItem<category.List>>>(
context,
listen: false);
dropdownMenuItem = dropdownmenuoptions.first;
dropDownValue = dropdownMenuItem.value.name;
}
});

StreamBuilder<FileSystemEntity>(dirty, state: _StreamBuilderBaseState<FileSystemEntity, AsyncSnapshot<FileSystemEntity>>#25d1b)

I have got an error while working with Stream builders.
In my code, I used if(snapshot.data != null) { list.add(snapshot.data); } but I m getting a msg that add was called on null. I even added print('') statement to check if snapshot.data is null, but it is working fine with print() too. So I m not at all understanding how to solve this error. Someone please respond. Thanks in advance.
Here is my code
class Wrapper extends StatefulWidget {
#override
_WrapperState createState() => _WrapperState();
}
class _WrapperState extends State<Wrapper> {
Stream<FileSystemEntity> mystream;
var _directory;
void getfilesdata() async
{
_directory = await getApplicationDocumentsDirectory();
await Directory('${_directory.path}/data').create(recursive: true);
mystream = Directory('${_directory.path}/data').list().map((data) => data);
await Directory('${_directory.path}/documents').create(recursive: true);
}
#override
void initState() {
super.initState();
getfilesdata();
}
#override
Widget build(BuildContext context) {
List<FileSystemEntity> alldata;
return StreamBuilder<FileSystemEntity>(
stream: mystream,
builder: (context, snapshot) {
if(!snapshot.hasData)
{
print('No data yet');
return Loading();
}
else
{
if(snapshot.data != null && !snapshot.hasError)
{
print(snapshot.data);
alldata.add(snapshot.data);
}
if(snapshot.connectionState==ConnectionState.done)
{
return HomeScreen(alldata: alldata);
}
else return Loading();
}
}
);
}
}
And this is the result:
Performing hot restart...
Syncing files to device ZUK Z2132...
Restarted application in 1,734ms.
I/flutter (11840): No data yet
I/flutter (11840): No data yet
I/flutter (11840): File: '/data/user/0/com.example.easyscan/app_flutter/data/data[0]'
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following NoSuchMethodError was thrown building StreamBuilder<FileSystemEntity>(dirty, state: _StreamBuilderBaseState<FileSystemEntity, AsyncSnapshot<FileSystemEntity>>#25d1b):
The method 'add' was called on null.
Receiver: null
Tried calling: add(Instance of '_File')
The relevant error-causing widget was:
StreamBuilder<FileSystemEntity> file:///home/praneeth/AndroidStudioProjects/easyscan/lib/wrapper.dart:40:12
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1 _WrapperState.build.<anonymous closure> (package:easyscan/wrapper.dart:53:25)
#2 StreamBuilder.build (package:flutter/src/widgets/async.dart:509:81)
#3 _StreamBuilderBaseState.build (package:flutter/src/widgets/async.dart:127:48)
#4 StatefulElement.build (package:flutter/src/widgets/framework.dart:4619:28)
...
════════════════════════════════════════════════════════════════════════════════════════════════════
Your error is because allData is null so you cannot call the add() method.
You can declare your variable as follow:
List<FileSystemEntity> alldata = [];
By doing this allData will be initialized as an empty list and you will be able to call its methods.

type 'Future<dynamic>' is not a subtype of type 'int'

I'm new on flutter. I just wanted to store best score value. I tried to use Shared Preferences but i got an error.
import 'package:shared_preferences/shared_preferences.dart';
int best;
setBest(int n) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setInt('best', n);
}
getBest() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
int intValue = prefs.getInt('best');
if (intValue == null) {
return 0;
}
return intValue;
}
I call this dart file an another dart file
'import .... as x'
This pages shows to the user their current score and best
int best = x.getBest();
#override
void initState() {
super.initState();
if (score > best) {
best = score;
x.setBest(score);
}
}
error message
Exception caught by widgets library
The following _TypeError was thrown building Builder:
type 'Future<dynamic>' is not a subtype of type 'int'
The relevant error-causing widget was MaterialApp lib\main.dart:9
When the exception was thrown, this was the stack
#0 new _QuizResultState package:quiz_game/pages/quiz_result.dart:16
#1 QuizResult.createState package:quiz_game/pages/quiz_result.dart:12
#2 new StatefulElement package:flutter/…/widgets/framework.dart:4591
#3 StatefulWidget.createElement package:flutter/…/widgets/framework.dart:894
Normal element mounting (115 frames)
When you put async in a method, this method will return a Future<dynamic> object, so in second block of code you try to put a future inside a int:
int best = x.getBest();
To solve this I suggest:
Future<int> best = x.getBest();
#override
void initState() async {
super.initState();
if (score > await best) {
best = Future.sync(score);
x.setBest(score);
}
}