Future builder build only after all recursive call finished - flutter

my recursive function to get all .jpg files from device
Directory dir = Directory("/storage/emulated/0");
late CameraController controller;
List<String> visited = [];
List<String> files = [];
Future getphotos(olddir) async {
Directory newdir = olddir;
for (var item in newdir.listSync()) {
if (item.runtimeType.toString() == "_Directory" &&
!visited.contains(item.toString()) &&
!item.path.contains(".thumbnail")) {
visited.add(item.toString());
await getphotos(item);
} else {
if (item.path.endsWith(".jpg")) {
files.add(item.path);
}
}
}
my future builder
FutureBuilder<Object>(
future: temp(),
builder: (context, snapshot) {
return GridView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 5),
//if file/folder list is grabbed, then show here
itemCount: snapshot.hasData ? files.length : 5,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(3.0),
child: !snapshot.hasData
? Image.asset("assets/images/load.gif")
: Image.file(
File(files[index]),
fit: BoxFit.cover,
filterQuality: FilterQuality.low,
width: 200,
height: 200,
),
);
});
});
problem: my futurebuilder build its child widget only when the above recursive function is finished, screen stuck while its loading all the images path

Related

Flutter FutureBuilder duplicates items inside a GridView

It seems that the GridView.builder inside FutureBuilder duplicates each element a number of times equal to the list length.
Here is the code:
InformationScreen:
List<Reference> documentReference = [];
Widget showSavedDocument() => FutureBuilder(
future: _futureListResult,
builder: (context, AsyncSnapshot<ListResult> snapshot) {
if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.items.length,
itemBuilder: (context, index) {
final photo = snapshot.data!.items[index].getDownloadURL();
final photoName = snapshot.data!.items[index].name;
final metaData = snapshot.data!.items[index].getMetadata();
documentReference = snapshot.data!.items;
return Column(
children: [
FutureBuilder(
future: metaData,
builder: (context, AsyncSnapshot<FullMetadata> snapshot) {
if(snapshot.hasData) {
photoType = snapshot.data!.contentType!;
}
return Container();
},
),
FutureBuilder(
future: photo,
builder: (context, AsyncSnapshot<String?> snapshot) {
if (snapshot.hasData) {
final image = snapshot.data;
List<Document> documents = [];
for (int i = 0; i < documentReference.length; i++) {
Document document = Document(user!.uid, image!, photoName, photoType);
documents.add(document);
}
return DocumentGrid(documents: documents,); // <------------------------------
}
return Container();
},
),
],
);
},
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
);
}
if (snapshot.connectionState == ConnectionState.waiting || !snapshot.hasData) {
return const Loader();
}
if (snapshot.hasError) {
return Utils.showErrorMessage(snapshot.hasError.toString());
}
return Container();
},
);
DocumentGrid
import 'package:flutter/material.dart';
import 'package:app_test/constant/color.dart';
import '../constant/text.dart';
import '../model/document.dart';
class DocumentGrid extends StatelessWidget {
final List<Document> documents;
const DocumentGrid({Key? key, required this.documents}) : super(key: key);
#override
Widget build(BuildContext context) {
return buildGridView();
}
//****************************************************************************
// Create GridView
//****************************************************************************
Widget buildGridView() => GridView.builder(
itemCount: documents.length,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 2,
mainAxisSpacing: 2,
),
itemBuilder: (context, index) {
final photo = documents[index].photo;
final title = documents[index].title;
final type = documents[index].type;
return buildGridViewItem(photo, title, type);
},
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
);
//****************************************************************************
// Create GridView item
//****************************************************************************
Widget buildGridViewItem(String photo, String? title, String type) => Container(
width: 50,
height: 50,
color: phoneButtonColor,
child: Stack(
fit: StackFit.expand,
alignment: Alignment.center,
children: [
buildNetworkImage(photo, type),
buildBlackOpacity(title),
],
),
);
//****************************************************************************
// Create Network image
//****************************************************************************
Widget buildNetworkImage(String photo, String type) => Image.network(
fit: BoxFit.cover,
width: 100,
height: 100,
photo,
errorBuilder: (context, exception, stackTrace) {
return type == "pdf" || type != "jpg"
|| type != "jpeg" || type != "png"
? Image.asset(
fit: BoxFit.cover,
width: 100,
height: 100,
"assets/images/pdf.png",
)
: Container(
color: grey,
width: 100,
height: 100,
child: const Center(
child: Text(
errorLoadImage,
textAlign: TextAlign.center,
),
),
);
},
);
//****************************************************************************
// Create Black opacity
//****************************************************************************
Widget buildBlackOpacity(String? title) => Container(
color: Colors.black54,
padding: const EdgeInsets.symmetric(
vertical: 30,
horizontal: 20,
),
child: Column(
children: [
Expanded(
child: Center(
child: Text(
title!,
style: const TextStyle(
fontSize: 20,
color: Colors.white,
),
),
),
),
],
),
);
}
How can I solve that, thanks in advance
Problem solved
Replacing ListView by GridView
Widget showSavedDocument() => FutureBuilder(
future: _futureListResult,
builder: (context, AsyncSnapshot<ListResult> snapshot) {
if(snapshot.connectionState == ConnectionState.done && snapshot.hasData) {
return GridView.builder(
itemCount: snapshot.data!.items.length,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 2,
mainAxisSpacing: 2,
),
itemBuilder: (context, index) {
final instructorDocument = snapshot.data!.items;
final photo = instructorDocument[index].getDownloadURL();
final photoName = instructorDocument[index].name;
final metaData = instructorDocument[index].getMetadata();
return Column(
children: [
FutureBuilder(
future: metaData,
builder: (context, AsyncSnapshot<FullMetadata> snapshot) {
if (snapshot.hasData) {
photoType = snapshot.data!.contentType!;
}
return Container();
},
),
FutureBuilder(
future: photo,
builder: (context, AsyncSnapshot<String?> snapshot) {
if (snapshot.hasData) {
final image = snapshot.data!;
return Expanded(
child: buildGridViewItem(image, photoName, photoType),
);
}
return Container();
},
),
],
);
},
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
);
}
if(snapshot.connectionState == ConnectionState.waiting || !snapshot.hasData) {
return const Loader();
}
if(snapshot.hasError) {
return Utils.showErrorMessage(snapshot.hasError.toString());
}
return Container();
},
);

Firebase String doesn't automatically line break when inserting it in Flutter Text Widget

So I use Firebase as my backend.
The String about which Im talking looks like this:
When I add this String as a variable in my Text Widget
Text("${beschreibung}")
the text doesn't automatically line break, its just cut off by the right side of the screen
How can I achieve a behaviour where this doesn't happen & get flutter to detect the spaces to automatically line break?
Additional Details
Here Im getting the data from firebase and passing it on:
class Produkte extends StatelessWidget {
final Stream<QuerySnapshot> data =
FirebaseFirestore.instance.collection("products").snapshots();
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Container(
width: MediaQuery.of(context).size.width,
child: StreamBuilder<QuerySnapshot>(
stream: data,
builder: ((BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text("Some error");
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("loading");
}
final data = snapshot.requireData;
return Container(
height: 800,
child: GridView.builder(
itemCount: data.size,
itemBuilder: (context, index) {
return ProductTile(
titel: data.docs[index]["Name"].isNotEmpty
? data.docs[index]["Name"]
: " ",
beschreibung:
data.docs[index]["Beschreibung"].isNotEmpty
? data.docs[index]["Beschreibung"]
: " ");
},
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 5,
crossAxisSpacing: 2),
));
}),
),
),
),
);
}
}
& here Im using the data
class Produkt extends StatelessWidget {
Produkt({required this.titel, required this.beschreibung});
final List<String> beschreibung;
final String titel;
#override
Widget build(BuildContext context) {
return Scaffold(body:
Container(
height: 350,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: beschreibung.length,
itemBuilder: (context, index) {
return Text("${beschreibung[index]}");
},
),
),
);
}
}
Add width to the container so the text knows where to break and use a new line and remove the axis horizontal..
return Scaffold(body:
Container(
height: 350,
width: MediaQuery.of(context).size.width,
child: ListView.builder(
itemCount: beschreibung.length,
itemBuilder: (context, index) {
return Text("${beschreibung[index]}");
},
),
),
If you wish to keep the horizontal scroll but still have the text in one screen then add a container to the text
return Scaffold(body:
Container(
height: 350,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: beschreibung.length,
itemBuilder: (context, index) {
return Container( width: MediaQuery.of(context).size.width,
child : Text("${beschreibung[index]}")
);
},
),
),

Error: No AWSAccessKey was presented - flutter Amplify

I have a code like this in my flutter project:
final imageUrl = await Amplify.Storage.getUrl(key: urlKey);
return StreamBuilder(
stream: imageUrl.url,
builder: (context, snapshot) {
if (snapshot.hasData) {
if (snapshot.data.length != 0) {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 1),
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return CachedNetworkImage(
imageUrl: snapshot.data,
fit: BoxFit.cover,
placeholder: (context, url) => Container(
alignment: Alignment.center,
child: CircularProgressIndicator(),
),
);
});
} else {
// 5
return Center(child: Text('No images to display.'));
}
} else {
// 6
return Center(child: CircularProgressIndicator());
}
});
I figured that in order to access an existing object from your bucket with amplify, you have to put those objects in a Public folder. So your URL should be something like: aws..../public/other-folders-or-assets

Why GridView.builder clear when obtain more data in flutter

I have my GRidView builder and I have my future and my ScrollController, why my gridView clear when scrollController is equal than mi maxScroll and obtain more information? It's supposed to show all of it, not the latest information.
this is my code
future: _future ,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if(snapshot.hasData){
List<dynamic> loaded = snapshot.data;
return
Container(
width: double.infinity,
height: _screenSize.height * .8,
child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: MediaQuery.of(context).size.width /(MediaQuery.of(context).size.height /1.5),),
controller: _controller,
itemCount: loaded.length,
itemBuilder: (context, i){
return _row(context,loaded,i);
},
)
);
}else{
and the constructor
Future<List> _future;
ScrollController _controller = ScrollController(initialScrollOffset: 0.0, keepScrollOffset: true);
_SearchPageState(){
_controller.addListener(() {
if(_controller.position.pixels >= _controller.position.maxScrollExtent-30 ){
setState(() {
_future = videoJuegos.getPaginationPopular();
});
}
});
_future = videoJuegos.getPaginationPopular();
}
Your Gridview.builder is clearing because of this line:
List<dynamic> loaded = snapshot.data;
It will clear the current list and add the new data. You should use initialize your list above the future and then use list.add:
List<dynamic> loaded = [];
future: _future ,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if(snapshot.hasData){
loaded.add(snapshot.data);
return
Container(
width: double.infinity,
height: _screenSize.height * .8,
child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: MediaQuery.of(context).size.width /(MediaQuery.of(context).size.height /1.5),),
controller: _controller,
itemCount: loaded.length,
itemBuilder: (context, i){
return _row(context,loaded,i);
},
)
);
}else{
Hope that helps.

Flutter carouse_slider image always refresh make app crash

I have problem when listing multi images from api to carousel_slider.
It always crash and show no error.
I have compare to my old app, it works as normal, but another one always crash.
return ChangeNotifierProvider(
create: (context) => HomeProvider(),
child: Consumer<HomeProvider>(builder: (bContext, homeProderAction, _) {
return RefreshIndicator(
key: refreshKey,
onRefresh: () async {
refreshKey.currentState?.show(atTop: false);
await Future.delayed(Duration(seconds: 1));
homeProderAction.setHomeData(homeData: fetchHomeData());
return null;
},
child: FutureBuilder<HomeModel>(
future: _homeData,
builder: (context, snapshot) {
print('hello world');
// if (_source.keys.toList()[0] == ConnectivityResult.wifi ||
// _source.keys.toList()[0] == ConnectivityResult.mobile) {
if (snapshot.hasData &&
snapshot.connectionState == ConnectionState.done) {
// return Container(
// child: ListView.builder(
// itemCount: 2 + snapshot.data.categories.length,
// shrinkWrap: true,
// addAutomaticKeepAlives: true,
// itemBuilder: (context, ind) {
// //Developer sum array of banner and course together
// //That's why list index 0 for homepage banner
// //And other for other ...
// if (ind == 0) {
return Container(
width: MediaQuery.of(context).size.width,
child: CarouselSlider.builder(
enableInfiniteScroll: true,
viewportFraction: 1.0,
height: 100,
itemCount: snapshot.data.courses.length,
itemBuilder: (context, ind) {
return Container(
width: 100,
height: 100,
color: Colors.pink,