i'm new on Flutter/Dart, on my code i'm retrieving some data from a table and map it to a List
My code works fine but i'd like to Handling errors & exceptions so i tried to use DatabaseException
This is my code:
I know that maybe the question is basic but i don't understand
why list is no valid inside "if (e.isNoSuchTableError()) {"
Thanks for help
MM
The list is defined inside a try block, which means its not in the scope of the catch block, that's why you cannot access it inside the catch block. You need to define it outside the try block to be able to access it:
List<Map> list = null;
try {
list = await db.rawQuery(cmd);
} on DatabaseException catch(e){
//access it
}
The same concept is used in methods:
void getData(){
List<String> listOfNames = List<String>();
}
void retrieveData(){
print(listOfNames); // Undefined name 'listOfNames' - line 10
}
Related
I'm working with an app in Flutter that writes data to a Firebase database that I created and then reads and displays it in a list view in my app. Currently the app writes the data correctly and also reads it and prints it to the command line. However, when I code the bit that's supposed to then take that data and dump it into a list that can be printed in list view I get the following error when trying to iterate it from a map to a list using a forEach command. The error is "The method 'forEach' can't be unconditionally invoked because the receiver can be 'null'."
I've even tried adding '!' to force it to run since I know it's not null but it still won't work. Any ideas? The code for that section is below. Thanks in advance!
_ListViewReadPageState() {
// load all students from firebase database and display them in list view
FirebaseDatabase.instance.ref("students").once()
.then((databaseEvent) {
print("Successfully loaded the data");
print(databaseEvent);
print("Key:");
print(databaseEvent.snapshot.key);
print("value:");
print(databaseEvent.snapshot.value);
print("Iterating the value map");
var studentTmpList = [];
databaseEvent.snapshot.value.forEach((k, v) {
print(k);
print(v);
studentTmpList.add(v);
});
print("Final student list");
print(studentTmpList);
studentList = studentTmpList;
setState(() {
});
}).catchError((error) {
print("Failed to load the data");
print(error);
});
}
I've tried adding '!' to force the code to run since I know the data isn't null but no dice. When I try adding the '!' I get a new error stating "The method 'forEach' isn't defined for the type 'Object'".
how I can show DeliveryBoys in a specific location, in my realtime database I have a value that I need to compare drivers with which is "City" I would like to have all DeliveryBoys that are in a specific city. How can I do that? Using flutter
Am only able to get all drivers without a conditional statement
**This is my Function that i want to modify **
retrieveOnlineDriversInformation(List onlineNearestDriversList) async {
DatabaseReference ref =
FirebaseDatabase.instance.ref().child("DeliveryBoys");
for (int i = 0; i < onlineNearestDriversList.length; i++) {
await ref
.child(onlineNearestDriversList[i].driverId.toString())
.once()
.then((dataSnapshot) {
var driverKeyInfo = dataSnapshot.snapshot.value;
dList.add(driverKeyInfo);
});
}
}
Database Structure
Based on your responses and as far as I can see, you don't need the loop where you have it. Therefore, I am going to ignore it and simply show you the code that will return the list of driver ids of all drivers for city 'Lusaka'.
Future<List<String>> retrieveOnlineDriversInformation() async {
final driverIds = <String>[];
DatabaseReference ref = FirebaseDatabase.instance.ref().child("drivers");
try {
await ref.orderByChild("city")
.equalTo("Lusaka")
.once()
.then(
(event) {
if (event.snapshot.value != null) {
final driverListData =
Map<String, dynamic>.from(event.snapshot.value! as Map);
driverListData.forEach((key, value) {
driverIds.add(key);
});
}
},
} on FirebaseException catch (error, stackTrace) {
// < Some code here to print database error details or otherwise deal with it >
} catch (error, stackTrace) {
// < Some code here to print other error details or otherwise deal with it >
}
return driverIds;
}
You could instead modify this to just return the Map 'driverListData' which contains each driver's id and associated driver data.
A couple of other points:
You don't stick to a standard naming convention for your database node and field names. I suggest that you always use lowerCamelCase as the standard (so for example, change DriverLicense to driverLicense) as it will match what you typically name the variables within the Flutter/Dart code.
You don't need to hold the driver id as a separate field in the driver node. It is a duplicate (and therefore wastes space on the database) of the driver record key, which is already accessible to you.
As you see, you should always wrap your database call logic in a try / catch clauses in order to handle any errors that the call to the database may return. There are specific exceptions that can be tested for with the on clause.
I am new to dart/flutter programming. I have been trying to analyze the content of a file and return the result but couldn't. The code actually works when in the main function, but as soon as I take it out it doesn't work anymore. I have read the dart tutorial on futures, async, await, and streams as well as watched YouTube videos but still couldn't solve the problem. I believe my problem revolves around those concepts. Here is my code:
Future<String> r(String name) async {
var f = File(name);
var lines = f.readAsLines();
await lines
.then((line) => line.forEach((element) {
if (element.contains(RegExp(r'^hello'))) {
return element;
}
}))
.onError((error, stackTrace) => 'An error occured');
}
I was getting 2 errors:
The function name 'r' was underlined:
The body might complete normally, causing 'null' to be returned, but the return type is a potentially non-nullable type.
Try adding either a return or a throw statement at the end.
The variable 'element' was underlined:
The return type 'String' isn't a 'void', as required by the closure's context.
Thanks.
Your first error says that "Whatever happens, You have to return a String"
Your second error says that you are trying to return a String in a void function, As you see List. Foreach is a void function and you can't just return something in it because the return statement matches with the closest Function
So I rewrited you're code as following
Future<String> r(String name) async {
try {
var f = File(name);
var lines = await f.readAsLines();
for (var element in lines)
if (element.contains(RegExp(r'^hello'))) {
return element;
}
return "not found";
} catch (e) {
return 'An error occurred: $e';
}
}
Since you are using File and File.readAsLines I think it would be better to just wrap everything inside a try catch bloc k.
Help is much appreciated how to trace down this issue, because I am running out of ideas.
I am calling the function getOrderCollection, below, but it aborts after the first line var myCompanyDoc = await FirebaseFirestore.instance.collection('companies').doc(myCompany).get(); Without trowing anything to the console or jumping into some library when debugging. When I click next statement it jumps back to the calling function.
I am authenticated to the database, companyCollection = FirebaseFirestore.instance.collection('companies') provides an initialized object pointing to the collection and myCompany is a constant with the document id entered by copy/paste.
If some rules for the database but I can't see successful or denied queries with the monitor.
Any ideas how I can proceed tracing down the issue?
Future<void> getOrderCollection() async {
var myCompanyDoc = await FirebaseFirestore.instance.collection('companies').doc(myCompany).get();
print("companyDoc fetched");
final myDeliveryDocRef = myCompanyDoc.data()['delivery'].toString();
orderCollection = FirebaseFirestore.instance.collection('companies').doc(myCompany).collection('features').doc(myDeliveryDocRef).collection('orders');
orderBriefDoc = FirebaseFirestore.instance.collection('companies').doc(myCompany).collection('features').doc(myDeliveryDocRef);
}
UPDATE: This is collection > document what corresponds to final String myCompany = '4U4kZKXkr3rHA6B04S5K';
As we discussed in your comments, the issue was that you forgot to await the getOrderCollection() function. Even though, as you mentioned, your caller function _deliveryRepository.initRepository() was awaited, you still had to await getOrderCollection() inside your caller method to make sure that the code is waiting for the getOrderCollection() to be executed before it proceeds to the next line.
In general, you want to have some error handling and to type the known types/classes (avoid using var).
Error handling - for async/await place the code inside a try/catch.
Typing - Dart is type safe, which is really great to prevent runtime errors.
Depending on your setup, you might be able to hover over the Firestore.instance.collection(...).doc(...) to see the return type. .doc(...).get() returns a DocumentSnapshot and .collection(...).get() returns a CollectionSnapshot.
Using the above, it should be easier to debug:
Future<void> getOrderCollection() async {
try {
DocumentSnapshot myCompanyDoc = await FirebaseFirestore.instance.collection('companies').doc(myCompany).get();
print("companyDoc fetched");
final myDeliveryDocRef = myCompanyDoc.data()['delivery'].toString();
} catch(e) {
print('Error: ' + e.toString());
}
}
Don't forget to await your other 2 Firestore queries.
I am programming a flutter app, in which I have a callback from the native system containing some nfc information. I register the callback via the following line of code:
eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError);
The callback looks like this:
void _onEvent(Object event) {
//Receive Event
print("NFC Event received");
//Get the Payload
event['Payload']; //This does not work, it gives an error
}
But how can I parse out the data? I know it contains a field by the name Payload however, I cannot access it via event['Payload'].
I am very confused, I tried to cast it to another type like this: Map<String, String> eventMap = Map<String, String>.from(event); but that didnt work. Could someone please point out what I am doing wrong and how I can correctly extract the data?
Without too much information of native part, I suggest
you can reference this package or fork this https://github.com/akeblom/flutter-nfc-reader
directly
this repo fix some issue of pub.dev and work well in real device
the dart code you need reside in
https://github.com/akeblom/flutter-nfc-reader/blob/master/lib/flutter_nfc_reader.dart
void _onEvent(dynamic data) {
print("Event");
print(data);
}
Edit add more detail
akeblom has add Write NFC capability to IOS, so IOS part should work. please ue this fork https://github.com/akeblom/flutter-nfc-reader
For IOS MissingPluginException issue, I do not have IOS, I suggest you can ask akeblom
The data part you mentioned in comments if I do not misunderstand is line 77, please see describe below
In Android part.
https://github.com/akeblom/flutter-nfc-reader/blob/master/android/src/main/kotlin/it/matteocrippa/flutternfcreader/FlutterNfcReaderPlugin.kt
line 174, use kotlin mapOf returns a new read-only map with the specified contents and eventSink.success result to Dart
if (message != null) {
val data = mapOf(kId to id, kContent to message, kError to "", kStatus to "read")
eventSink?.success(data)
}
In https://github.com/akeblom/flutter-nfc-reader/blob/master/lib/flutter_nfc_reader.dart
line 22, with named constructor
factory NfcData.fromMap(Map data) {
NfcData result = NfcData(
id: data['nfcId'],
content: data['nfcContent'],
error: data['nfcError'],
statusMapper: data['nfcStatus'],
);
In line 77, NFC read start and _onEvent(dynamic data) get the data.
stream use this named constructor, and parse data, here with map((result)) transfer to NfcData
static Stream<NfcData> get read {
final resultStream = _channel
.invokeMethod('NfcRead')
.asStream()
.asyncExpand((_) => stream
.receiveBroadcastStream()
.map((result) => NfcData.fromMap(result)));
return resultStream;
In https://github.com/akeblom/flutter-nfc-reader/blob/master/example/lib/main.dart
line 33, response has transfered to NfCData, so example just use _nfcData = response;
FlutterNfcReader.read.listen((response) {
setState(() {
_nfcData = response;
});
});
The simplest way I found to parse an event to a Map is the following:
I encoded the variable to a String (but I use json.encode(event)instead of event.toString()as encode(event)returns a valid string.
Then I use this string to construct a map via json.decode. All of this is achieved with the flutter native library dart:convert. The complete code looks like this:
import 'dart:convert';
...
void _onEvent(dynamic event) {
//Receive Event
print("NFC Event received");
String str = json.encode(event);
Map eventMap = json.decode(str);
}
Have you tried event.toString()? It might return a string containing the field you are trying to get, from which you can easily parse the value.
You may also want to try:
Class<?> clazz = event.getClass();
Field payload= clazz.getField("Payload"); //Note, this can throw an exception if the field doesn't exist.
String fieldValue = payload.toString();
If it isn't returning what you want, you may need to make an interface for the object type, with a get method, or override the toString method to get return the Payload value.