Flutter simultaneous images upload - flutter

I need to upload a list of images into a storage, but I don't want to upload and await for every single image after the other, because it takes quite some time.
I would like to upload them simultaneously, like in different threads.
There is a way to do achieve multithreading with standard dart async? Or should I use Isolates?
Do you have some sample code?

You can use them in a single future
final results = await Future.wait([
uploadFunction(image1)
uploadFunction(image2)
]);
you can start uploading all images without waiting for the previous one to complete await will be returned once both uploads are completed

You can use Queue
Whats it will do it will hold your actions and you can do other task while uploading images
import 'package:dart_queue/dart_queue.dart';
main() async {
final queue = Queue(parallel: 2);
final result1 = await queue.add(()=>Future.delayed(Duration(milliseconds: 10)));
final result2 = await queue.add(()=>Future.delayed(Duration(milliseconds: 10)));
//Thats it!
}
By using this you dont need to add await.
NOTE: Make sure app is running while this queue is active.

Related

How to view all Flutter app cache files and objects?

Listview / PageView Widgets do cache data and I don't know where, as well as Image.network and another bunch of widgets do cache data.
I know that you may clear cache by these methods below :-
and the methods mentioned in this thread
How to clear app cache programmatically on Flutter
setState(() {
imageCache.clear();
imageCache.clearLiveImages();
PaintingBinding.instance.imageCache.clear();
});
But I'm not sure that I have deleted ALL cached data allover the app,
Are these enough to clear all cached data or there are more ?
and How can you list and view all the cached data that are misteriously hidden somewhere I don't know where !?
please excuse my ignorance
This would not be the answer as I still don't know how to list and read all the data
but I could gather number of functions that make up a good cocktail to cleanup my heavy app
Future<void> deleteAllCacheThereIsInThisHeavyLaggyAppThatSucksMemoryLikeABlackHole() async {
await Future.wait(<Future>[
getTemporaryDirectory().then((Directory directory) async {
await Directory(directory.path).delete(recursive: true);
}),
getApplicationDocumentsDirectory().then((Directory directory) async {
await Directory(directory.path).delete(recursive: true);
}),
DefaultCacheManager().emptyCache(),
]);
imageCache.clear();
imageCache.clearLiveImages();
PaintingBinding.instance.imageCache.clear();
}
notice that i used this package https://pub.dev/packages/flutter_cache_manager as well
Please feel free to add any method that deletes any hidden magical cached file that I do not know about
I prefer to call these methods multiple times rather than having my app too heavy to navigate

Saving Local Data for a list on Flutter

I have an app that plays a sound. There is a list of sounds and I show that to an listview. So user can click a listtile and plays a sound. And I added a "Favourite" section. And it works fine. But when user closes the app it goes away. I tried to use SharedPrefences but I couldnt manage to do it. Because I need to save the whole list and I dont know how.
When I close the app, all my 'favourite' list goes away.
I will just share all the codes for better understanding:
Main.dart
Favourite.dart
Here is the explaining with the pictures:
Since the list of saved songs is a list of Strings you can use setStringList() method from SharedPrefences. When you want to save the list, use:
final prefs = await SharedPreferences.getInstance();
await prefs.setStringList('savedSounds', savedSounds);
Then when the application starts you load the songs by using:
final prefs = await SharedPreferences.getInstance();
savedSounds = prefs.getStringList('savedSounds') ?? [];
Then you can use a for-loop to also get the saved indexes, although I would recommend you to try only using one list of the saved songs.
for(int i = 0; i < savedSounds.length; i++){
if(soundList[i] == savedSounds[i]){
savedIndex.add(i.toString());
}
}
You can use the SQFlite package to store your List items locally. Here is the package:
https://pub.dev/packages/sqflite

Where can I store the images for my android app?

I am building an app in flutter and I want to store many images. So will anyone suggest me where I can store the images which is easy to use in my app. I mean should I store it locally or in cloud? If yes which cloud or backend should I use, whichone is good and fully optimized for my flutter app (like mongo, django, firebase etc. ). Will anyone suggest me the best?
Anyone kind of help is appreaciated as I have no prior knowledge about the production part....
Storing Images on a server can be very expensive, since the file sizes are very large compared to the usual data. So if you do not NEED to store them on a server, don't.
Storing images locally is pretty simple. You will want to use the path_provider package https://pub.dev/packages/path_provider . I ll post a function I am using in my current project that does this. You ll see, its pretty simple.
Note: In my Code I pull the file from my server. Obviously leave that part out if you are getting your images from a different source.
Future<File> createFileOfPdfUrl(String fileLocation, String name) async {
final url = Helper.baseUrl + "Files/Newsletter/" + fileLocation;
final filename = url.substring(url.lastIndexOf("/") + 1);
var request = await HttpClient().getUrl(Uri.parse(url));
var response = await request.close();
var bytes = await consolidateHttpClientResponseBytes(response);
String dir = (await pathProvider.getApplicationDocumentsDirectory()).path;
File file = new File('$dir/$filename');
await file.writeAsBytes(bytes);
return file;
}

Flutter - How check new verson with Firebase Remote Config

I try to check if my app has new version. If has new version shows a modal to force to update. I use the firebase remote config package.
The code looks
versionCheck(context) async {
PackageInfo info = await PackageInfo.fromPlatform();
RemoteConfig remoteConfig = await RemoteConfig.instance;
await remoteConfig.fetch();
await remoteConfig.activateFetched();
final currentBuildNumber = int.parse(info.buildNumber);
final requiredBuildNumber = remoteConfig
.getInt('android_app_version');
if (requiredBuildNumber > currentBuildNumber) {
versionDialog(context);
}
}
The problem: currentBuildNumber return the correct number, but the requiredBuildNumber always return '50', so the if conditional doesn´t work as expected. Something is wrong but don't i don't know what. What´s is the rigth way to do this?
If the app fetches so many times in a short period of time it the fetch calls are throttled. Because of the throttling limits, it is not possible for your app to immediately see changes in Remote Config values. Cached values will be used until the next fetch is allowed. The default cache expiration is 12 hours. This is done to optimize the network usage by Remote Config feature.
Keep in mind that this setting should be used for development only,
not for an app running in production. If you're just testing your app
with a small 10-person development team, you are unlikely to hit the
hourly service-side quota limits. But if you pushed your app out to
thousands of test users with a very low minimum fetch interval, your
app would probably hit this quota.

Async/Await/then in Dart/Flutter

I have a flutter application where I am using the SQFLITE plugin to fetch data from SQLite DB. Here I am facing a weird problem. As per my understanding, we use either async/await or then() function for async programming.
Here I have a db.query() method which is conducting some SQL queries to fetch data from the DB. After this function fetches the data, we do some further processing in the .then() function. However, in this approach, I was facing some issues. From where I am calling this getExpensesByFundId(int fundId)function, it doesn't seem to fetch the data properly. It's supposed to return Future> object which will be then converted to List when the data is available. But when I call it doesn't work.
However, I just did some experimentation with it and added "await" keyword in front of the db.query() function and somehow it just started to work fine. Can you explain why adding the await keyword is solving this issue? I thought when using .then() function, we don't need to use the await keyword.
Here are my codes:
Future<List<Expense>> getExpensesByFundId(int fundId) async {
Database db = await database;
List<Expense> expenseList = List();
// The await in the below line is what I'm talking about
await db.query(expTable,where: '$expTable.$expFundId = $fundId')
.then((List<Map<String,dynamic>> expList){
expList.forEach((Map<String, dynamic> expMap){
expenseList.add(Expense.fromMap(expMap));
});
});
return expenseList;
}
In simple words:
await is meant to interrupt the process flow until the async method has finished.
then however does not interrupt the process flow (meaning the next instructions will be executed) but enables you to run code when the async method is finished.
In your example, you cannot achieve what you want when you use then because the code is not 'waiting' and the return statement is processed and thus returns an empty list.
When you add the await, you explicitly say: 'don't go further until my Future method is completed (namely the then part).
You could write your code as follows to achieve the same result using only await:
Future<List<Expense>> getExpensesByFundId(int fundId) async {
Database db = await database;
List<Expense> expenseList = List();
List<Map<String,dynamic>> expList = await db.query(expTable,where: '$expTable.$expFundId = $fundId');
expList.forEach((Map<String, dynamic> expMap) {
expenseList.add(Expense.fromMap(expMap));
});
return expenseList;
}
You could also choose to use only the then part, but you need to ensure that you call getExpensesByFundId properly afterwards:
Future<List<Expense>> getExpensesByFundId(int fundId) async {
Database db = await database;
List<Expense> expenseList = List();
return db.query(expTable,where: '$expTable.$expFundId = $fundId')
.then((List<Map<String,dynamic>> expList){
expList.forEach((Map<String, dynamic> expMap){
expenseList.add(Expense.fromMap(expMap));
});
});
}
// call either with an await
List<Expense> list = await getExpensesByFundId(1);
// or with a then (knowing that this will not interrupt the process flow and process the next instruction
getExpensesByFundId(1).then((List<Expense> l) { /*...*/ });
Adding to the above answers.
Flutter Application is said to be a step by step execution of code, but it's not like that.
There are a lot of events going to be triggered in the lifecycle of applications like Click Event, Timers, and all. There must be some code that should be running in the background thread.
How background work execute:
So there are two Queues
Microtask Queue
Event Queue
Microtask Queue runs the code which not supposed to be run by any event(click, timer, etc). It can contain both sync and async work.
Event Queue runs when any external click event occurs in the application like Click event, then that block execution done inside the event loop.
The below diagram will explain in detail how execution will proceed.
Note: At any given point of application development Microtask queue will run then only Event Queue will be able to run.
When making class use async for using await its simple logic to make a wait state in your function until your data is retrieve to show.
Example: 1) Its like when you follow click button 2) Data first store in database than Future function use to retrieve data 3) Move that data into variable and than show in screen 4) Variable show like increment in your following/profile.
And then is use one by one step of code, store data in variable and then move to next.
Example: If I click in follow button until data store in variable it continuously retrieve some data to store and not allow next function to run, and if one task is complete than move to another.
Same as your question i was also doing experiment in social media flutter app and this is my understanding. I hope this would help.
A Flutter question from an answer from your answer.
await is meant to interrupt the process flow until the async method has finished. then however does not interrupt the process flow but enables you to run code when the async method is finished. So, I am asking diff. between top down & bottom down process in programming.