Unable to execute inner statements of a for loop in Dart - flutter

I am trying to display an image in my weather app based on the current weather condition.
I have a jsonConditionsDay variable which stores JSON data fetched from https://www.weatherapi.com/docs/conditions.json.
I have a List<String> conditionsDayImgUrls = []; //network image urls contained in this which stores image urls.
Current weather data is fetched using dio from https://www.weatherapi.com/api-explorer.aspx#forecast and stored in a variable jsonData.
Now when I'm calling the following function String getCurrentConditionsBgImgForDay(String str) I am not getting the desired image from the conditionsDayImgUrls list, instead I'm only getting the first image of the list.
Code for getCurrentConditionsBgImgForDay in global_variables.dart:
String getCurrentConditionsBgImgForDay(String str) {
int i;
for (i = 0; i < jsonConditions.length; i++) {
if (str == jsonConditions[i]["day"]) {
return conditionsDayImgUrls[i];
}
}
//print(i);
return conditionsDayImgUrls[0];
}
The following code in current_weather_screen.dart tries to display the desired weather image based on current weather condition:
Container(
width: screenWidth,
height: screenHeight,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(
getCurrentConditionsBgImgForDay(
jsonData["current"]
["condition"]["text"])),
fit: BoxFit.fill,
),
),
),
What is wrong in my code that is preventing it from displaying the correct weather image and how to solve it?

Related

Exception Flutter from fetch network Image without connection internet

after turning off the internet i gets this error: "Remove network images from cache on any exception during loading"
my app fetch pictures from api. how can i fix this bug how i prevent that?
return Column(children: [
GestureDetector(
child: Image.network(thumbnailUrl))])
You can use the Cached Network Image Plugin if you are developing for android and ios. In Web, the plugin is not working as expected.
Use the following as a widget for your application.
import 'package:cached_network_image/cached_network_image.dart';
Widget commonCacheImageWidget(String? url, {double? width, BoxFit? fit, double? height}) {
if (url!.startsWith('http')) {
return CachedNetworkImage(
placeholder: (context, url) => Image.asset('assets/path....', fit: BoxFit.cover),
imageUrl: url,
height: height,
width: width,
fit: fit,
);
} else {
return Image.asset(url, height: height, width: width, fit: fit);
}
}
In Placeholder you can have any widget, here am using a local image that is stored as an asset.
Or You can check whether the internet connection is there or not before loading the image and change that to some other widget.

How do I cache images from firebase in flutter?

I have been trying to do a cache management system in my flutter app. Ideally I want to retrieve images from firebase storage and display them along with other details. I retrieve the snapshots from firestore and have used cachednetworkimage to display the images. But the amount of images I display is a lot and is causing my app to crash. I believe if I was caching the image locally, that problem would be solved. And besides that, I also want to cache json files so that in offline mode, my app will display both the cached images and the other details available in the cache memory.
I want to display posts, which contain username, user profile picture, the image post itself, caption and comments. So the way I retrieve the posts is according to the following...
void fetchFeed() async {
auth.User currentUser = await _repository.getCurrentUser();
User user = await _repository.fetchUserDetailsById(currentUser.uid);
setState(() {
this.currentUser = user;
});
setState(() {
loadingPosts = true;
});
Query query = _firestore.collection("users").doc(user.uid).collection("following").orderBy("uid").limit(perPage);
QuerySnapshot querySnapshot = await query.get();
for (var i = 0; i < querySnapshot.docs.length; i++) {
followingUIDs.add(querySnapshot.docs[i].id);
}
for (var i = 0; i < followingUIDs.length; i++) {
Query posts = _firestore.collection("users").doc(followingUIDs[i]).collection("posts").orderBy("time").limit(perUser);
QuerySnapshot postSnapshot = await posts.get();
lastPost = postSnapshot.docs[postSnapshot.docs.length -1];
for (var i = 0; i < postSnapshot.docs.length; i++) {
feedlist.add(postSnapshot.docs[i]);
}
}
setState(() {
loadingPosts = false;
});
}
And after I retrieved the posts, I put them in a listview and show them sequentially. The problem I am getting is that since the images are not cached locally, I use cached network image widget to display them. And whenever I navigate to another page and return, all the cached network images get reloaded and that puts a big load on the app, which causes it to crash.
CachedNetworkImage(
imageUrl: list[index].data()['imgUrl'],
placeholder: ((context, url) => Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/Black.png'),
fit: BoxFit.cover),
))),
fit: BoxFit.fitWidth,
),
Alternatively, I tried to download the images and save them locally using the following function. And I call the function for every image item I retrieve from firebase. But that just distorts the images for some reason.
Future <Null> downloadFile(String httpPath) async{
final StorageReference ref = await FirebaseStorage.instance.getReferenceFromUrl(httpPath);
final StorageFileDownloadTask downloadTask = ref.writeToFile(file);
final int byteNumber = (await downloadTask.future).totalByteCount;
print(byteNumber);
setState(() => _cachedFile = file);
}
The http path is a download url I got for each image. But I am not sure if this is the best way to download images. Since I don't have a way to know the image file names as they appear in firebase storage, this was my only option.
Can someone tell me an alternative way to download and cache images, and also json files (which contain username, comments, caption) in my case, so that I can show them offline?
For this purpose use cached_network_image package. which also support placeholders and fading images in as they’re loaded.
CachedNetworkImage( imageUrl: 'https://picsum.photos/250?image=9');
Complete Example
`
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: CachedNetworkImage(
placeholder: (context, url) => CircularProgressIndicator(),
imageUrl:
'https://picsum.photos/250?image=9',
),
),
),
);
`

Converting base64 to Image in Flutter Error

I have this image as a base64 String which I then want to convert to image in BoxDecoration like so:
Container(
decoration: BoxDecoration(image: DecorationImage(image: Utility.imageFromBase64String(drink.image))),
Here is the function that decodes the String to Image.
Function
class Utility {
static Image imageFromBase64String(String base64String) {
return Image.memory(
base64Decode(base64String),
fit: BoxFit.fill,
);
}}
However, I am getting an error in BoxDecoration:
The argument type 'Image' can't be assigned to the parameter type 'ImageProvider<Object>'
The error is in this part, I suppose I can't put in Image since it asks for ImageProvider:
image: DecorationImage(image: Utility.imageFromBase64String(drink.image))
Any ideas how to make it work? Thanks!
The image property from DecorationImage is of type ImageProvider<object> not Image.
Return a MemoryImage from imageFromBase64String like so
static MemoryImage imageFromBase64String(String base64String) {
return MemoryImage(
base64Decode(base64String)
);
}
Then this.
image: DecorationImage(
image: Utility.imageFromBase64String(drink.image),
fit: BoxFit.fill,
)

Removing image from cache when using Image.network

Im using Image.Network to display a image based on a URL :
ClipOval(
child: Image.network(
'http://myurl${userId}.png',
width: 100,
height: 100,
fit: BoxFit.cover,
key: profileImageKey,
),
),
I'm trying get the user to upload a new profile image, however, i'm retaining the same filename (userid + .png). Once the user has uploaded the image the above is display is not displaying the new image.
I've tried rebuilding the widget using :
setState(() {
//generateKey();
profileImageKey = ValueKey(new Random().nextInt(100));
userId = userId;
});
I've also tried removing the url from the cache using :
PaintingBinding.instance.imageCache.evict('http://myurl${userId}.png');
However, none of these methods work. Is there a way to update the Image.Network to download and use the new image that was uploaded ?
Thanks
Based on #pskink's comment https://stackoverflow.com/a/60916852/2252830
The solution to this question was to use the evict method on Image. So I refactored my code to below :
Image profileImage;
...
profileImage = Image.network(
'http://myurl${userId}.png',
width: 100,
height: 100,
fit: BoxFit.cover,
key: profileImageKey,
);
...
ClipOval(
child: profileImage,
),
...
profileImage.image.evict();
setState(() {
//generateKey();
profileImageKey = ValueKey(new Random().nextInt(100));
userId = userId;
});

"Unable to load asset" with image picker

I'm using Image Picker package in my Flutter project
I choose image from gallery then preview it in Image.asset widget
The problem here is if image name "example_name.png" (without spaces) the image is visible on the screen, but if image name "example name.png" (with spaces) the image is invisible like this Screenshot.
Error: Unable to load asset: /storage/emulated/0/Download/images (9).jpeg
File _image;
Image.asset(
_image != null
? "${_image.path}"
: getImage("icon.png"),
fit: BoxFit.cover,
width: 120,
height: 120,
);
...
Future chooseFile() async {
await ImagePicker.pickImage(source: ImageSource.gallery).then((image) {
setState(() {
_image = image;
});
});
}
You are using the wrong Image constructor. Use Image.file instead of Image.asset. Image.asset load files packaged in the application (assets section of pubspec.yaml) and ImagePicker does not have access to them.
in the image_picker (version 0.6.7 + 22) I was able to recover the image with this condition
if (photo == null) {
return Image (
image: AssetImage ('assets / no-image.png'),
height: 300.0,
fit: BoxFit.cover,
);
} else {
return Image.file (
Photo,
height: 300.0,
fit: BoxFit.cover,
);
}
Using Image.file is a good option but you like to display it in an effective way use
Image.file(_image).image this will help you to convert Image file to image provider