Flutter: "(path): must not be null" on conditional file checks - image

I am trying to have a background to my application that either the user has chosen previously, or to use a default image if no file is found.
The code is very simple:
decoration: BoxDecoration(
color: Colors.blueAccent,
image: DecorationImage(
image: File(customImageFile).existsSync() ? FileImage(File(customImageFile)) : backgroundImage,
fit: BoxFit.fill,
),
),
The application crashes on the conditional line, saying that (path): Must not be null. I have tried many ways to get around this, but what I am specifically saying there is "if the file path is null, don't use it. Use this image I made earlier for you". But then it gets upset anyway.
Is there another way I can achieve the intended result here?
Edit:
As requested by #Vikas, more complete sample of code involved:
ImageProvider backgroundImage;
String themeLoader = 'blueTheme';
String customImageFile;
// Declaration
void initState() {
_loadThemeSettings();
super.initState();
}
// Initialisation
_loadThemeSettings() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
themeLoader = prefs.getString('themeColour' ?? 'blueTheme');
customImageFile = prefs.getString('customImageFile' ?? 'empty')
if (customImageFile != null) {
if(File(customImageFile).existsSync()) {
prefs.setString('customImageFile', customImageFile);
} else {
print('Path not valid');
}
} else {
print('customImageFile is NULL');
}
if (themeLoader != null) {
switch (themeLoader) {
case 'blueTheme':
{
colorBloc.changeColor('blueTheme');
setState(() {
backgroundImage = ExactAssetImage('lib/images/bg_blue_new.jpg');
buttonTheme = AppState.blueTheme;
}
}
break;
} else {
print('Theme loader was NULL');
}
}
}
}
// Loading previously selected themes at run time. There are several colours here in the case statement, but they are all identical and you get the idea.
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () => _exitApp(context),
child: Scaffold(
body: SafeArea(
child: BlocProvider<ColorBloc>(
bloc: colorBloc,
child: Container(
child: Stack(
children: [
Container(
decoration: BoxDecoration(
color: Colors.blueAccent,
image: DecorationImage(
image: (customImageFile != null && File(customImageFile).existsSync()) ? FileImage(File(customImageFile)) : backgroundImage,
fit: BoxFit.fill,
),
),
// that's where it sits, everything else works fine. The rest of the build method is not relevant to this issue, and is working, but here it is anyway:
child: SafeArea(
child: Stack(
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
themesVisible == true
? SizedBox()
: buttonRow(),
SizedBox(
height: 20,
),
],
),
Padding(
padding: EdgeInsets.all(15),
child: topMenuRow(),
),
],
),
),
),
BlocProvider<CustomToggleBloc>(
bloc: customToggleBloc,
child: Center(
child: Container(
child: themesVisible == true ? singlePlayerThemes(singlePlayerCallbacks: callBacks) : scoreText(),
),
),
),//bloc
],
),
),
),
),
),
);
}

Related

Flutter 2 second shows error when page load and ater 2 secons successfully shows

Hello Any One Flutter Expert here ?? plz help meee...what i want to make is Like Facebook photo viewer when user slides images and check is this like or not same i want in my code...
i made my code in that i come from listing page and when i tap on listing i can see full screen image.. and i Can slide(Scroll) images...
BUTTT when i comes first time on this screen which i code it show me some bugs on screen for 3,4 seconds...after that i can see the image plz help mee and show my error
Future<PhotoDetail> pagedetail() async {
sharedPreferences = await SharedPreferences.getInstance();
Map data = {
"AccessToken": sharedPreferences.getString("AccessToken"),
"CustomerId": sharedPreferences.getInt("CustomerId"),
"ImageId": indexx == null ? widget.images[widget.currentindex].photoId : indexx
};
print(data);
final http.Response response = await http.post(
Constants.CUSTOMER_WEBSERVICE_URL + "/photo/detail",
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(data),
);
var jsonResponse = json.decode(response.body);
if (response.statusCode == 200) {
print("Response status : ${response.statusCode}");
print("Response status : ${response.body}");
isLike = jsonResponse["IsLike"]; //here i saving value when api is run
print("iSLiked Value:" +isLike.toString()); // value is printing here
return PhotoDetail.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load data');
}
}
Future<PhotoDetail> _photoDetail;
#override
void initState() {
_photoDetail = pagedetail();
setState(() {
pagedetail(); //here is my api run when page is load
});
super.initState();
}
void pageChange(int index){ //this method is when i scroll page
setState(() {
pagedetail(); // api is call again and again
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
body: Stack(
children: <Widget>[
Container(
child:
Center(
child: PhotoViewGallery.builder(
itemCount: widget.images.length,
builder: (BuildContext context , int index) {
return PhotoViewGalleryPageOptions(
imageProvider:
NetworkImage(widget.images[index].photoPreviewImagePath),
maxScale: PhotoViewComputedScale.covered * 1.8,
minScale: PhotoViewComputedScale.contained * 1.0,
);
},
pageController: _pageController,
enableRotation: false,
scrollDirection: Axis.horizontal,
onPageChanged: pageChange,
loadingBuilder: (BuildContext context , ImageChunkEvent event){
return Center(child: CircularProgressIndicator(),);
},
)
)
),
Positioned(
bottom: 10,
left: 30,
right: 30,
child: (_photoDetail == null) ? Text("error")
: FutureBuilder<PhotoDetail>(
future: _photoDetail,
// ignore: missing_return
builder: (context , snapshot){
int like = snapshot.data.isLike;
int Slection = snapshot.data.selectedCount;
print("like ?????:" +like.toString());
print("Selection ????? :" + Slection.toString());
if (snapshot.hasData){
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
InkWell(
child: InkWell(
Likes();
Fluttertoast.showToast(
msg: "Liked",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Color(0xfff58634),
textColor: Colors.white,
fontSize: 16.0
);
},
child: Icon(Icons.thumb_up,size: 20,color: like == 1 ? Color(0xfff58634) : Colors.white),
),
),
InkWell(
child: Icon(Icons.comment,size: 20,color: Colors.white),
),
InkWell(
onTap: (){
_onShare();
},
child: Icon(Icons.share,size: 20,color: Colors.white,),
),
InkWell(
onTap: (){},
child: Icon(Icons.photo_album,size: 20,color: Slection == 0 ? Colors.white : Color(0xfff58634)),
),
InkWell(
onTap: (){
setState(() {
viewwholike();
});
},
child: Icon(Icons.card_giftcard,size: 20,color:
Colors.white,),
),
]
);
}
else {
Text("error");
}
},
),
),
],
),
);
}
ERROR::════════ Exception caught by widgets library
═══════════════════════════════════════════════════════
The following NoSuchMethodError was thrown building
FutureBuilder<PhotoDetail>(dirty, state:
_FutureBuilderState<PhotoDetail>#ef81b):
The getter 'isLike' was called on null.
Receiver: null
Tried calling: isLike
The relevant error-causing widget was:
FutureBuilder<PhotoDetail>
file:///C:/Users/Hello%20Devloper/AndroidStudioProjects/
September/PhotoGranth-
App/lib/CampaignSinglePhotos.dart:400:15
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1 _CampaignSinglePhotosState.build.<anonymous closure>
(package:photogranth2020/CampaignSinglePhotos.dart:404:42)
#2 _FutureBuilderState.build
(package:flutter/src/widgets/async.dart:732:55)
#3 StatefulElement.build
(package:flutter/src/widgets/framework.dart:4619:28)
#4 ComponentElement.performRebuild
(package:flutter/src/widgets/framework.dart:4502:15)
Flutter tells you that data is not ready when you test snapshot.data.isLike.
You should test always at the beginning if snapshot.hasData, only after that you can make all you want.
Otherwise, if snapshot.hasData is false, simply return CircularProgressIndicator() .

firestore image not load to profile page

when i try to pull profile image from firestore daatabse, It show following error on profile page
'package:flutter/src/painting
_network_image_io.dart':
Failed assertion:line22
pos14:'url!=null':is
not true.
See also:
https://flutter.dev/docs/testing/errors
although it gives this error if i press ctrl+s it loads the profile page. This is my code.
String profilePicUrl;
#override
void initState() {
super.initState();
FirebaseAuth.instance.currentUser().then((user){
profilePicUrl=user.photoUrl;
}).catchError((e){
print(e);
});
}
and then i put profilpicUrl inside of networkImage, as follows
Container(
width: 150.0,
height: 150.0,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(profilePicUrl),
fit: BoxFit.cover,
),
borderRadius: BorderRadius.all(Radius.circular(75.0)),
boxShadow: [
BoxShadow(
blurRadius:7.0,
color:Colors.black
)
]
),
),
Every time i run the App i have to press ctrl+s to prevent the error and load the profile page
The image is not loading in time, first the initState is getting called and the build method is getting called before the image is received. Therefore, you can use FutureBuilder:
Container(
width: 150.0,
height: 150.0,
child: FutureBuilder(
builder: (context, AsyncSnapshot<FirebaseUser> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Image.network(profilePicUrl, fit: BoxFit.cover);
} else if (snapshot.connectionState == ConnectionState.none) {
return Text("No data");
}
return CircularProgressIndicator();
},
future: FirebaseAuth.instance.currentUser(),
),
),

How to get the number of data that are retrieving through response.body?

How can I get the number of data that are retrieving through response.body?
I tried many methods including below one to get that number. But non of them worked out pretty well.
var convertJsonToData = json.decode(response.body);
data = convertJsonToData;
data.forEach((element) => touristCount++);
The variable touristCount is declared and initialized to 0 at the beginning of this dart file.
Here are my codes.
AdminMenu.dart
String apiurl = "http://10.0.2.2:8000/api/retrieveTourists/";
List data;
var touristCount = 0;
class _AdminMenuState extends State<AdminMenu> {
#override
// var touristCount = 2;
// _AdminMenuState({this.touristCount});
void initState() {
super.initState();
this.getTouristCount(context);
}
void getTouristCount(BuildContext context) async {
var response = await http
.get(Uri.encodeFull(apiurl), headers: {"Accept": "application/json"});
if (this.mounted) {
setState(() {
var convertJsonToData = json.decode(response.body);
data = convertJsonToData;
data.forEach((element) => touristCount++);
});
}
}
..................
..................
....................
AuthController.php
public function retrieveTourists(){
$user = tourists::all();
return response()->json($user);
}
api.php
Route::get('/retrieveTourists','Api\AuthController#retrieveTourists');
All I want is to display the count at "Text" here.
Widget buttonSection1 = Container(
padding: const EdgeInsets.only(top: 30),
decoration: BoxDecoration(
border: Border.all(width: 5, color: Colors.black38),
borderRadius: const BorderRadius.all(const Radius.circular(8)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildButtonColumn(color, Icons.people, 'Guides'),
Text(touristCount.toString()), <----------------------------------- Display the count???
],
),
);
Can someone help me with this? :)
If your incoming data is an array, you can use the length property to get the number of data, like this:
if (this.mounted) {
setState(() {
var convertJsonToData = json.decode(response.body);
touristCount = convertJsonToData.length
});
}
I found a way to do that! We can get this thing done by passing the touristCount variable as a parameter to the buttonSection1 widget
Widget buttonSection1(int num_guides){
return Container(
padding: const EdgeInsets.only(top: 30),
decoration: BoxDecoration(
border: Border.all(width: 5, color: Colors.black38),
borderRadius: const BorderRadius.all(const Radius.circular(8)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildButtonColumn(color, Icons.people, 'Guides'),
Text(num_guides.toString()),
],
),
);
}
Calling the widget in build widget
Widget build(BuildContext context) {
return Container(
child: Scaffold(
appBar: AppBar(
leading: Icon(Icons.menu),
title: Text("Admin Menu"),
backgroundColor: Colors.indigo,
actions: <Widget>[
IconButton(icon: Icon(Icons.person)),
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
buttonSection1(touristCount),
.....................
.....................

How to upload image in Flutter using Image Picker

I tried to save image in image upload form using image picker, I used "OnSaved" but there are error said "The named Parameter OnSaved isnt defined. How can I solve this?
This is the code that i use :
onSaved: (val) => _image = val,
This is the complete code:
import 'dart:io';
import 'package:image_picker/image_picker.dart';
class NewPostScreen extends StatefulWidget {
#override
_NewPostScreen createState() => _NewPostScreen();
}
class _NewPostScreen extends State<NewPostScreen> {
File _image;
Future getImageFromGallery() async {
var image = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
_image = image;
});
}
#override
Widget build(BuildContext context) {
// TODO: implement build
return Container(
child: Scaffold(
key: _scaffoldkey,
appBar: AppBar(
backgroundColor: Colors.blue,
title: new Text("Create Post"),
),
resizeToAvoidBottomPadding: false,
body: SingleChildScrollView(
padding: new EdgeInsets.all(8.0),
child: Form(
key: _formkey,
child: Column(
children: <Widget>[
new TextFormField(
decoration: new InputDecoration(
/*hintText: "Tujuan",*/
labelText: "Tujuan"),
onSaved: (String val) => destination = val,
),
Padding(
padding: const EdgeInsets.all(15.0),
child: Center(
child: _image == null
? Text('Upload Foto')
: Image.file(_image),
onSaved: (val) => _image = val,
),
),
SizedBox(
width: 100.0,
height: 100.0,
child: RaisedButton(
onPressed: getImageFromGallery,
child: Icon(Icons.add_a_photo),
)),
there is no onSaved property in the Center widget. You can use a button instead and utilize the onPressed property or any other approach that you prefer.

Check image is loaded in Image.network widget in flutter

I am new to Flutter. I try to load network images using image.network widget. it's working fine but sometimes it takes time to load. I added tap listener to image.network during tap I need to check image is fully loaded or not based on the result I need to redirect the page. how to check image is loaded or not?
Code:
new Image.network('http://via.placeholder.com/350x150')
Any help will be appreciated, thank you in advance
You may use the loadingBuilder which is inbuilt feature from flutter for Image.Network
I did it as below:
Image.network(imageURL,fit: BoxFit.cover,
loadingBuilder:(BuildContext context, Widget child,ImageChunkEvent loadingProgress) {
if (loadingProgress == null) return child;
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null ?
loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes!
: null,
),
);
},
),
for this kind of issues it's good to use the cached_network_image
so you can provide a placeholder when the image is loading and an error widget in case a resource fails to load
String url = "http://via.placeholder.com/350x150";
CachedNetworkImage(
imageUrl: url,
placeholder: (context,url) => CircularProgressIndicator(),
errorWidget: (context,url,error) => new Icon(Icons.error),
),
for ones who do not need to cache the image can use meet_network_image package,
The package basic usage :
MeetNetworkImage(
imageUrl:
"https://random.dog/3f62f2c1-e0cb-4077-8cd9-1ca76bfe98d5.jpg",
loadingBuilder: (context) => Center(
child: CircularProgressIndicator(),
),
errorBuilder: (context, e) => Center(
child: Text('Error appear!'),
),
)
In addition, you can do that by yourself with using a FutureBuilder,
We need to get data with http call that way, we need to import http before import you also need to add pubspec.yaml and run the command flutter packages get
import 'package:http/http.dart' as http;
FutureBuilder(
// Paste your image URL inside the htt.get method as a parameter
future: http.get(
"https://random.dog/3f62f2c1-e0cb-4077-8cd9-1ca76bfe98d5.jpg"),
builder: (BuildContext context, AsyncSnapshot<http.Response> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('Press button to start.');
case ConnectionState.active:
case ConnectionState.waiting:
return CircularProgressIndicator();
case ConnectionState.done:
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
// when we get the data from the http call, we give the bodyBytes to Image.memory for showing the image
return Image.memory(snapshot.data.bodyBytes);
}
return null; // unreachable
},
);
This way it will start loading, then it will show the loading of the image loading and then the image. Best option if you don't want to use external libs.
Image.network(
imgUrl,
height: 300,
fit: BoxFit.contain,
frameBuilder: (_, image, loadingBuilder, __) {
if (loadingBuilder == null) {
return const SizedBox(
height: 300,
child: Center(child: CircularProgressIndicator()),
);
}
return image;
},
loadingBuilder: (BuildContext context, Widget image, ImageChunkEvent? loadingProgress) {
if (loadingProgress == null) return image;
return SizedBox(
height: 300,
child: Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes!
: null,
),
),
);
},
errorBuilder: (_, __, ___) => Image.asset(
AppImages.withoutPicture,
height: 300,
fit: BoxFit.fitHeight,
),
)
thank you for your comment thats help to resolve the situation that how to know if the image is loaded or not hope that help
I use a StatefulWidget
need a editing depend on your AffichScreen
situation :
-i have an url that i enter
-if url is correct affich the image if not affich an icon
-if empty affich a Text()
-precacheImage check if the url is correct if not give an error and change _loadingimage(bool) to false to affich the icon eror
-i use a NetworkImage to check with precacheImage and before affich use a Image.network
bool _loadingimage;
ImageProvider _image;
Image _imagescreen;
#override
void initState() {
_loadingimage = true;
_imageUrlfocusNode.addListener(_updateImageUrl);
super.initState();
}
#override
void dispose() {
_imageUrlfocusNode.removeListener(_updateImageUrl);
_quantityfocusNode.dispose();
_imageUrlConroller.dispose();
_imageUrlfocusNode.dispose();
super.dispose();
}
void _updateImageUrl() {
setState(() {
_image = NetworkImage(_imageUrlConroller.text);
});
if (!_imageUrlfocusNode.hasFocus) {
if (_imageUrlConroller.text.isNotEmpty) {
setState(() {
loadimage();
});
}
}
}
void loadimage() {
_loadingimage = true;
precacheImage(_image, context, onError: (e, stackTrace) {
// log.fine('Image ${widget.url} failed to load with error $e.');
print('error $e');
setState(() {
_loadingimage = false;
print(_loadingimage);
});
});
if (_loadingimage == true) {
_imagescreen = Image.network(
_imageUrlConroller.text,
fit: BoxFit.fill,
);
}
}
Container(
width: 100,
height: 100,
margin: EdgeInsets.only(top: 13, right: 11),
decoration: BoxDecoration(
border: Border.all(
width: 1,
color: Colors.grey,
),
),
child:_imageUrlConroller.text.isEmpty
? Text('enter an url')
: !_loadingimage
? Container(
child: Icon(Icons.add_a_photo),
)
: Container(
child: _imagescreen,
),
),

Resources