values are null after calling network data - flutter

I am beginner in Flutter, I tried to call network data, but I used a parameter that comes from shared preferences in my function that calls the api data, and I put my function in initState but after I execute I find that the data are null, while there is data that came from internet call,
I am confused about the reason that made my data null, I mean here clubName, and points and fixture etc ...
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:footyappp/Fantazyy/club_json.dart';
import 'package:footyappp/Fantazyy/club_edit.dart';
import 'package:footyappp/Fantazyy/player_update_view.dart';
import 'package:footyappp/Fantazyy/styles.dart';
import 'package:footyappp/Fantazyy/player%20copy.dart';
import 'package:footyappp/Fantazyy/players_creation_details_view.dart';
import 'package:footyappp/Fantazyy/team_display_view.dart';
import 'package:footyappp/Key/Key.dart';
import 'package:http/http.dart';
import 'package:shared_preferences/shared_preferences.dart';
class TeamDisplayView extends StatefulWidget {
List<Playerr> selectedPlayers;
TeamDisplayView({
Key key,
players,
selectedPlayers,
}) : selectedPlayers = (selectedPlayers == null) ? new List<Playerr>.generate(16, (int index) => null) : selectedPlayers;
#override
_TeamDisplayViewState createState() => _TeamDisplayViewState();
}
class _TeamDisplayViewState extends State<TeamDisplayView> {
getClubId() async{
SharedPreferences prefs = await SharedPreferences.getInstance();
int clubid= prefs.getInt("clubID");
print(clubid);
makePostRequest(clubid);
}
Future<void> makePostRequest(int clubid) async {
// set up POST request arguments
String url = '${ApiKey.url}/api/questions/getclub';
Map<String, String> headers = {"Content-type": "application/json"};
String json = '{"clubid": "' + clubid.toString() + '}';
Response response = await post(url, headers: headers, body: json);
String res = response.body;
Map parsed = jsonDecode(res);
ClubEdit club = ClubEdit.fromJson(parsed);
setState((){
clubName=club.data.name;
budget=club.data.price;
points=club.data.points;
fixture=club.data.fixture;
});
print(clubName);
print(budget);
print(points);
print(fixture);
if((res != "Invalid email")||(res != "Invalid password")){
Fluttertoast.showToast(
msg: "login success",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.green,
textColor: Colors.white,
fontSize: 16.0
);
}
else{
Fluttertoast.showToast(
msg: "Login failed",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0
);
}
}
updateRequest(int userid, String email, int points,String fixtures,String password,String name, double price, List<Playerr> players) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
email=prefs.getString("userEmail");
password=prefs.getString("userPassword");
setState((){
userid=prefs.getInt("userID");
});
// set up POST request arguments
final url = Uri.parse('${ApiKey.url}/api/questions/updateQuestion');
Map<String, String> headers = {"Content-type": "application/json"};
List<Player> pl = [];
for(var item in players){
pl.add(Player(id:item.playerID,firstname:item.firstName.toString(),lastname:item.lastName.toString(),position:item.position.toString(),price:item.price,appearences:item.appearances,goals:item.goals,assists:item.assists,cleansheets:item.cleanSheets,redcards:item.redCards,yellowcards:item.yellowCards,image:item.image));
}
ClubJson club = ClubJson(userid: userid, email: email, password: password, name: name, price: price, players: pl );
var json = jsonEncode(club.toJson());
print(club.name);
print(club.name);
print(club.price);
for(var item in club.players){
print(item.price);
}
// make POST request
Response response = await post(url, headers: headers, body: json);
// check the status code for the result
int statusCode = response.statusCode;
// this API passes back the id of the new item added to the body
String body = response.body;
// var res = jsonDecode(response.body);
// if(res == "success"){
//
//Navigator.push(context, MaterialPageRoute(builder: (context)=>BodyFantasy(),),);
return response;
}
int clubid;
String clubName;
double budget;
int points;
String fixture;
double _budget = 150.0;
String _teamName = "";
Widget _saveChanges = Text("Press to save changes");
int userid;
String email;
String password;
#override
void initState() {
Map<int,int> teamCount = new Map<int, int>();
for (Playerr player in widget.selectedPlayers) {
if (player != null) {
_budget -= player.price;
}
}
super.initState();
this.getClubId();
}
emptyPlayer(int index) {
Playerr player = widget.selectedPlayers[index];
Widget playerView;
if (player == null) {
playerView = Image.asset("Assets/shirt_blank.png", fit: BoxFit.fitHeight,);
} else {
playerView = Column(
children: <Widget>[
Expanded(
child: Image.asset(player.image, fit: BoxFit.fitHeight,),
),
Container(
color: Colors.black,
child: Text(player.firstName.substring(0,1) + ". " + player.lastName, textAlign: TextAlign.center, softWrap: false, overflow: TextOverflow.fade,),
),
Container(
color: Colors.black,
child: Text("£${player.price}m", textAlign: TextAlign.center),
),
],
);
}
return Expanded(
child: InkWell(
onTap: () => Navigator.pushReplacement(context, MaterialPageRoute(builder: (BuildContext context) {return PlayerUpdateView(selectedPlayers: widget.selectedPlayers, playerIndex: index,);})),
child: Padding(padding: EdgeInsets.only(left: 3.0, right: 3.0), child:playerView,)
),
);
}
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async => false,
child: Scaffold(
appBar: AppBar(title: Text("Your team"),),
body: Stack(
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
child: Stack(
children: <Widget>[
Positioned.fill(
child: Image.asset("Assets/pitch.jpg", fit: BoxFit.fitWidth, alignment: Alignment.topLeft,)
)
]
)
),
],
),
Column( //players
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
flex: 1,
child: Container()
),
Expanded(
flex: 6,
child: Padding(
padding: EdgeInsets.only(left: 40.0, right: 40.0), child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: List.generate(2, (index) => emptyPlayer(index)),
),
)
),
Expanded(
flex: 1,
child: Container()
),
Expanded(
flex: 6,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: List.generate(5, (index) => emptyPlayer(index+2)),
)
),
Expanded(
flex: 1,
child: Container()
),
Expanded(
flex: 6,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: List.generate(5, (index) => emptyPlayer(index+7)),
)
),
Expanded(
flex: 1,
child: Container()
),
Expanded(
flex: 6,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: List.generate(4, (index) => emptyPlayer(index+12)),
)
),
Expanded(
flex: 1,
child: Container()
),
Container(
color: Styles.colorAccentDark,
padding: EdgeInsets.only(left: 8.0, right: 8.0),
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 4.0, bottom: 4.0),
child: Row(
children: <Widget>[
Expanded(
child: Text("Team Name", style: Styles.budgetLabel,),
),
Text("${clubName}", style: Styles.budgetLabel,)
],
),
),
Padding(
padding: EdgeInsets.only(top: 4.0, bottom: 4.0),
child: Row(
children: <Widget>[
Expanded(
child: Text("Fixture", style: Styles.budgetLabel,),
),
Text("${fixture}", style: Styles.budgetLabel,)
],
),
),
Padding(
padding: EdgeInsets.only(top: 4.0, bottom: 4.0),
child: Row(
children: <Widget>[
Expanded(
child: Text("Remaining Budget", style: Styles.budgetLabel,),
),
Text("£${budget}m", style: Styles.budgetLabel,)
],
),
),
Padding(
padding: EdgeInsets.only(top: 4.0, bottom: 4.0),
child: Row(
children: <Widget>[
Expanded(
child: Text("Points", style: Styles.budgetLabel,),
),
Text("${points}", style: Styles.budgetLabel,)
],
),
),
/* Padding(
padding: EdgeInsets.only(top: 4.0, bottom: 4.0),
child: Column(
children: <Widget>[
Expanded(
child: Text("Next Fixture", style: Styles.budgetLabel,),
),
Text("yyy", style: Styles.budgetLabel,)
],
),
),*/
],
),
)
,
new MaterialButton(
height: 50.0,
minWidth: double.infinity,
color: Styles.colorButton,
splashColor: Colors.teal,
textColor: Colors.white,
child: _saveChanges,
onPressed: () {
if (widget.selectedPlayers.length ==16){
updateRequest(userid, "dhya#hotmail.com", 20, "22", "password", "name", 25.0, widget.selectedPlayers) ;
}
}
),
],
),
],
)
)
);
}
}

You need to call setState when you change your variables which you are trying to show in UI.
I believe you are trying to show one or more of these variables in your UI so wrap it in setState.
setState((){
clubName=club.data.name;
budget=club.data.price;
points=club.data.points;
fixture=club.data.fixture;
});
The reason being when you initialize your variables they are by default null.
And by the time makePostRequest() executes the build method is run and widgets are drawn on the screen with null data. but once the makePostRequest completes execution and you have your variables with your updated data you need to call setState this means when you call setState the build method will be called again to rebuild the widgets with the updated data.
I highly recommend you to play with the flutter counter app in the dartpad to understand how setState works.

Related

How can I create a multi-level dependent list (dropdown) using CupertinoPicker in flutter?

Based on the serviceAreas list, I want to return the corresponding bus stops. For Instance, If a user selects Oyo in the serviceArea list, the list to return in the second cupertinoPicker should be the ibadanBusstop, and if a user selects Lagos in the first list, the return should be lagosBusstop list.
I'm open to other approaches to make this work but I don't want to use a dropdown.
class _BookingPageState extends State<BookingPage> {
FixedExtentScrollController scrollController = FixedExtentScrollController();
final List<String> ibadanBusstop = [
'Lead City Bus Stop',
'Olorunsogo Bus Stop',
'Challenge Bus Stop',
'Mokola Bus Stop',
];
final List<String> lagosBusstop = [
'Jibowu Bus Stop',
'Obalende Bus Stop',
];
final List<String> serviceAreas = [
'Lagos',
'Oyo',
];
int ibadanIndex = 0;
int lagosIndex = 0;
int serviceAreaIndex = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: FraserDimensions.xFlexHeight(context, 24),
),
GestureDetector(
onTap: (() {
scrollController.dispose();
scrollController =
FixedExtentScrollController(initialItem: serviceAreaIndex);
showCupertinoModalPopup(
context: context,
builder: (context) => CupertinoActionSheet(
actions: [
SizedBox(
height: FraserDimensions.xFlexHeight(context, 3),
child: CupertinoPicker(
scrollController: scrollController,
itemExtent: 64,
onSelectedItemChanged: (index) {
setState(() {
this.serviceAreaIndex = index;
});
final item = serviceAreas[index];
print(item);
},
children: serviceAreas
.map((e) => Center(
child: Text(
e,
style: FraserTextStyle.textBlack24,
),
))
.toList()),
)
],
),
);
}),
child: Container(
width: FraserDimensions.xFlexWidth(context, 1),
height: FraserDimensions.xFlexHeight(context, 18),
decoration: BoxDecoration(
color: FraserColors.line,
borderRadius: const BorderRadius.all(
Radius.circular(24),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 24.0),
child: Text(
serviceAreas[serviceAreaIndex],
style: FraserTextStyle.textGrey16,
),
),
),
Padding(
padding: const EdgeInsets.only(right: 16.0),
child: Icon(
Icons.arrow_drop_down_outlined,
color: FraserColors.primaryBlack,
size: 22,
),
),
],
),
),
),
SizedBox(
height: FraserDimensions.xFlexHeight(context, 64),
),
GestureDetector(
onTap: (() {
scrollController.dispose();
scrollController =
FixedExtentScrollController(initialItem: ibadanIndex);
showCupertinoModalPopup(
context: context,
builder: (context) => CupertinoActionSheet(
actions: [
SizedBox(
height: FraserDimensions.xFlexHeight(context, 3),
child: CupertinoPicker(
scrollController: scrollController,
itemExtent: 64,
onSelectedItemChanged: (index) {
setState(() {
this.ibadanIndex = index;
});
final item = ibadanBusstop[index];
print(item);
},
children: ibadanBusstop
.map((e) => Center(
child: Text(
e,
style: FraserTextStyle.textBlack24,
),
))
.toList()),
)
],
),
);
}),
child: Container(
width: FraserDimensions.xFlexWidth(context, 1),
height: FraserDimensions.xFlexHeight(context, 18),
decoration: BoxDecoration(
color: FraserColors.line,
borderRadius: const BorderRadius.all(
Radius.circular(24),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 24.0),
child: Text(
ibadanBusstop[ibadanIndex],
style: FraserTextStyle.textGrey16,
),
),
),
Padding(
padding: const EdgeInsets.only(right: 16.0),
child: Icon(
Icons.arrow_drop_down_outlined,
color: FraserColors.primaryBlack,
size: 22,
),
),
],
),
),
),
],
),
),
);
}
Because I don't have the BookingPage I can't render to check the result.
But I think you should put some conditions where the ibadanBusstop list and lagosBusstop list is being used. So based on the position of the serviceAreaIndex you make some decision. So say the we are using busStopList Eg. busStopList = serviceAreaIndex == 0 ? ibadanBusstop : lagosBusstop;.
With this the logic of deciding the kind of list is taken care of by the condition.

Images don't displayed on screen

I have modified my code. I thought I could achieve what I am willing to do but I am still having an issue. The first image is fine, but when I am adding more images, they don't display to the screen. The idea is to allow the user to click on a button to select one or several images. Then, he can tap on a second button and add one pfd file, it is like adding attachment in email.Then, if the user wants he can tap on the first button and add an other image. The list of all the documents should be displayed on the screen. I though that maybe a set State is missing somewhere. Here is the code. I do not understand where is my mistake. Thank you in advance.
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
List<PlatformFile>? _paths;
List<String> filesGB =[];
bool _loadingPath = false;
String fileExtension='';
String _fileName='';
// To access the pictures
void _openPictureFileExplorer() async {
setState(() => _loadingPath = true);
try {
_paths = (await FilePicker.platform.pickFiles(
type: FileType.media,
allowMultiple: true,
))?.files;
if (_paths != null) {
_paths!.forEach((element) {
filesGB.add(element.path.toString());
print(filesGB);
print(filesGB.length);
});
setState(() {
});
}
} on PlatformException catch (e) {
print("Unsupported operation" + e.toString());
} catch (ex) {
print('$ex');
}
if (!mounted) return;
setState(() {
_loadingPath = false;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: const Text('File Picker app'),
),
body: Center(
child: Padding(
padding: const EdgeInsets.only(left: 10.0, right: 10.0),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 20.0),
//#############
//Display card with button to select type of document
child: Card(
child:
Container(
// color: Colors.red,
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//Attachement
FlatButton(
onPressed: () {},
child:
InkWell(
child: Container(
// color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment
.center,
children: [
Icon(Icons.attach_file),
Text('Attachment'),
],
)
),
onTap: () async {
fileExtension = 'pdf';
_openDocumentFileExplorer();
},
),
),
//Photo
FlatButton(
onPressed: () {},
child:
InkWell(
child: Container(
// color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment
.center,
children: [
Icon(Icons.add_a_photo_rounded),
Text('Photo'),
],
)
),
onTap: () {
fileExtension = 'jpeg';
_openPictureFileExplorer();
},
),
),
],
),
)),
),
Builder(
builder: (BuildContext context) => _loadingPath ?
Padding(
padding: const EdgeInsets.only(bottom: 10.0),
child:const CircularProgressIndicator(),
)
: filesGB.isNotEmpty ?
Column(
children: listOfCards(filesGB),
)
:Text('Nothing to display'),
),
]),)))));
}
}
List<Widget> listOfCards(List<String> item){
List<Widget> list = <Widget>[];
ListView.builder(
itemCount: filesGB.length,
itemBuilder: (BuildContext ctxt, int index) {
return new Container(
height: 114,
child: GestureDetector(
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
elevation: 10,
child: ClipPath(
clipper: ShapeBorderClipper(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15))),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: 113, width: 113,
child: Image.file(File(item[i].toString()),
fit: BoxFit.fill,
width: double.infinity,),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text(item[i]
.split('/')
.last),
),
),
],
),
),),
),
);
});
return list;
}
first of all, you don't need to use for loop for building your pictures list
just use ListView.builder
but about your problem, I think it happens because you set selected pictures in a row
then return that row as a child of your column
so your pictures align horizontally and column just show widgets in vertical aligns
in other words, your column just have one child, and its a Row
so column just show pictures as possible then you just see the first picture.
for solving this problem you should return a list of widgets in the listOfCards function
just do these simple changes and I hope your problem solved
change your function return parameter to List<Widget>
Widget listOfCards(List<String> item) {
to
List<Widget> listOfCards(List<String> item) {
then just return your list
return list;
and your column should look like this
Column(
children: listOfCards(filesGB),
)
I have find a working solution. It does what I was expecting with image. I still have a problem when I delete a record, the card is not removed. I do not find where I should use the setState. I will continue to investigate.
body: Center(
child: Padding(
padding: const EdgeInsets.only(left: 10.0, right: 10.0),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 20.0),
//#############
//Display card with button to select type of document
child: Card(
child:
Container(
// color: Colors.red,
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//Attachement
FlatButton(
onPressed: () {},
child:
InkWell(
child: Container(
// color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment
.center,
children: [
Icon(Icons.attach_file),
Text('Attachment'),
],
)
),
onTap: () async {
fileExtension = 'pdf';
_openDocumentFileExplorer();
},
),
),
//Photo
FlatButton(
onPressed: () {},
child:
InkWell(
child: Container(
// color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment
.center,
children: [
Icon(Icons.add_a_photo_rounded),
Text('Photo'),
],
)
),
onTap: () {
fileExtension = 'jpeg';
_openPictureFileExplorer();
},
),
),
],
),
)),
),
Builder(
builder: (BuildContext context) => _loadingPath ?
Padding(
padding: const EdgeInsets.only(bottom: 10.0),
child:const CircularProgressIndicator(),
)
: filesGB.isNotEmpty ?
Column(
children: getList(),//[listOfCards(filesGB)],
)
:Text('Nothing to display'),
),
]),)))));
}
}
List<Widget> getList() {
List<Widget> childs = [];
for (var i = 0; i < filesGB.length; i++) {
childs.add(
GestureDetector(
onTap: (){
print ("Pressed");
},
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
elevation: 10,
child: ClipPath(
clipper: ShapeBorderClipper(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15))),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: 113,width: 113,
child: fileExtension == 'pdf'?
Image.asset('assets/logo_pdf.png',
// fit: BoxFit.fill,
// width: double.infinity,
):
Image.file(File(filesGB[i].toString()),
fit: BoxFit.fill,
width: double.infinity,),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text(filesGB[i].toString().split('/').last,//_nameOfFile,//name,
style: TextStyle(fontWeight: FontWeight.bold),),
),
),
Padding(
padding: const EdgeInsets.only(right:25.0),
child: IconButton(onPressed: (){
//delete a record and the card displaying this record
// Delete the selected image
// This function is called when a trash icon is pressed
if (filesGB.length > 1) {
filesGB.removeAt(i);
print(filesGB);
setState(() {});
}
},
icon:Icon (Icons.delete, color: Colors.red,),),
)
],
),
),
//subtitle: Text(path),
),
));}
return childs;
}

Widget is taking maximum space in Flutter

I have some widgets (message bubbles ) inside a StreamBuilder, however this message bubbles are taking the maximum space possible when they should adapt to the size of the text inside.
This is the code of the main screen:
#override
Widget build(BuildContext context) {
return SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('messages').snapshots(),
builder: (context, snapshot){
List<Widget> messagesWidgets = [];
if (snapshot.hasData){
final messages = snapshot.data.docs;
for (var message in messages){
final messageText = message.data()['text'];
final messageSender = message.data()['sender'];
final messageWidget = MessageBubble(
text: messageText,
sender: messageSender,
);
messagesWidgets.add(messageWidget);
}
}
return Expanded(
child: ListView(
//padding: EdgeInsets.symmetric(horizontal: 0.0, vertical: 20.0),
children: messagesWidgets,
),
);
},
),
Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
flex: 6,
child: TextInput(
textAlign: TextAlign.left,
onChanged: (value){
messageText = value;
},
hintText: 'Type a message',
),
),
Expanded(
flex: 1,
child: Button(
child: Icon(Icons.send, color: background,),
function: (){
if(messageText.trim() == '') return;
_firestore.collection('messages').add({
'text': messageText,
'sender': Usr.email,
});
setState(() {
messageText = '';
});
},
tag: 'hey2d2',
),
),
],
),
),
],
),
);
And this is the code of the message bubbles:
#override
Widget build(BuildContext context) {
return Container(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
child: Material(
elevation: 10.0,
borderRadius: BorderRadius.circular(30.0),
color: Colors.white,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'$sender',
style: TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
color: background,
),
),
Text(
'$text',
style: TextStyle(
fontSize: 15.0,
color: background,
),
),
],
),
),
),
),
);
Here there is a screenshot of what I mean:
This happens because the ListView widget automatically forces its children to take up all the available width. You can bypass this behaviour by wrapping the message bubble container with the Align widget. See below:
#override
Widget build(BuildContext context) {
return Align(
// Set the align's alignment to centerLeft.
alignment: Alignment.centerLeft,
child: Container(
...
),
);
}

Flutter item not updating in widget when delete need to come back to see changes

I have a simple cart page I am showing products on the cart page. The issue is when I am deleting an item it's deleting but in the widget, it's not deleting I need to go back and come again to show the changes. I try to rise setState also but not working.
My code
class _CartPageState extends State<CartPage> {
num amount = 0;
bool checkLogin = false;
void navigateToAddressPage() {
Get.to(AddressPage());
}
check() async {
final storage = new FlutterSecureStorage();
String imi = await storage.read(key: "imei");
print(imi);
if (imi == "loginhuavaha") {
setState(() {
this._query();
checkLogin = true;
});
}
}
#override
void initState() {
setState(() {
this.check();
});
}
List<Widget> textWidgetList = List<Widget>();
void _query() async {
print('cart');
final dbHelper = DatabaseHelper.instance;
final allRows = await dbHelper.queryAllRows();
allRows.forEach((row) {
amount += double.parse(row['price']);
print(amount);
print(row);
});
for (int i = 0; i < allRows.length; i++) {
textWidgetList.add(Card(
elevation: 5.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0),
),
margin: EdgeInsets.symmetric(vertical: 8.0),
child: Container(
width: double.infinity,
height: 120.0,
padding: EdgeInsets.all(12.0),
child: Row(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(12.0),
child: Image.network(allRows[i]['image'],
width: 100, height: 100)),
SizedBox(width: 12.0),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Text(
allRows[i]['title'],
textAlign: TextAlign.start,
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
),
SizedBox(width: 5.0),
Row(
children: [
GestureDetector(
onTap: () async {
print('delete');
final id = await dbHelper.queryRowCount();
print(id);
final rowsDeleted = await dbHelper.delete(
id, allRows[i]['id']);
print('deleted $rowsDeleted row(s): row $id');
setState(() {
});
},
child: Icon(
FlutterIcons.delete_outline_mco,
),
)
],
)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
allRows[i]['price'],
),
),
// Counter(),
],
),
],
),
),
)
],
),
),
));
}
setState(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: buildAppBar(context),
body: checkLogin
? Container(
child: SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 18.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Column(children: textWidgetList),
],
),
),
)
: Center(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(child: Text('Your are not login')),
SizedBox(height: 10),
SizedBox(
width: 85.0,
height: 50.0,
child: RaisedButton(
color: Theme.of(context).primaryColor,
elevation: 0.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Text(
'LOGIN',
style: Theme.of(context).textTheme.button,
).tr(),
onPressed: () {
Get.offAll(SignInPage());
},
),
),
])),
),
);
}
You can see I have added a comment in my code I delete the product and it actually deleted from database but state isn't changing of widget -_-
I think what you need here is the Provider package. Provider makes state management easier a lot. Just define a model class that extends ChangeNotifier and then wrap your widgets with ChangeNotifierProvider<Model_class_name>. To access the fields Use Provider.of(context).var or Provider.of(context).function
First of all you need to put textWidgetList in the setState since you manipulate those Widgets I guess. Secondly you have to put a key to those Widgets due to how Flutter handles elements in a list on the UI.Have a look at this page https://medium.com/flutter/keys-what-are-they-good-for-13cb51742e7d
Its Simple Man
Once the item is removed
use setState((){})
setState(() {
//Inside setState Clear the allrows list
allrows.clear();
//Then get the allrows again so that the deleted data will not be shown
allRows = await dbHelper.queryAllRows();
});
setState rebuilds your widgets

Getting error -- type 'SocketException' is not a subtype of type 'widget' in flutter

My App is working properly on laptops means in the simulator but not on android phone. This error started when I have added a JSON connection. please help me in solving it.
Android Screenshot (it's not working in android)
IOS working Screenshot (it's working in ios)
Someone told me to add below code
static const Map<String, String> header = {
'Content-type': 'application/json',
'Accept': 'application/json',
};
tried this but still no luck.
import 'package:flutter/material.dart';
import 'package:xxxxxxxx/product_page.dart';
import 'homepage_banner.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'categoryJson.dart';
import 'mCategory.dart';
import 'featuredItemJSON.dart';
class HomeScreenBanner extends StatelessWidget {
static const Map<String, String> header = {
'Content-type': 'application/json',
'Accept': 'application/json',
};
Future<List<CategoryAPI>> fetchPosts() async {
http.Response response = await http
.get('http://api-url-here');
var responseJson = json.decode(response.body);
return (responseJson as List).map((p) => CategoryAPI.fromJson(p)).toList();
}
Future<List<MiddleCategoryAPI>> mfetchPosts() async {
http.Response response = await http
.get('http://api-url-here');
var mresponseJson = json.decode(response.body);
return (mresponseJson as List).map((p) => MiddleCategoryAPI.fromJson(p)).toList();
}
Future<List<FeaturedItemAPI>> ffetchPosts() async {
http.Response response = await http
.get('http://api-url-here');
var fresponseJson = json.decode(response.body);
return (fresponseJson as List).map((p) => FeaturedItemAPI.fromJson(p)).toList();
}
#override
void initState() async {
fetchPosts();
mfetchPosts();
ffetchPosts();
}
Build Method as requested:
final scrollingofferbanner = HomePageBanner();
#override
Widget build(BuildContext context) {
return Container(
child: new ListView(
children: <Widget>[
Container(
height: 139.0,
margin: EdgeInsets.only(left: 0, right: 0, top: 5, bottom: 0),
padding: EdgeInsets.only(top: 0),
alignment: Alignment.center,
color: Color(0xfffefeff),
child: new ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
Container(
child: new FutureBuilder<List<CategoryAPI>>(
future: fetchPosts(),
builder: (context, snapshot) {
if (snapshot.hasData){
List<CategoryAPI> posts = snapshot.data;
return new Row(
children: posts.map((post) => new Column(
children: <Widget>[
//category circle starts
Padding(
padding: const EdgeInsets.all(9.0),
child: new GestureDetector(
onTap: () {
// Change the color of the container beneath
Navigator.of(context).push(
new MaterialPageRoute(
builder: (context) => new ProductPage(
//producttitle: post.title,
)
)
);
},
child: Column(
children: <Widget>[
Container(
width: 60.0,
height: 60.0,
child: Column(
children: <Widget>[
CircleAvatar(
radius: 30.0,
backgroundImage:
NetworkImage(post.productimg),
backgroundColor: Colors.transparent,
),
],
),
),
Container(
width: 100.0,
margin: EdgeInsets.only(
left: 0, right: 0, top: 13, bottom: 1),
child: Column(
children: <Widget>[
Container(
child: Text(post.title,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 13.0,
fontFamily: 'avenirblack',
color: Color(0xff535353),
)),
)
],
),
),
],
),
),
),
//category circle ends
],
)).toList()
);
}
else if(snapshot.hasError)
{
return snapshot.error;
}
return new Center(
child: new Column(
children: <Widget>[
new Padding(padding: new EdgeInsets.all(50.0)),
new CircularProgressIndicator(),
],
),
);
},
),
),
],
),
),
//top category menu starts
//top category menu ends
scrollingofferbanner,
//middle category menu starts
new Container(
height: 188.00,
margin: EdgeInsets.only(left: 0, right: 0, top: 5, bottom: 0),
padding: EdgeInsets.only(top: 0),
alignment: Alignment.center,
color: Color(0xfffefeff),
child: new ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
Container(
child: new FutureBuilder<List<MiddleCategoryAPI>>(
future: mfetchPosts(),
builder: (context, snapshot) {
if (snapshot.hasData){
List<MiddleCategoryAPI> posts = snapshot.data;
return new Row(
children: posts.map((post) => new Column(
children: <Widget>[
//category circle starts
Padding(
padding: const EdgeInsets.all(9.0),
child: Container(
width: 128.0,
child: Center(
child: Column(
children: <Widget>[
Container(
child: FadeInImage.assetNetwork(
placeholder: 'assets/loading.gif',
image: post.imagen,
),
),
//new Image.network(post.imagen),
Container(
margin: EdgeInsets.only(
left: 0, right: 0, top: 5, bottom: 1),
child: Text(post.title,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 15.0,
fontFamily: 'avenirblack',
color: Color(0xff535353))))
],
),
),
),
),
//category circle ends
],
)).toList()
);
}
else if(snapshot.hasError)
{
return snapshot.error;
}
return new Center(
child: new Column(
children: <Widget>[
new Padding(padding: new EdgeInsets.all(50.0)),
new CircularProgressIndicator(),
],
),
);
},
),
),
],
),
)
//middle category menu ends
,
//featured product list starts
new Container(
height: 300.0,
color: Color(0xffF1ECE7),
child: new Column(
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(20, 15, 0, 5),
child: new Row(
children: <Widget>[
Container(
child: Text('FEATURED ITEMS',
style: TextStyle(
color: Color(0xffE18C21), fontSize: 20.0)),
),
],
),
),
Container(
height: 250.00,
margin:
EdgeInsets.only(left: 10, right: 0, top: 0, bottom: 0),
padding: EdgeInsets.only(top: 0),
alignment: Alignment.center,
child: new ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
//category circle starts
Container(
child: new FutureBuilder<List<FeaturedItemAPI>>(
future: ffetchPosts(),
builder: (context, snapshot) {
if (snapshot.hasData){
List<FeaturedItemAPI> posts = snapshot.data;
return new Row(
children: posts.map((post) => new Column(
children: <Widget>[
//category circle starts
Padding(
padding: const EdgeInsets.all(9.0),
child: Container(
width: 180.0,
child: Center(
child: new GestureDetector(
onTap: () {
// Change the color of the container beneath
Navigator.of(context).push(
new MaterialPageRoute(
builder: (context) => new ProductPage(
ProductTitle: post.name,
ProductPrice: post.productprice,
ProductCode: post.productcode,
ProductDescription: post.productdescription,
ProductImage: post.productimg,
ProductAltTag: post.alttags,
Productid: post.id,
)
)
);
},
child: new Column(
children: <Widget>[
Container(
child: FadeInImage.assetNetwork(
placeholder: 'assets/loading.gif',
image: post.productimg,
),
),
Container(
margin: EdgeInsets.only(top: 10),
child: new Text(post.name),
)
// Image.network(
// post.productimg, // On click should redirect to an URL
// )
],
),
),
),
),
),
//category circle ends
],
)).toList()
);
}
else if(snapshot.hasError)
{
return snapshot.error;
}
return new Center(
child: new Column(
children: <Widget>[
new Padding(padding: new EdgeInsets.all(50.0)),
new CircularProgressIndicator(),
],
),
);
},
),
)
//category circle ends
],
),
)
],
),
),
//featured product list ends
],
),
);
}
}
Actually, I don't why this problem arises but somewhere I had read and found this solution :
you need to add
In the AndroidManifest.xml file located at android/app/src/main you need to add this permission in tag.
<uses-permission android:name="android.permission.INTERNET"/>
Somewhere there's an exception in one of the fetch methods (perhaps 1+). So, as a result, the output of HomeScreenBanner is an exception rather than a widget.
There's no widget build method in the code. However, since you say it was working on the simulator, I assume you haven't posted the build method here.
Try to add a try catch block and check which fetch method(s) have exception. A set of print statements might help as well.