Why is the listview empty and not showing the data?
Database = FirebaseDatabase.getInstance();
ref = Database.getReference().child(Let).child(Gen);
arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, arrayList);
ListView.setAdapter(arrayAdapter);
arrayAdapter.notifyDataSetChanged();
//
ref.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot snapshot, #Nullable String previousChildName) {
//arrayList.clear();
String value = snapshot.getValue(Name.class).getName();
arrayList.add(value);
arrayAdapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(#NonNull DataSnapshot snapshot, #Nullable String previousChildName) {
arrayAdapter.notifyDataSetChanged();
}
#Override
public void onChildRemoved(#NonNull DataSnapshot snapshot) {
arrayAdapter.notifyDataSetChanged();
}
#Override
public void onChildMoved(#NonNull DataSnapshot snapshot, #Nullable String previousChildName) {
arrayAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
arrayList.clear();
arrayAdapter.clear();
}
}
Replace
String value = snapshot.getValue(Name.class).getName();
with
String value=String.valueOf(snapshot.child("Name").getValue(String.class));
Related
i am trying to add the product to initial state so i can basically show it on the screen.
class _ProductListState extends State
{
var dbHelper = DbHelper();
late List<Product> products;
int productCount = 0;
#override
void initState(){
var productsFuture = dbHelper.getProducts();
productsFuture.then((data){
this.products.add(data);
});
from dbHelper:
Future<List> getProducts() async
{
Database db = await this.db;
var result = await db.query("products");
return List.generate(result.length, (i)
{
return Product.fromObject(result[i]);
});
}
but i get an error. what should i do?
previously, code was like this:
class _ProductListState extends State
{
var dbHelper = DbHelper();
late List<Product> products;
int productCount = 0;
#override
void initState(){
var productsFuture = dbHelper.getProducts();
productsFuture.then((data){
this.products = data;
});
}
try to provide list data type
Future<List<Product>> getProducts() async{
I have a collection in Firebase that I am trying to retrieve and add to a list:
I also have an events model defined. Before adding the event to a list, I would like to create an Event object using the data read from Firebase.
event_model:
class Event {
String eid;
String title;
String location;
String start;
String end;
String instructor;
String image;
String description;
Event({
required this.eid,
required this.title,
required this.location,
required this.start,
required this.end,
required this.instructor,
required this.image,
required this.description
});
String getEid() {
return eid;
}
String getTitle() {
return title;
}
String getLocation() {
return location;
}
String getStart() {
return start;
}
String getEnd() {
return end;
}
String getInstructor() {
return instructor;
}
String getImage() {
return image;
}
String getDescription() {
return description;
}
void setEid(String eid) {
this.eid = eid;
}
void setTitle(String title) {
this.title = title;
}
void setLocation(String location) {
this.location = location;
}
void setStart(String start) {
this.start = start;
}
void setEnd(String end) {
this.end = end;
}
void setInstructor(String instructor) {
this.instructor = instructor;
}
void setImage(String image) {
this.image = image;
}
void setDescription(String description) {
this.description = description;
}
}
This is what I have so far. I am creating the list of Event objects then trying to get the entire collection and for each document in the collection, I am creating the Event object and trying to add it to the list. I am not sure if this is correct.
List<Event> _events = [];
Future<UserProfile> getUserProfile() async {
try {
final FirebaseAuth auth = FirebaseAuth.instance;
final snapshot = await FirebaseFirestore.instance.collection('events').get();
snapshot.docs.forEach((doc) {
Map<String, dynamic>? data = snapshot.data();
Event event = Event(
eid: data?['eid'],
title: data?['title'],
...
});
a better approach for this is that the conversation of the Map<String, dynamic> to an Event class object, should be done using a factory constructor of the Event class, and setting a default value for each property so if something goes null, your app won't crash, it will have a default value and work fine, like this:
add this to your Event class:
factory Event.fromMap(Map<String, dynamic>? map) {
return Event(
eid: map?["eid"] ?? "defaultValue,"
title: map?["title"] ?? "defaultValue",
location: map?["location"] ?? "defaultValue",
start: map?["start"] ?? "defaultValue,"
end: map?["ends"] ?? "defaultValue,"
instructor: map?["instructor"] ?? "defaultValue,"
image: map?["image"] ?? "defaultValue,"
description: map?["description"] ?? "defaultValue",
);
}
then instead of implementing your methods, save yourself from the boilerplate code by using the:
Event event = Event.fromMap(snapshot.data() as Map<String, dynamic>);
_events.add(event);
I am setting values of variables declared in View Model class which is a StateNotifier, inside a function of widget. When I try to access the values of those variables from a different function of same widget, their values are null. I have debugged code to verify that first function is setting values correctly.
Any help will be highly appreciated.
Here is cutdown version of my StateNotifier
class ProductViewModel extends StateNotifier<ProductState> {
String errorMessage;
Product product;
final ProductService productService;
final CategoryService categoryService;
final BrandService brandService;
final TranslatorService translatorService;
final ProductOptionsViewModel productOptionsViewModel;
final ProductVariantViewModel productVariantViewModel;
ProductViewModel(this.productService, this.categoryService, this.brandService, this.translatorService,
this.productOptionsViewModel, this.productVariantViewModel)
: super(ProductInitial());
String productId;
List<SizeEnum> _sizes;
String _selectedBrand;
String _selectedCategory;
String _selectedStore;
String _productName;
String _productIntlName;
String _sku;
String get selectedBrand => _selectedBrand;
set selectedBrand(String value) {
_selectedBrand = value;
}
String get selectedCategory => _selectedCategory;
set selectedCategory(String value) {
_selectedCategory = value;
}
String get selectedStore => _selectedStore;
set selectedStore(String value) {
_selectedStore = value;
}
String get productName => _productName;
set productName(String value) {
_productName = value;
}
String get productIntlName => _productIntlName;
set productIntlName(String value) {
_productIntlName = value;
}
String get sku => _sku;
set sku(String value) {
_sku = value;
}
Future<bool> saveProductDetails() async {
bool isSave = false;
bool imageSaved = await saveProductImage();
if (!imageSaved) return imageSaved;
List<String> searchKeywords = indexProductName(_productName);
List<String> searchTag1 = _searchTag1 != null ? indexProductName(_searchTag1) : null;
List<String> searchTag2 = _searchTag2 != null ? indexProductName(_searchTag2) : null;
List<String> searchTag3 = _searchTag3 != null ? indexProductName(_searchTag3) : null;
if (deal != null && _dealsAddedDateTime == null) {
_dealsAddedDateTime = DateTime.now();
}
print(productOptionsViewModel.toString());
Product _product = Product(
productId: productId,
name: _productName,
intlName: _productIntlName,
category: FirebaseFirestore.instance.doc(_selectedCategory),
brand: FirebaseFirestore.instance.doc(_selectedBrand),
sku: _sku,
quantity: _quantity,
price: _price,
containSizes: productOptionsViewModel.sizes,
containColors: productOptionsViewModel.colors,
accessory: productOptionsViewModel.accessory ,
salesTaxApplicable: productOptionsViewModel.salesTax,
);
isSave = await productService.saveProduct(_product);
if (!isSave) {
errorMessage = "Error in saving product information";
} else {
productId = productService.newProductId;
}
return isSave;
}
}
StateNotifierProvider declaration
final productViewModelProvider = StateNotifierProvider.autoDispose<ProductViewModel,ProductState>((ref) => ProductViewModel(
ref.watch(productServiceProvider),
ref.watch(categoryServiceProvider),
ref.watch(brandServiceProvider),
ref.watch(translatorServiceProvider),
ref.watch(productOptionsViewModelProvider),
ref.watch(productVariantViewModelProvider)));
UI Functions
I set values in validateProduct and read values again in saveProductDetails.
Future<bool> validateProduct() async {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
final model = context.read(productViewModelProvider.notifier);
final storeViewModel = context.read(storeViewModelProvider.notifier);
var _store = await storeViewModel.getMyStore();
model.productName = _productName;
model.productIntlName = _productIntlName;
model.sku = _sku;
model.quantity = _quantity;
model.price = _price;
model.selectedBrand = _selectedBrand;
model.selectedCategory = _selectedCategory;
model.selectedStore = _storeCode;
model.description = _productDescription;
model.manufacturerLink = _manufacturerLink;
model.searchTag1 = _searchTag1;
model.searchTag2 = _searchTag2;
model.searchTag3 = _searchTag3;
if (model.addedDateTime == null) {
model.addedDateTime = DateTime.now();
}
if (_storeCode == null) {
_storeCode = _store.store;
}
if (model.selectedStore == null) {
model.selectedStore = _storeCode;
}
return true;
}
else return false;
}
Future<bool> saveProductDetails() async {
final model = context.read(productViewModelProvider.notifier);
bool isProductSaved = await model.saveProductDetails();
if (isProductSaved) {
if (_isProductExist) {
displayMessage(context, "Product Information Updated");
} else
displayMessage(context, "Product Information Saved");
_formSaved = true;
isFormChanged = false;
return true;
} else if (isProductSaved == false) {
_formSaved = false;
displayMessage(context, model.errorMessage);
}
return isProductSaved;
}
State
abstract class ProductState {
const ProductState();
}
class ProductInitial extends ProductState {
const ProductInitial();
}
class ProductLoading extends ProductState {
const ProductLoading();
}
class ProductLoaded extends ProductState {
final Product product;
ProductLoaded(this.product);
#override
bool operator ==(Object other) =>
identical(this, other) || other is ProductLoaded && runtimeType == other.runtimeType && product == other.product;
#override
int get hashCode => product.hashCode;
}
class ProductSaving extends ProductState {
const ProductSaving();
}
class ProductSaved extends ProductState {
final Product product;
ProductSaved(this.product);
#override
bool operator ==(Object other) =>
identical(this, other) || other is ProductSaved && runtimeType == other.runtimeType && product == other.product;
#override
int get hashCode => product.hashCode;
}
class ProductError extends ProductState {
final String errorMessage;
ProductError(this.errorMessage);
}
Remove .autoDispose modifier
final productViewModelProvider = StateNotifierProvider<ProductViewModel,ProductState>((ref) => ProductViewModel(
ref.watch(productServiceProvider),
ref.watch(categoryServiceProvider),
ref.watch(brandServiceProvider),
ref.watch(translatorServiceProvider),
ref.watch(productOptionsViewModelProvider),
ref.watch(productVariantViewModelProvider)));
Hi I need to retrieve all documents from firestore collection with this:
EventList<Event>testdata(QuerySnapshot snapshot) {
return snapshot.docs.map((data) => EventList<Event>(events: {
data['date']: [
Event(
date: data['date'], title: data['name'], icon: Icon(
Icons.block,
color: Colors.red[200],
size: 30,
)),
]
})).toList();
}
Stream<EventList<Event>> get caldendardata {
return events.snapshots().map(testdata);
}
but i get this error: A value of type 'List<EventList<Event>>' can't be returned from the method 'testdata' because it has a return type of 'EventList<Event>'.
The Firestore :
I'm using this package to add calendar to my app it requires the event on the calendar to be {EventList<Event>? markedDatesMap} .
EventList form the package:
class EventList<T> {
Map<DateTime, List<T>> events;
EventList({
required this.events,
});
void add(DateTime date, T event) {
final eventsOfDate = events[date];
if (eventsOfDate == null)
events[date] = [event];
else
eventsOfDate.add(event);
}
void addAll(DateTime date, List<T> events) {
final eventsOfDate = this.events[date];
if (eventsOfDate == null)
this.events[date] = events;
else
eventsOfDate.addAll(events);
}
bool remove(DateTime date, T event) {
final eventsOfDate = events[date];
return eventsOfDate != null ? eventsOfDate.remove(event) : false;
}
List<T> removeAll(DateTime date) {
return events.remove(date) ?? [];
}
void clear() {
events.clear();
}
List<T> getEvents(DateTime date) {
return events[date] ?? [];
}
}
Event form the package:
class Event implements EventInterface {
final DateTime date;
final String? title;
final Widget? icon;
final Widget? dot;
final int? id;
Event({
this.id,
required this.date,
this.title,
this.icon,
this.dot,
});
#override
bool operator ==(dynamic other) {
return this.date == other.date &&
this.title == other.title &&
this.icon == other.icon &&
this.dot == other.dot &&
this.id == other.id;
}
#override
int get hashCode => hashValues(date, title, icon, id);
#override
DateTime getDate() {
return date;
}
#override
int? getId() {
return id;
}
#override
Widget? getDot() {
return dot;
}
#override
Widget? getIcon() {
return icon;
}
#override
String? getTitle() {
return title;
}
}
abstract class EventInterface {
DateTime getDate();
String? getTitle();
Widget? getIcon();
Widget? getDot();
int? getId();
}
I would appreciate a little help here.
Thank you in advance
map returns a List. That's why you have a List<EventList>.
I believe you are trying to flatten the list so that you instead have a single EventList with all of the events. One way to accomplish this is to use fold.
Here is an example that you should be able to apply to your code. One could paste this into Dartpad to quickly see how it works:
class Event {
const Event(this.id);
final int id;
}
class EventList {
const EventList({required this.events});
final List<Event> events;
}
class FirebaseData {
const FirebaseData(this.docs);
final List<Event> docs;
}
void main() {
// Simulating your data stream
final FirebaseData snapshot = FirebaseData(List.generate(5, (index) => Event(index)));
// What you are returning from your code currently
final List<EventList> eventListList =
snapshot.docs.map((data) => EventList(events: [data])).toList();
// What you actually want to return from your code
final EventList eventList = eventListList.fold(EventList(events: []),
(previousValue, element) => EventList(events: previousValue.events..addAll(element.events)));
print(eventList.events);
}
When performing toList you getting a List<EventList<Event>> each EventList with one event.
I think you want to get a List<Map> from Firestore to later build your class.
You can achieve that with a code like this.
EventList<Event>testdata(QuerySnapshot snapshot) {
//Get all data
final List<Map> eventListMap = snapshot.docs.map((data) => {
data['date']: [
Event(
date: data['date'], title: data['name'], icon: Icon(
Icons.block,
color: Colors.red[200],
size: 30,
)),
]
}).toList();
//Join to single Map, it should not contain repeated keys (date) as one of them would be lost
final Map eventsMap = eventsData.fold({},(map1, map2) => map1..addAll(map2));
//Return your class
return EventList<Event>(events: eventsMap);
}
Stream<EventList<Event>> get caldendardata {
return events.snapshots().map(testdata);
}
I did not try it and you can rename or change anything.
I am trying to make a post request in flutter using chopper. I have made an ApiService.dart file as
a generator file.
import 'package:bindle/Chopper/Models/LoginResponse.dart';
import 'package:chopper/chopper.dart';
part 'ApiService.chopper.dart';
#ChopperApi(baseUrl: 'http://192.168.1.20/bindal/api/v1/user/')
abstract class ApiService extends ChopperService {
#Post(path: "login")
Future<Response<LoginResponse>> doLogin([
#Header('auth_key') String authType,
#Query('email') String email,
#Query('password') String password,
#Query('userType') String userType,
]);
static ApiService create() {
final client = ChopperClient(
// The first part of the URL is now here
baseUrl: 'http://192.168.1.20/bindal/api/v1/user/',
services: [
// The generated implementation
_$ApiService(),
],
interceptors: [
HttpLoggingInterceptor()
],
// Converts data to & from JSON and adds the application/json header.
converter: JsonConverter(),
);
// The generated class with the ChopperClient passed in
return _$ApiService(client);
}
}
And this is my generated file.
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'ApiService.dart';
// **************************************************************************
// ChopperGenerator
// **************************************************************************
class _$ApiService extends ApiService {
_$ApiService([ChopperClient client]) {
if (client == null) return;
this.client = client;
}
final definitionType = ApiService;
Future<Response<LoginResponse>> doLogin(
[String authType, String email, String password, String userType]) {
final $url = 'http://192.168.1.20/bindal/api/v1/user/login';
final Map<String, dynamic> $params = {
'email': email,
'password': password,
'userType': userType
};
final $headers = {'auth_key': authType};
final $request = Request('POST', $url, client.baseUrl,
parameters: $params, headers: $headers);
return client.send<LoginResponse, LoginResponse>($request);
}
}
Next what i Did is i generated a model class called as LoginResponse where I have to fetch the data.
abstract class LoginResponse implements Built<LoginResponse, LoginResponseBuilder> {
int get status;
String get message;
LoginResponse._();
factory LoginResponse([void Function(LoginResponseBuilder) updates]) = _$LoginResponse;
static LoginResponse fromJson(String jsonString){
return serializers.deserializeWith(LoginResponse.serializer, json.decode(jsonString));
}
static Serializer<LoginResponse> get serializer => _$loginResponseSerializer;
}
this is the generated file for the above LoginResponse.dart file using built_value generator
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'LoginResponse.dart';
// **************************************************************************
// BuiltValueGenerator
// **************************************************************************
Serializer<LoginResponse> _$loginResponseSerializer =
new _$LoginResponseSerializer();
class _$LoginResponseSerializer implements StructuredSerializer<LoginResponse> {
#override
final Iterable<Type> types = const [LoginResponse, _$LoginResponse];
#override
final String wireName = 'LoginResponse';
#override
Iterable<Object> serialize(Serializers serializers, LoginResponse object,
{FullType specifiedType = FullType.unspecified}) {
final result = <Object>[
'status',
serializers.serialize(object.status, specifiedType: const FullType(int)),
'message',
serializers.serialize(object.message,
specifiedType: const FullType(String)),
];
return result;
}
#override
LoginResponse deserialize(
Serializers serializers, Iterable<Object> serialized,
{FullType specifiedType = FullType.unspecified}) {
final result = new LoginResponseBuilder();
final iterator = serialized.iterator;
while (iterator.moveNext()) {
final key = iterator.current as String;
iterator.moveNext();
final dynamic value = iterator.current;
switch (key) {
case 'status':
result.status = serializers.deserialize(value,
specifiedType: const FullType(int)) as int;
break;
case 'message':
result.message = serializers.deserialize(value,
specifiedType: const FullType(String)) as String;
break;
}
}
return result.build();
}
}
class _$LoginResponse extends LoginResponse {
#override
final int status;
#override
final String message;
factory _$LoginResponse([void Function(LoginResponseBuilder) updates]) =>
(new LoginResponseBuilder()..update(updates)).build();
_$LoginResponse._({this.status, this.message}) : super._() {
if (status == null) {
throw new BuiltValueNullFieldError('LoginResponse', 'status');
}
if (message == null) {
throw new BuiltValueNullFieldError('LoginResponse', 'message');
}
}
#override
LoginResponse rebuild(void Function(LoginResponseBuilder) updates) =>
(toBuilder()..update(updates)).build();
#override
LoginResponseBuilder toBuilder() => new LoginResponseBuilder()..replace(this);
#override
bool operator ==(Object other) {
if (identical(other, this)) return true;
return other is LoginResponse &&
status == other.status &&
message == other.message;
}
#override
int get hashCode {
return $jf($jc($jc(0, status.hashCode), message.hashCode));
}
#override
String toString() {
return (newBuiltValueToStringHelper('LoginResponse')
..add('status', status)
..add('message', message))
.toString();
}
}
class LoginResponseBuilder
implements Builder<LoginResponse, LoginResponseBuilder> {
_$LoginResponse _$v;
int _status;
int get status => _$this._status;
set status(int status) => _$this._status = status;
String _message;
String get message => _$this._message;
set message(String message) => _$this._message = message;
LoginResponseBuilder();
LoginResponseBuilder get _$this {
if (_$v != null) {
_status = _$v.status;
_message = _$v.message;
_$v = null;
}
return this;
}
#override
void replace(LoginResponse other) {
if (other == null) {
throw new ArgumentError.notNull('other');
}
_$v = other as _$LoginResponse;
}
#override
void update(void Function(LoginResponseBuilder) updates) {
if (updates != null) updates(this);
}
#override
_$LoginResponse build() {
final _$result =
_$v ?? new _$LoginResponse._(status: status, message: message);
replace(_$result);
return _$result;
}
}
finally i called my api in the login page as
void doLogin(String email, String pass, BuildContext context) async {
try {
final response = await Provider.of<ApiService>(context)
.doLogin("d1d2fe0514f7d5c748c0e7e085b36f74","arpit1692#gmail.com",
"e10adc3949ba59abbe56e057f20f883e","App");
print(response.body);
} catch (e) {
print(e);
}
}
Which ultimately gives me Exception as => Instance of 'Response dynamic'
Please help me for what I am doing wrong.
The reason why the Response returns dyanmic is because the response wasn't serialized to the model you've defined. If LoginResponse is the model that should be used for the response, the LoginResponse class should have fromJson() that should serialize the json response. You can follow this guide to help you manage json serialization.