How to return Future<object> and assign it to just object , flutter - android

I have a custom class that fetches data from the database, that returns Future<List<Line>>, which lies in line_list.dart files :
Future<List<Line>> fetchingLinesData() async {
List<Line> lineList = [];
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'main.db');
Database database = await openDatabase(path, version: 1);
database.transaction((tnx) async {
dbRef.child('line').once().then((DataSnapshot dataSnapshot) async {
dataSnapshot.value.forEach((key, value) async {
List<Station> inLineStations = [];
for (var i = 0; i < 100; i++) {
if (value["station_$i"] != null) {
List<Map> stations = await tnx.rawQuery("SELECT * FROM Station");
stations.forEach((s) {
if (s['stationName'] == value["station_$i"]) {
Station stationInstance = Station(
key: s['key'],
cityName: s['cityName'],
stationName: s['stationName'],
stationLongitude: s['stationLongitude'],
stationLatitude: s['stationLatitude']);
inLineStations.add(stationInstance);
}
});
}
}
Line lineInstance = Line(
startStation: value['start_station'],
endStation: value['end_station'],
inLineStations: inLineStations,
notes: value['notes'],
price: value['price'],
transportationType: value['transportation_type']);
lineList.add(lineInstance);
});
});
});
return lineList;
}
}
and then in my main.dart widget, I have this :
List<Line> allLines = [];
I want to do something like this :
allLines = LinesList().fetchingLinesData();
But of course, it gives me an error as am trying to assign Future<List<Line>> to List<Line>
how to do it?

You have to await for future to complete.
allLines = await LinesList().fetchingLinesData();

You would just put the code below in a async function make main async and make your code
allLines = await LinesList().fetchingLinesData();

Related

Stream returning null even though EVERY print statement is getting printed

I have a Stream which seems to work perfectly fine: Every print statement you see in the stream is getting printed. Also when calling if(snapshot.hasData) it apparently is true. But still, my stream only returns the following: AsyncSnapshot<List<dynamic>>(ConnectionState.done, [], null, null).
What do I need to change in order to be able to access the Data in my retVal variable?
Stream<List>? roomsListStream() {
try {
List<RoomsListModel> retVal = [];
print("userId: $userId");
var rooms = FirebaseFirestore.instance
.collection("rooms")
.where("users", arrayContains: userId)
.orderBy("latestMessageTime", descending: true)
.snapshots();
print("rooms: $rooms");
rooms.forEach((element) {
element.docs.forEach((element) {
print("element: $element");
var room = element.data();
print("room: $room");
var roomId = room["roomId"];
var otherUserId =
room["users"].firstWhere((element) => element != userId);
var lastMessage = room["latestMessage"];
var lastMessageTime = room["latestMessageTime"];
print("otherUserId: $otherUserId");
getOtherUser(otherUserId).then((value) {
print("value: $value");
var avatar = value["photoUrl"];
var name = value["name"];
retVal.add(RoomsListModel(
roomId: roomId,
otherUserId: otherUserId,
avatar: avatar,
name: name,
lastMessage: lastMessage,
lastMessageTime: lastMessageTime));
});
});
});
return Stream.value(retVal);
} catch (e) {
print("Error: $e");
}
}
Try:
var rooms = await FirebaseFirestore.instance
.collection("rooms")
.where("users", arrayContains: userId)
.orderBy("latestMessageTime", descending: true)
.snapshots();

GetStorage always returns null in flutter

Code
print("Before : ${GetStorage().read("XXX")}");
GetStorage().write("XXX", 1);
print("After : ${GetStorage().read("XXX")}");
This is my Code. Every time I run the App, the Output is
Before : null
After : 1
Why is the storage data getting cleared everytime I restart the App? I thought this was an alternative to SharedPreference which works just fine. Have I missed something?
Before anything, initialize the package, normally I do this on main.dart
main() async {
await GetStorage.init();
}
Create an instance from GetStorage, I always put a name on the box, if not it will put "GetStorage" by default. It needs to have a name so it can retrieve your data.
GetStorage getStorage = GetStorage('myData');
After that you can write and retrieve data from it, I recommend you to "await" all reads and writes.
await getStorage.write('XXX', 1);
var a = await getStorage.read('XXX');
print(a); /// 1
I recommend you to put a name on the box according to what you are storing.
You should await for GetStorage.init().
void main() async {
await GetStorage.init();
print("Before : ${GetStorage().read("XXX")}");
GetStorage().write("XXX", 1);
print("After : ${GetStorage().read("XXX")}");
}
final _userBox = () => GetStorage('User');
class UserPref {
void call(){
_userBox.call()..initStorage;
}
dynamic setValueInt(String key, int value) {
return 0.val(key, getBox: _userBox).val = value;
}
String setValue(String key, String value) {
return ''.val(key, getBox: _userBox).val = value;
}
dynamic getValueInt(String key) {
return (-1).val(key,getBox: _userBox).val;
}
dynamic getValue(String key) {
return ''.val(key,getBox: _userBox).val;
}
void setUser(User user) {
''.val('uname', getBox: _userBox).val = user.uname ?? '';
(-1).val('gender', getBox: _userBox).val = user.gender ?? -1;
''.val('born', getBox: _userBox).val = user.born.toString();
true.val('enabled', getBox: _userBox).val = user.enabled ?? true;
}
User getUser() {
final String? uname = ''.val('uname',getBox: _userBox).val;
final int? gender = (-1).val('gender',getBox: _userBox).val;
final DateTime? born = ''.val('born',getBox: _userBox).val == '' ? null : DateTime.parse(''.val('born',getBox: _userBox).val);
final bool? enabled = true.val('enabled',getBox: _userBox).val;
return User(
uname: uname,
gender: gender,
born: born,
enabled: enabled,
);
}
}
///INIT:
#override
void initState() {
//The init function must be written separately from the read/write function due to being asynchronous.
UserPref().call();
}
//OR
Future<void> main() async {
//await GetStorage.init();
UserPref().call();
}
///USAGE:
class MyStatefulWidget extends StatefulWidget {
final Users prefUser = UserPref().getUser();
...
}
//OR
#override
Widget build(BuildContext context) {
final Users prefUser = UserPref().getUser();
return ...;
}

cant save json.decode to share preferences in flutter

I have list, I want to save in sharepreferences,
setString('key',json.encode(temporaryData));
When I try to get this value, only show Instance of Future<dynamic>
but when i print that json.encode show it value
[{"name":"Stranger","birthDate":"","idCardNum":"-1","currentTime":1593598133479,"imageFlag":1,"imageName":"-1_1_1593598133479.png","type":-1,"tempratrue":"36.3","mask":0}]
Future<SharedPreferences> storage() {
return SharedPreferences.getInstance();
}
void setTempData(String temp) async {
SharedPreferences sharedPreferences = await storage();
await sharedPreferences.setString('datas', temp);
}
getTempData(String key) async {
SharedPreferences sharedPreferences = await storage();
await sharedPreferences.get(key);
}
_getTemp() async {
DateTime start = DateTime.now().subtract(Duration(seconds: 5));
DateTime end = DateTime.now();
Map data = {'pass': '123456', 'startTime': '$start', 'endTime': '$end'};
var response = await http.post('$urlApiQr:8080/newFindRecords', body: data);
var jsonData = json.decode(response.body);
var jsEnc = json.encode(response.body);
TempJson tempJson = TempJson.fromJson(jsonData);
var parse = json.decode(tempJson.config);
setState(() {
dataList = parse;
temporaryData = dataList.toSet().toList();
setTempData(json.encode(temporaryData));
//try to print value
print('$start and $end');
print(parse);
print(getTempData('datas'));
});
}
Is there a solution to my problem?
UPDATE 2.0
you have to add await anywhere your are requesting value from a Future.. as the below method return a Future as you can see from your error, just add await keyword from where you are requesting a value,
for example
print(await getTempData(key));
UPDATE
return keyword missing
getTempData(String key) async {
SharedPreferences sharedPreferences = await storage();
//you missed the return keyword here
return await sharedPreferences.get(key);
}
original answer
dont miss the await keyword
var thestring = await sp.getString('the_key');
var theJsonObj = json.decode(thestring);
this is my assumption, please post more code

need some processing to do before cloud function returns a promise. But promise is return before the processing

i have a cloud function where i pass an array of numbers and compare those numbers with collection in the firestore . And if the numbers are present than return an array with those numbers. But before comparing those numbers the function return empty value in the promise.
I've tried using async await but the execution sequence remained same.
//sort contact list
export const addMessage= functions.https.onCall(async (data:any, context) => {
const col=admin.firestore().collection("joshua");
var match:[]
match=data.list
var perm1=new Array()
res11.push("454675556")
console.log("above resolve")
for(let val in match){
var inter=await Promise.all([getValues(col,val)])
console.log("inside resolve"+inter)
}
perm1.push("23432")
console.log("just before resolve")
return new Promise((res,rej)=>{
res(perm1)
})
});
//the async function which is suppose to process on every iteration
function getValues(col1:any,val1:any)
{
return new Promise(async(res,rej)=>{
var query= await col1.where('Listed','array-contains',val1)
var value=await query.get()
res(value)
})
.catch(err=>{
console.log(err)
})
}
i want the sequence to be asynchronous where the return value from getValues is waited upon and inside getValues result of query.get is waited upon.
so that at last return only be sent when all process is finished.
I think this is what you are looking for
export const addMessage= functions.https.onCall(async (data:any, context) => {
const col = admin.firestore().collection("joshua");
var match:[]
match = data.list
var perm1 = []
// res11.push("454675556") // ? undefined
for(let val in match){
var inter = await getValues(col,val)
console.log("inside resolve" + inter)
}
perm1.push("23432") // ??
// console.log("just before resolve")
return Promise.resolve(perm1)
});
const getValues = async (col1:any, val1:any) => {
const query = col1.where('Listed','array-contains', val1)
var value = await query.get().then(getAllDocs)
return value
}
const getAllDocs = function(data: any) {
const temp: Array<any> = []
data.forEach(function (doc: any) {
temp.push(doc.data())
})
return temp
}

SQLite connections returns null in Flutter

I am using SQFLite flutter package in my app. However, I keep getting null as a result of the connection to the DB. Below is my code used in initializing DB, creating table, and methods for adding items and fetching them:
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
import 'package:path/path.dart';
import 'dart:async';
class StoreDBProvider {
Database db;
init() async {
Directory documentsDirectory = await
getApplicationDocumentsDirectory();
final path = join(documentsDirectory.path, "carts.db");
db = await openDatabase(
path,
version: 3,
onCreate: (Database newDB, int version){
newDB.execute('CREATE TABLE Cart (id INTEGER
PRIMARY KEY, name TEXT, price DOUBLE, image TEXT, rating DOUBLE)');
}
);
return db;
}
Future<dynamic> fetchItem(int id) async {
print("DB CONNECTION IS: $db");
final maps = await db.query(
"Cart",
columns: null,
where: "id = ?",
whereArgs: [id],
);
print(maps);
if(maps.length > 0){
print("Data exists");
return maps.first;
}
return null;
}
Future<int> addItem(item) async{
return db.insert("Cart", item);
}
}
After some debuggin, I notice that "db" value is null. Here is the error message:
E/flutter ( 6921): [ERROR:flutter/shell/common/shell.cc(182)] Dart
Error: Unhandled exception:
E/flutter ( 6921): NoSuchMethodError: The method 'insert' was called on null.
E/flutter ( 6921): Receiver: null
E/flutter ( 6921): Tried calling: insert("Cart", _LinkedHashMap len:5)
E/flutter ( 6921): #0 Object.noSuchMethod
(dart:core/runtime/libobject_patch.dart:50:5)
E/flutter ( 6921): #1 StoreDBProvider.addItem
(file:///Users/Oluwashola/workspace/fashion_style/lib/src/resources/store_db_provider.dart:46:15)
Please, any assistance here is appreciated. Thank you.
If it helps, here is my working code. Note I use an async getter for db and await when using the db in a method. Afraid I'm rather a Flutter newbie too.
Note I interact with DatabaseHelper via a Future. See second code block. I think this requires using FutureBuilder. I suspect you need to use this to cope with (slightly) slow to load async db calls.
class DatabaseHelper {
final String tableName = "Gear";
static Database _db;
Future<Database> get db async {
if (_db != null) return _db;
_db = await initDb();
await importData();
return _db;
}
initDb() async {
// Get a location using path_provider
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, "gear_log.db");
await deleteDatabase(path);
var theDb = await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
print('creating db...');
String sql = await rootBundle.loadString('assets/db/schema.txt');
for (var s in sql.split(";")) {
if (s.length > 5) {
// catching any hidden characters at end of schema
await db.execute(s + ';');
}
}
// When creating the db, create the table
});
return theDb;
}
importData() async {
final datasources =
'observation_bodyissue.json,observation_observation.json,observation_observation_bodyIssues.json,observation_observation_shoeIssues.json,observation_shoeissue.json,observation_gearissue.json,runner_runner.json,gear_actualpair.json,gear_characteristic.json,gear_shoe.json,gear_family.json,gear_maker.json,gear_gear.json,gear_gear_characteristics.json,users_user.json'
.split(',');
var batch = _db.batch();
for (var datasource in datasources) {
try {
String str = await rootBundle.loadString('assets/db/data/$datasource');
String table = datasource.split('.')[0];
if (str.length > 0 && str != '[]') {
List<dynamic> _list = await json.decode(str);
for (var _json in _list) {
batch.insert(table, _json);
}
}
} catch (e) {
print(e.toString());
}
}
print('added db data');
var results = await batch.commit();
//print(results);
//print('imported data');
}
Future<List<Item>> getItems() async {
var dbClient = await db;
List<Map> list = await dbClient.rawQuery('SELECT *'
'FROM "gear_actualpair" '
'DESC, "gear_actualpair"."created" DESC');
//prob need to specify 'first X' at sometime
List<Item> items = new List();
for (int i = 0; i < list.length; i++) {
Item item = Item.fromMap(list[i]);
if (list[i]['selected'] == 1) {
item.observations = await getObservations(list[i]['id']);
}
items.add(item);
}
return items;
}
}
Interacting with dbHelper class:
Future<List<Item>> fetchItemsFromDatabase() async {
var dbHelper = DatabaseHelper();
Future<List<Item>> items = dbHelper.getItems();
return items;
}
I have common abstract provider like this:
abstract class DbProvider<T extends DbItem> {
static Future<String> get localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
Database db;
Future open() async {
String path = await localPath;
db = await openDatabase(join(path, file_name), version: 1, onCreate: (database, version) async {
await database.execute(''' create table */code for creating table/* ''');
});
}
Future _update(T item) async {
return await db.update(getTableName(), item.toMap(), where: "$col_dbId = ?", whereArgs: [item.dbId]);
}
Future _insert(T item) async {
return await db.insert(getTableName(), item.toMap());
}
Future delete(String dbId) async {
return await db.delete(getTableName(), where: "$col_dbId = ?", whereArgs: [dbId]);
}
Future close() => db.close();
Future remove() => db.delete(getTableName());
String getTableName();
Future save(T item);
Future<Iterable<T>> get();
}
And for doing some transactions:
void loadDbData() async {
FavoriteProvider favoriteProvider = FavoriteProvider();
await favoriteProvider.open();
Iterable<DbItem> favorites = await favoriteProvider.getConferences();
await favoriteProvider.close();
...
}

Categories

Resources