Flutter table_calendar load today - flutter

Im using table_calendar package in my project, but ive faced two problems so far :
The calendar doesnt load todays events below the calendar, i would love to hear some ideas how to get this one done.
Even if i put (code below) in tables parameters, it doesnt allow to switch calendar modes.
code for swiching calendar modes for 2nd bullet point of my problems:
availableCalendarFormats: const {
CalendarFormat.month: '',
CalendarFormat.week: '',
},
Just in case, here is the whole code for page which has problems :
class Lecture_graph extends StatefulWidget {
Lecture_graph({Key key}) : super(key: key);
#override
State<Lecture_graph> createState() => myLectureGraph();
}
class myLectureGraph extends State<Lecture_graph>
with TickerProviderStateMixin {
List _selectedEvents;
DateTime _selectedDate = DateTime.now();
Map<DateTime, List<Lecture>> _events;
CalendarController _calendarController;
AnimationController _animationController;
List<Lecture> _lectures;
String coursecode = "";
bool isJoin, isBreaks = false;
bool isLoading = true;
final Map<DateTime, List> _holidays = {
// DateTime(2021, 1, 1): ['New Year\'s Day'],
// DateTime(2021, 2, 14): ['Valentine\'s Day'],
// DateTime(2021, 3, 8): ['Woman\'s Day'],
};
Future<Map<DateTime, List>> getLectures(DateTime _selectedDate) async {
print("getLectures started.");
setState(() {
isLoading = true;
});
Map<DateTime, List<Lecture>> mapFetch = {};
//get saved course
if (coursecode == "" || coursecode == null) {
coursecode = await _checkSavedCourse();
//debug
print('courscode recieved from sharedprefs');
}
//build request URL
var requestURL =
'https://lekcijas.va.lv/lekcijas_android/getMonthLectures.php?date=' +
DateFormat('yyyy-MM').format(_selectedDate) +
(isBreaks ? "&breaks" : "") +
(isJoin ? "&join" : "") +
"&program=" +
coursecode +
"&lang=" +
AppLocalizations.of(context).translate('request_language');
print("Lecture request url : $requestURL");
//wait for response
var response = await http.get(Uri.parse(requestURL));
var data = json.decode(response.body)["result"];
//clear array after each request
if (_lectures != null) _lectures.clear();
try {
//create lectures from json response
_lectures = List<Lecture>.from(data.map((x) => Lecture.fromJson(x)));
} on Exception catch (_) {
print("Error occured getting lectures");
}
_lectures.forEach((element) {
if (mapFetch[element.lecture_date] != null) {
mapFetch[element.lecture_date] += [element];
} else {
mapFetch[element.lecture_date] = [element];
}
});
setState(() {
isLoading = false;
});
print("getLectures finished.");
return mapFetch;
}
Future<void> _saveVales(String key, bool value) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
print("Sharedpref $key is set to $value now");
prefs.setBool(key, value);
}
Future<void> _checkSavedParameters() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
isBreaks = prefs.getBool('lectures_breaks') == null
? false
: prefs.getBool('lectures_breaks');
isJoin = prefs.getBool('lectures_join') == null
? false
: prefs.getBool('lectures_join');
}
Future<String> _checkSavedCourse() async {
//check saved parameters for lecture requests too
await _checkSavedParameters();
SharedPreferences prefs = await SharedPreferences.getInstance();
String _coursecode = prefs.getString('savedCourse');
if (_coursecode == "" || _coursecode == null) {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CourseSelectionPage()),
);
return null;
} else {
return _coursecode;
}
}
void _onDaySelected(DateTime day, List events) {
print('CALLBACK: _onDaySelected');
setState(() {
_selectedEvents = events;
});
}
#override
void initState() {
super.initState();
//enable portrait only mode
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
_selectedEvents = [];
_calendarController = CalendarController();
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 400),
);
_animationController.forward();
WidgetsBinding.instance.addPostFrameCallback((_) {
getLectures(_selectedDate).then((val) => setState(() {
_events = val;
}));
});
}
#override
void dispose() {
_calendarController.dispose();
//unlock orientation mode
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeRight,
DeviceOrientation.landscapeLeft,
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(coursecode +
" | " +
AppLocalizations.of(context).translate('lectures_title')),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.settings,
color: Colors.white,
),
onPressed: () {
showDialog(
context: context,
builder: (context) {
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
title: Text(
AppLocalizations.of(context).translate('settings')),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
CupertinoSwitch(
value: isJoin,
onChanged: (bool value) {
_saveVales('lectures_join', value);
isJoin = value;
WidgetsBinding.instance
.addPostFrameCallback((_) {
getLectures(_selectedDate)
.then((val) => setState(() {
_events = val;
}));
});
},
),
Text(AppLocalizations.of(context)
.translate('join_lectures'))
],
),
SizedBox(height: 10),
Row(
children: [
CupertinoSwitch(
value: isBreaks,
onChanged: (bool value) {
_saveVales('lectures_breaks', value);
isBreaks = value;
WidgetsBinding.instance
.addPostFrameCallback((_) {
getLectures(_selectedDate)
.then((val) => setState(() {
_events = val;
}));
});
},
),
Text(AppLocalizations.of(context)
.translate('show_breaks'))
],
),
SizedBox(height: 10),
SizedBox(
width: double.infinity,
child: OutlinedButton(
onPressed: () {
//close popup
Navigator.pop(context);
//close page
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
CourseSelectionPage()),
);
},
child: Text(
AppLocalizations.of(context)
.translate('select_course'),
style: TextStyle(color: Colors.lime),
)),
)
],
),
actions: <Widget>[
FlatButton(
onPressed: () => Navigator.pop(context),
child: Text(AppLocalizations.of(context)
.translate('close')),
),
],
);
},
);
},
);
},
)
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
isLoading
? Expanded(child: Center(child: CircularProgressIndicator()))
: _buildTableCalendarWithBuilders(),
const SizedBox(height: 2.0),
Expanded(child: _buildEventList()),
],
),
),
);
}
Widget _buildTableCalendarWithBuilders() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Card(
color: Colors.white,
margin: const EdgeInsets.all(8.0),
clipBehavior: Clip.antiAlias,
child: TableCalendar(
locale:
AppLocalizations.of(context).translate('request_language') ==
'lv'
? "lv_LV"
: "en_US",
initialSelectedDay: _selectedDate,
calendarController: _calendarController,
events: _events,
holidays: _holidays,
initialCalendarFormat: CalendarFormat.month,
formatAnimation: FormatAnimation.scale,
startingDayOfWeek: StartingDayOfWeek.monday,
availableGestures: AvailableGestures.all,
availableCalendarFormats: const {
CalendarFormat.month: '',
CalendarFormat.week: '',
},
calendarStyle: CalendarStyle(
outsideDaysVisible: false,
weekendStyle: TextStyle().copyWith(color: Colors.blue[800]),
holidayStyle: TextStyle().copyWith(color: Colors.blue[800]),
),
daysOfWeekStyle: DaysOfWeekStyle(
weekendStyle: TextStyle().copyWith(color: Colors.blue[600]),
),
headerStyle: HeaderStyle(
centerHeaderTitle: true,
formatButtonVisible: false,
),
builders: CalendarBuilders(
selectedDayBuilder: (context, date, _) {
return FadeTransition(
opacity:
Tween(begin: 0.0, end: 1.0).animate(_animationController),
child: Container(
margin: const EdgeInsets.all(4.0),
padding: const EdgeInsets.only(top: 5.0, left: 6.0),
color: Colors.deepOrange[300],
width: 100,
height: 100,
child: Text(
'${date.day}',
style: TextStyle().copyWith(fontSize: 16.0),
),
),
);
},
todayDayBuilder: (context, date, _) {
return Container(
margin: const EdgeInsets.all(4.0),
padding: const EdgeInsets.only(top: 5.0, left: 6.0),
color: Colors.amber[400],
width: 100,
height: 100,
child: Text(
'${date.day}',
style: TextStyle().copyWith(fontSize: 16.0),
),
);
},
markersBuilder: (context, date, events, holidays) {
final children = <Widget>[];
if (events.isNotEmpty) {
children.add(
Positioned(
right: 1,
bottom: 1,
child: _buildEventsMarker(date, events),
),
);
}
if (holidays.isNotEmpty) {
children.add(
Positioned(
right: -2,
top: -2,
child: _buildHolidaysMarker(),
),
);
}
return children;
},
),
onDaySelected: (date, events, holidays) {
_onDaySelected(date, events);
_animationController.forward(from: 0.0);
},
onVisibleDaysChanged: _onVisibleDaysChanged,
),
),
],
);
}
void _onVisibleDaysChanged(
DateTime first, DateTime last, CalendarFormat format) {
_selectedDate = first;
WidgetsBinding.instance.addPostFrameCallback((_) {
getLectures(_selectedDate).then((val) => setState(() {
_events = val;
}));
});
print('CALLBACK: _onVisibleDaysChanged');
}
Widget _buildEventsMarker(DateTime date, List events) {
return AnimatedContainer(
duration: const Duration(milliseconds: 300),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: _calendarController.isSelected(date)
? Colors.brown[500]
: _calendarController.isToday(date)
? Colors.brown[300]
: Colors.green[400],
),
width: 18.0,
height: 18.0,
child: Center(
child: Text(
'${events.length}',
style: TextStyle().copyWith(
color: Colors.white, fontSize: 12.0, fontWeight: FontWeight.w900),
),
),
);
}
Widget _buildHolidaysMarker() {
return Icon(
Icons.add_box,
size: 20.0,
color: Colors.blueGrey[800],
);
}
Widget _buildEventList() {
return ListView(
children: _selectedEvents.reversed
.map((lecture) => Container(
decoration: BoxDecoration(
border: Border.all(width: 0.1),
// borderRadius: BorderRadius.circular(2.0),
color: hexToColor(lecture.color),
),
margin:
const EdgeInsets.symmetric(horizontal: 6.0, vertical: 1.5),
child: ListTile(
title: Column(
children: [
Align(
alignment: Alignment.centerLeft,
child: Text(
lecture.start + " - " + lecture.end,
style: new TextStyle(
fontSize: 12.0,
color: Colors.black,
),
),
),
Align(
alignment: Alignment.centerLeft,
child: Text(lecture.lecture,
style: new TextStyle(
fontSize: 16.0,
color: Colors.black,
)),
),
],
),
onTap: () => displayDialog(lecture, context),
),
))
.toList(),
);
}
void displayDialog(Lecture selectedLecture, BuildContext ctx) {
//if selected lecture is a break
if (!selectedLecture.lecturer.isEmpty &&
!selectedLecture.classroom.isEmpty &&
!selectedLecture.programs.isEmpty) {
showDialog(
barrierDismissible: true,
context: ctx,
builder: (BuildContext context) => new AlertDialog(
title: new Text(AppLocalizations.of(context).translate('info_title')),
content: new Wrap(
runSpacing: 5,
children: [
Align(
alignment: Alignment.centerLeft,
child: Text(
AppLocalizations.of(context).translate('info_time') +
selectedLecture.start +
" - " +
selectedLecture.end),
),
Align(
alignment: Alignment.centerLeft,
child: Text(
AppLocalizations.of(context).translate('info_lecturer') +
selectedLecture.lecturer),
),
Align(
alignment: Alignment.centerLeft,
child: Text(
AppLocalizations.of(context).translate('info_classroom') +
selectedLecture.classroom),
),
Align(
alignment: Alignment.centerLeft,
child: Text(
AppLocalizations.of(context).translate('info_lecture') +
selectedLecture.lecture),
),
Align(
alignment: Alignment.centerLeft,
child: Text(
AppLocalizations.of(context).translate('info_date') +
DateFormat('yyyy-MM-dd')
.format(selectedLecture.lecture_date)
.toString()),
),
Align(
alignment: Alignment.centerLeft,
child: Text(
AppLocalizations.of(context).translate('info_programs') +
selectedLecture.programs),
),
],
),
actions: [
new TextButton(
child: Text(AppLocalizations.of(context).translate('close')),
onPressed: () => Navigator.pop(context, true),
),
],
),
);
}
}
}
In case someone wants to see JSON request results, here is the link for that.

So i got this fixed, adding this to TableCalendar() parameters:
(i called selectedEvents variable update once calendar finished building (because im showing CircularProgressIndicator instead of it while i recieve data from http request) )
onCalendarCreated: (d1, d2, cf){WidgetsBinding.instance
.addPostFrameCallback((_) => _onDaySelected(_selectedDate, _events[_selectedDate]));},
changed _onDaySelected method to:
(here i change selectedday variable to day recieved from calendar click and change state of selectedEvents, replacing them with total_events_map[key_which_is_selectedDay])
void _onDaySelected(DateTime day, List events) {
print('CALLBACK: _onDaySelected');
//dates are used with nulled time
_selectedDate = DateTime(day.year, day.month, day.day, 0, 0, 0);
setState(() {
_selectedEvents = _events[_selectedDate];
});
}
and changed _buildEventList() to this :
(so if selectedEvents are empty, it tells user so, if not, generates a list of items from selectedEvents)
Widget _buildEventList() {
if(_selectedEvents == null)
return ListView(
children: [
Card(
clipBehavior: Clip.antiAlias,
margin: const EdgeInsets.all(8.0),
child: ListTile(
title: Column(
children: [
Align(
alignment: Alignment.centerLeft,
child: Text(tr('nothing_planned'),
style: new TextStyle(
fontSize: 16.0,
color: Colors.black,
)),
),
],
),
),
),
],
);
else return ListView(
children: _selectedEvents.reversed
.map((lecture) => Container(
decoration: BoxDecoration(
border: Border.all(width: 0.1),
// borderRadius: BorderRadius.circular(2.0),
color: hexToColor(lecture.color),
),
margin:
const EdgeInsets.symmetric(horizontal: 6.0, vertical: 1.5),
child: ListTile(
title: Column(
children: [
Align(
alignment: Alignment.centerLeft,
child: Text(
lecture.start + " - " + lecture.end,
style: new TextStyle(
fontSize: 12.0,
color: Colors.black,
),
),
),
Align(
alignment: Alignment.centerLeft,
child: Text(lecture.lecture,
style: new TextStyle(
fontSize: 16.0,
color: Colors.black,
)),
),
],
),
onTap: () => displayDialog(lecture, context),
),
))
.toList(),
);
}

Related

how to shuffle a list in flutter

i am adding shuffle() function but the error is showing Another exception was thrown: type 'String' is not a subtype of type 'int' of 'index' is there any solution to put question in shuffle i don't know where to add this shuffle function there was not any error in this project the json files is added with this code
i am adding mydata.shuffle() in this code
#override
Widget build(BuildContext context) {
setasset();
return FutureBuilder(
future:
DefaultAssetBundle.of(context).loadString(assettoload, cache: false),
builder: (context, snapshot) {
List? mydata = json.decode(snapshot.data.toString());
if (mydata == null) {
return Scaffold(
body: Center(
child: Text(
"Loading",
),
),
);
} else {
return quizpage(mydata: mydata);
}
},
);
}
}
class quizpage extends StatefulWidget {
final List mydata;
quizpage({required this.mydata});
#override
_quizpageState createState() => _quizpageState();
}
class _quizpageState extends State<quizpage> {
_quizpageState();
Color colortoshow = Colors.indigoAccent;
int marks = 0;
int i = 1;
bool disableAnswer = false;
// extra varibale to iterate
int timer = 30;
String showtimer = "30";
Map<String, Color> btncolor = {
"a": Colors.indigo.shade900,
"b": Colors.indigo.shade900,
"c": Colors.indigo.shade900,
"d": Colors.indigo.shade900,
};
bool canceltimer = false;
#override
void initState() {
starttimer();
super.initState();
}
#override
void setState(fn) {
if (mounted) {
super.setState(fn);
}
}
void starttimer() async {
const onesec = Duration(seconds: 1);
Timer.periodic(onesec, (Timer t) {
setState(() {
if (timer < 1) {
t.cancel();
nextquestion();
} else if (canceltimer == true) {
t.cancel();
} else {
timer = timer - 1;
}
showtimer = timer.toString();
});
});
}
void nextquestion() {
canceltimer = false;
timer = 30;
setState(() {
if (i < 10) {
i++;
} else {
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => resultpage(marks: marks),
));
}
btncolor["a"] = Colors.indigo.shade900;
btncolor["b"] = Colors.indigo.shade900;
btncolor["c"] = Colors.indigo.shade900;
btncolor["d"] = Colors.indigo.shade900;
disableAnswer = false;
});
starttimer();
}
void checkanswer(String k) {
if (widget.mydata[2][i.toString()] == widget.mydata[1][i.toString()][k]) {
marks = marks + 5;
} else {}
setState(() {
btncolor[k] = colortoshow;
canceltimer = true;
disableAnswer = true;
});
Timer(Duration(seconds: 2), nextquestion);
}
Widget choicebutton(String k) {
return Padding(
padding: EdgeInsets.symmetric(
vertical: 10.0,
horizontal: 20.0,
),
child: SizedBox(
height: 60,
width: 400,
child: OutlinedButton(
onPressed: () => checkanswer(k),
child: Text(
widget.mydata[1][i.toString()][k] ?? "",
style: TextStyle(
fontWeight: FontWeight.w600,
color: Colors.black,
fontFamily: "Alike",
fontSize: 18.0,
),
maxLines: 1,
),
style: OutlinedButton.styleFrom(
side: BorderSide(width: 3.0, color: Colors.indigo.shade900),
backgroundColor: Colors.transparent,
shape: const StadiumBorder()),
),
),
);
}
#override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]);
return WillPopScope(
onWillPop: () async {
return await showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(
"Quizstar",
),
content: Text("You Can't Go Back At This Stage."),
actions: <Widget>[
ElevatedButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text(
'Ok',
),
)
],
));
},
child: SafeArea(
child: Scaffold(
body: Column(
children: <Widget>[
Expanded(
flex: 3,
child: Container(
width: 500,
height: 200,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(
"assets/canva4.png",
),
fit: BoxFit.cover,
),
),
padding: EdgeInsets.all(15.0),
alignment: Alignment.bottomLeft,
child: Text(
widget.mydata[0][i.toString()],
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w700,
fontSize: 20.0,
fontFamily: "Quando",
),
),
),
),
Divider(height: 10, color: Colors.black, thickness: 10),
Expanded(
flex: 6,
child: AbsorbPointer(
absorbing: disableAnswer,
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
choicebutton('a'),
choicebutton('b'),
choicebutton('c'),
choicebutton('d'),
],
),
),
),
),
Expanded(
flex: 1,
child: Container(
alignment: Alignment.topCenter,
child: Center(
child: Text(
showtimer,
style: TextStyle(
fontSize: 35.0,
fontWeight: FontWeight.w700,
fontFamily: 'Times New Roman',
),
),
),
),
),
],
),
),
),
);
}
}

Unhandled Exception: type 'Null' is not a subtype of type 'String' in type cast flutter

I'm trying to make a simple messaging application while using firebase and flutter, everything was working fine until I came to the message screen, but on this screen, I get the error that I will specify below. Do you know the solution for this?
Unhandled Exception: type 'Null' is not a subtype of type 'String' in type cast
I could not understand where I got the error, when I click on any user on the page where I listed the users, it gives this error directly.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_chat_bubble/bubble_type.dart';
import 'package:flutter_chat_bubble/chat_bubble.dart';
import 'package:flutter_chat_bubble/clippers/chat_bubble_clipper_6.dart';
import 'package:ourchat/pallete.dart';
import 'package:ourchat/shared/utils.dart';
class ChatDetailPage extends StatefulWidget {
final String user;
const ChatDetailPage({
Key? key,
required this.user,
}) : super(key: key);
#override
_ChatDetailPageState createState() => _ChatDetailPageState();
}
class _ChatDetailPageState extends State<ChatDetailPage> {
TextEditingController messageController = TextEditingController();
final currentUserId = FirebaseAuth.instance.currentUser?.uid;
CollectionReference chats = FirebaseFirestore.instance.collection('chats');
var chatDocId;
var userData = {};
bool isLoading = false;
#override
void initState() {
super.initState();
getData();
checkUser();
}
void checkUser() async {
await chats
.where('users', isEqualTo: {userData['uid']: null, currentUserId: null})
.limit(1)
.get()
.then(
(QuerySnapshot querySnapshot) async {
if (querySnapshot.docs.isNotEmpty) {
setState(() {
chatDocId = querySnapshot.docs.single.id;
});
print(chatDocId);
} else {
await chats.add({
'users': {currentUserId: null, widget.user: null},
'names': {
currentUserId: FirebaseAuth.instance.currentUser?.displayName,
userData['uid']: userData['username']
}
}).then((value) => {chatDocId = value});
}
},
)
.catchError((error) {});
}
getData() async {
setState(() {
isLoading = true;
});
try {
var userSnap = await FirebaseFirestore.instance
.collection('users')
.doc(widget.user)
.get();
userData = userSnap.data()!;
print(userData);
setState(() {});
} catch (e) {
showSnackBar(
context,
e.toString(),
);
}
setState(() {
isLoading = false;
});
}
void sendMessage(String msg) {
if (msg == '') return;
chats.doc(chatDocId).collection('messages').add({
'createdOn': FieldValue.serverTimestamp(),
'uid': currentUserId,
'friendName': userData['username'],
'msg': msg
}).then((value) {
messageController.text = '';
});
}
bool isSender(String friend) {
return friend == currentUserId;
}
Alignment getAlignment(friend) {
if (friend == currentUserId) {
return Alignment.topRight;
}
return Alignment.topLeft;
}
#override
Widget build(BuildContext context) {
return isLoading
? const Center(
child: CircularProgressIndicator(),
)
: StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('users')
.doc(chatDocId)
.collection('messages')
.orderBy('createdOn', descending: true)
.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(
child: Text("Bir şeyler yanlış gitti..."),
);
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(
color: kBlue,
),
);
}
if (snapshot.hasData) {
var data;
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
elevation: 0,
automaticallyImplyLeading: false,
backgroundColor: Colors.black,
flexibleSpace: SafeArea(
child: Container(
padding: EdgeInsets.only(right: 16),
child: Row(
children: <Widget>[
IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: ImageIcon(
AssetImage("assets/icons/backicon.png"),
color: Colors.white,
),
),
SizedBox(
width: 2,
),
CircleAvatar(
backgroundImage:
NetworkImage(userData['photoUrl'].toString()),
maxRadius: 20,
),
SizedBox(
width: 12,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
userData['username'].toString(),
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.white),
),
SizedBox(
height: 6,
),
Text(
userData['bio'].toString(),
style: TextStyle(
color: Colors.grey.shade600,
fontSize: 13,
),
),
],
),
),
Icon(
Icons.settings,
color: Colors.white,
),
],
),
),
),
),
body: Stack(
children: <Widget>[
ListView(
reverse: true,
children: snapshot.data!.docs.map(
(DocumentSnapshot documentSnapshot) {
data = documentSnapshot.data()!;
print(documentSnapshot.toString());
print(data['msg']);
return Padding(
padding:
const EdgeInsets.symmetric(horizontal: 8.0),
child: ChatBubble(
clipper: ChatBubbleClipper6(
nipSize: 0,
radius: 0,
type: isSender(data['uid'].toString())
? BubbleType.sendBubble
: BubbleType.receiverBubble,
),
alignment: getAlignment(data['uid'].toString()),
margin: EdgeInsets.only(top: 20),
backGroundColor:
isSender(data['uid'].toString())
? Color(0xFF08C187)
: Color(0xffE7E7ED),
child: Container(
constraints: BoxConstraints(
maxWidth:
MediaQuery.of(context).size.width * 0.7,
),
child: Column(
children: [
Row(
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Text(data['msg'],
style: TextStyle(
color: isSender(data['uid']
.toString())
? Colors.white
: Colors.black),
maxLines: 100,
overflow: TextOverflow.ellipsis)
],
),
Row(
mainAxisAlignment:
MainAxisAlignment.end,
children: [
Text(
data['createdOn'] == null
? DateTime.now().toString()
: data['createdOn']
.toDate()
.toString(),
style: TextStyle(
fontSize: 10,
color: isSender(
data['uid'].toString())
? Colors.white
: Colors.black),
)
],
)
],
),
),
),
);
},
).toList(),
),
Align(
alignment: Alignment.bottomLeft,
child: Container(
padding:
EdgeInsets.only(left: 10, bottom: 10, top: 10),
height: 60,
width: double.infinity,
color: Colors.black,
child: Row(
children: <Widget>[
GestureDetector(
onTap: () {},
child: Container(
height: 40,
width: 40,
decoration: BoxDecoration(
color: kBlue,
borderRadius: BorderRadius.circular(30),
),
child: Icon(
Icons.add,
color: Colors.white,
size: 26,
),
),
),
SizedBox(
width: 15,
),
Expanded(
child: TextField(
controller: messageController,
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
hintText: "Lütfen mesaj yazınız.",
labelStyle:
TextStyle(color: Colors.white),
hintStyle: TextStyle(color: Colors.white),
border: InputBorder.none),
),
),
SizedBox(
width: 15,
),
GestureDetector(
onTap: () {
sendMessage(messageController.text);
},
child: Container(
height: 40,
width: 40,
decoration: BoxDecoration(
color: kBlue,
borderRadius: BorderRadius.circular(30),
),
child: Icon(
Icons.send,
color: Colors.white,
size: 20,
),
),
),
],
),
),
),
],
),
);
}
return null!;
},
);
}
}

setState() on showDialog() from initState() is not changing the state. Flutter

I have created a dialog with StatefulBuilder. Setstate works perfectly within the StatefulBuilder. But I want to change that state from initstate too. But the set state from initstate is not called.
My code:
#override
void initState() {
super.initState();
rest_controller = AnimationController(
vsync: this,
duration: Duration(seconds: 15),
);
rest_controller.addListener(() {
if (rest_controller.isAnimating) {
setState(() {
print("rp"+rest_progress.toString());
rest_progress = rest_controller.value;
});
} else {
setState(() {
print("rp2"+rest_progress.toString());
rest_progress = 1.0;
rest_isPlaying = false;
});
}
});
}
Dialog open function:
showDataAlert() {
showDialog(
context: context,
builder: (context) {
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(
20.0,
),
),
),
backgroundColor: kMainColor,
contentPadding: EdgeInsets.only(
top: 10.0,
),
title: Text(
"Take Rest",
style: TextStyle(fontSize: 24.0, color: kTextColor),
),
content:
Center(
child: Column(
children: [
SizedBox(
height: 10,
),
Expanded(
child: Stack(
alignment: Alignment.center,
children: [
SizedBox(
width: 260,
height: 260,
child: CircularProgressIndicator(
backgroundColor: Colors.grey.shade300,
value: rest_progress,
strokeWidth: 6,
),
),
AnimatedBuilder(
animation: rest_controller,
builder: (context, child) => Text(
restCountText,
style: TextStyle(
fontSize: 50,
fontWeight: FontWeight.bold,
color: kTextColor,
),
),
),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: () {
if (rest_controller.isAnimating) {
rest_controller.stop();
setState(() {
rest_isPlaying = false;
});
} else {
rest_controller.reverse(from: rest_controller.value == 0 ? 1.0 : rest_controller.value);
setState(() {
rest_isPlaying = true;
});
}
},
child: RoundButton(
icon: rest_isPlaying == true ? Icons.pause : Icons.play_arrow,
),
),
GestureDetector(
onTap: () {
rest_controller.reset();
setState(() {
rest_isPlaying = false;
});
},
child: RoundButton(
icon: Icons.stop,
),
),
],
),
)
],
),
),
);
}
);
});
}
Basically, setstate from the initstate is not changing the state. I have tried to change the state from showDataAlert function also, but no luck. Only the state changes if I click the button inside the showdialog.

How can I add a new value to my text editcontroller in Text formfield?

I have a database and retrieving my Data from firestore.
class ProductProvider with ChangeNotifier {
UserModel userModel;
List<UserModel> userModelList = [];
Future<void> getUserData() async {
List<UserModel> newList = [];
User currentUser = FirebaseAuth.instance.currentUser;
QuerySnapshot userSnapshot = await FirebaseFirestore.instance
.collection("Manufacturer-Accounts")
.get();
userSnapshot.docs.forEach(
(element) {
if (currentUser.uid == element.data()['Manufacturer_ID']) {
userModel = UserModel(
userFName: element.data()['FirstName'],
userCompany: element.data()['Company'],
userDesignation: element.data()['Designation'],
userEmail: element.data()['Email'],
userPhone: element.data()['PhoneNumber'],
userLastName: element.data()['LastName'],
);
newList.add(userModel);
}
userModelList = newList;
},
);
}
I have retrieved my data as a list and set it to the textformfield like this in a stateful widget as I know the TextEditing Controller should be initiated in stateful widget and should not be as final.
class ProfileScreen extends StatefulWidget {
static String routeName = "/Settings";
#override
_ProfileScreenState createState() => _ProfileScreenState();
}
class _ProfileScreenState extends State<ProfileScreen> {
var _formKey = GlobalKey<FormState>();
File _pickedImageFile;
PickedFile _pickedImage;
TextEditingController firstName;
TextEditingController lastName;
TextEditingController phoneNumber;
TextEditingController designation;
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
User user = FirebaseAuth.instance.currentUser;
void userDetailsUpdate() {
FirebaseFirestore.instance
.collection("Manufacturer-Accounts")
.doc(user.uid)
.update({
'Designation': designation.text,
'FirstName': firstName.text,
'LastName': lastName.text,
//'Email': user.email,
'Phone': phoneNumber.text,
//'UserImage': imageUrl == null ? "" : imageUrl,
});
}
Future<void> getImage({ImageSource source}) async {
_pickedImage = await ImagePicker().getImage(source: source);
if (_pickedImage != null) {
_pickedImageFile = File(_pickedImage.path);
}
}
String imageUrl;
void _uploadImage({File image}) async {
StorageReference storageReference = FirebaseStorage.instance
.ref()
.child('UserImage')
.child("UserImage/${user.uid}");
StorageUploadTask uploadTask = storageReference.putFile(image);
StorageTaskSnapshot taskSnapshot = await uploadTask.onComplete;
imageUrl = await taskSnapshot.ref.getDownloadURL();
}
Future<void> myDiscardChanges() {
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return CupertinoAlertDialog(
content: SingleChildScrollView(
child: ListBody(
children: [
Text("Discard changes?"),
SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
FlatButton(
padding: EdgeInsets.all(12),
color: Colors.amber[400],
hoverColor: Colors.blueGrey[300],
child: Text("Yes"),
onPressed: () {
setState(() {
editProfile = false;
});
Navigator.of(context).pop();
},
),
FlatButton(
padding: EdgeInsets.all(12),
color: Colors.amber[400],
hoverColor: Colors.blueGrey[300],
child: Text("No"),
onPressed: () {
setState(() {
editProfile = true;
});
Navigator.of(context).pop();
},
),
],
)
],
),
),
);
},
);
}
Future<void> myDialogBox() {
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
content: SingleChildScrollView(
child: ListBody(
children: [
ListTile(
leading: Icon(Icons.camera_alt),
title: Text("Camera"),
onTap: () {
getImage(source: ImageSource.camera);
Navigator.of(context).pop();
},
),
ListTile(
leading: Icon(Icons.photo_library),
title: Text("Gallery"),
onTap: () {
getImage(source: ImageSource.gallery);
Navigator.of(context).pop();
},
)
],
),
),
);
});
}
bool editProfile = false;
ProductProvider productProvider;
Widget newBuildTrue() {
List<UserModel> userModel = productProvider.getUserModelList;
return Column(
children: userModel.map((e) {
//userImage = e.userImage;
return Container(
child: Column(
children: [
buildContainerTrue(
startText: "First Name",
endText: e.userFName,
),
buildContainerTrue(
startText: "Last Name",
endText: e.userLastName,
),
buildContainerTrue(
startText: "E-mail",
endText: e.userEmail,
),
buildContainerTrue(
startText: "Designation",
endText: e.userDesignation,
),
buildContainerTrue(
startText: "Company",
endText: e.userCompany,
),
buildContainerTrue(
startText: "Telephone No",
endText: (e.userPhone).toString(),
),
],
),
);
}).toList(),
);
}
String userImage;
Widget newBuildFalse() {
List<UserModel> userModel = productProvider.getUserModelList;
return Column(
children: userModel.map((e) {
//userImage = e.userImage;
firstName = TextEditingController(text: e.userFName);
lastName = TextEditingController(text: e.userLastName);
phoneNumber = TextEditingController(text: e.userPhone);
designation = TextEditingController(text: e.userDesignation);
return Container(
child: Column(
children: [
// buildTextFormField(editText: "FirstName"),
MyTextFormField(
name: "FirstName",
controller: firstName,
),
MyTextFormField(
name: "LastName",
controller: lastName,
),
buildContainerTrue(
startText: "E-mail",
endText: e.userEmail,
),
MyTextFormField(
name: "Designation",
controller: designation,
),
buildContainerTrue(
startText: "Company",
endText: e.userCompany,
),
MyTextFormField(
name: "Telephone No",
controller: phoneNumber,
),
],
),
);
}).toList(),
);
}
#override
void initState() {
super.initState();
}
#override
void dispose() {
//firstName.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
productProvider = Provider.of<ProductProvider>(context);
productProvider.getUserData();
ScreenUtil.init(context, height: 896, width: 414, allowFontScaling: true);
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
leading: editProfile == false
? IconButton(
icon: Icon(Icons.menu),
color: kPrimaryColor,
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) => MenuFrame(),
),
);
},
)
: Container(),
elevation: 1,
actions: [
editProfile == false
? IconButton(
icon: Icon(Icons.edit),
color: kPrimaryColor,
onPressed: () {
setState(() {
editProfile = true;
});
},
)
: IconButton(
icon: Icon(Icons.close),
color: kPrimaryColor,
onPressed: () {
myDiscardChanges();
},
),
],
),
body: Form(
key: _formKey,
child: Container(
height: double.infinity,
width: double.infinity,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
height: kSpacingUnit.w * 10,
width: kSpacingUnit.w * 10,
margin: EdgeInsets.only(top: kSpacingUnit.w * 3),
child: Stack(
children: <Widget>[
CircleAvatar(
radius: kSpacingUnit.w * 8,
backgroundImage: _pickedImageFile == null
? AssetImage('assets/images/12.jpg')
: FileImage(_pickedImageFile),
),
editProfile == true
? Align(
alignment: Alignment.bottomRight,
child: Container(
height: kSpacingUnit.w * 2.5,
width: kSpacingUnit.w * 2.5,
decoration: BoxDecoration(
color: kAccentColor,
shape: BoxShape.circle,
),
child: Center(
heightFactor: kSpacingUnit.w * 1.5,
widthFactor: kSpacingUnit.w * 1.5,
child: GestureDetector(
onTap: () {
myDialogBox();
},
child: Icon(
LineAwesomeIcons.pen,
color: kDarkPrimaryColor,
size: ScreenUtil()
.setSp(kSpacingUnit.w * 1.5),
),
),
),
),
)
: Container(),
],
)),
SizedBox(height: kSpacingUnit.w * 1.5),
editProfile == false ? newBuildTrue() : newBuildFalse(),
editProfile == true
? FlatButton(
color: Colors.amber,
height: 50,
minWidth: 400,
child: Text("Save"),
onPressed: () {
userDetailsUpdate();
//_uploadImage(image: _pickedImageFile);
setState(() {
editProfile = false;
});
},
)
: Container(),
],
),
),
),
),
);
}
Widget buildContainerTrue({String startText, String endText}) {
return Container(
height: kSpacingUnit.w * 5.5,
margin: EdgeInsets.symmetric(
horizontal: kSpacingUnit.w * 2,
).copyWith(
bottom: kSpacingUnit.w * 2,
),
padding: EdgeInsets.symmetric(
horizontal: kSpacingUnit.w * 1.5,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(kSpacingUnit.w * 3),
color: kDarkSecondaryColor,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
alignment: Alignment.centerLeft,
width: 100,
height: kSpacingUnit.w * 5.5,
decoration: BoxDecoration(
// color: Colors.green,
border: Border(
right: BorderSide(color: Colors.white, width: 1),
),
),
child: Text(
startText,
style: TextStyle(color: Colors.white, fontSize: 12),
textAlign: TextAlign.left,
),
),
SizedBox(width: kSpacingUnit.w * 1.5),
Text(
endText,
style: kTitleTextStyle.copyWith(
fontWeight: FontWeight.w500,
color: Colors.amber,
fontSize: 12,
),
),
],
),
);
}
But still following the procedures I am facing an issue like when I enter my new value to the controller it still shows a new value when my keyboard exit. Tried lot of ways and still having the same issue.
Making changes to my functions it actually worked.
Widget newBuildTrue() {
List<UserModel> userModel = productProvider.getUserModelList;
return Column(
children: userModel.map((e) {
firstName = TextEditingController(text: e.userFName);
lastName = TextEditingController(text: e.userLastName);
phoneNumber = TextEditingController(text: e.userPhone);
designation = TextEditingController(text: e.userDesignation);
//userImage = e.userImage;
return Container(
child: Column(
children: [
buildContainerTrue(
startText: "First Name",
endText: e.userFName,
),
buildContainerTrue(
startText: "Last Name",
endText: e.userLastName,
),
buildContainerTrue(
startText: "E-mail",
endText: e.userEmail,
),
buildContainerTrue(
startText: "Designation",
endText: e.userDesignation,
),
buildContainerTrue(
startText: "Company",
endText: e.userCompany,
),
buildContainerTrue(
startText: "Telephone No",
endText: (e.userPhone).toString(),
),
],
),
);
}).toList(),
);
}
String userImage;
Widget newBuildFalse() {
List<UserModel> userModel = productProvider.getUserModelList;
return Column(
children: userModel.map((e) {
//userImage = e.userImage;
return Container(
child: Column(
children: [
// buildTextFormField(editText: "FirstName"),
MyTextFormField(
name: "FirstName",
controller: firstName,
),
buildTextFormField(
editText: "LastName",
textEditingController: lastName,
),
buildContainerTrue(
startText: "E-mail",
endText: e.userEmail,
),
MyTextFormField(
name: "Designation",
controller: designation,
),
buildContainerTrue(
startText: "Company",
endText: e.userCompany,
),
MyTextFormField(
name: "Telephone No",
controller: phoneNumber,
),
],
),
);
}).toList(),
);
}

A non-null string must be provided to a text widget - Flutter Android

My code was working fine but now I'm unable to see the Profile page as it generates an error and I'm unable to identify, even though I tried to return a Container() at the end of buildProfileButton() but it did not solve the issue as I updated the code of that function later on.
class Profile extends StatefulWidget {
final String profileId;
Profile({this.profileId});
#override
_ProfileState createState() => _ProfileState();
}
class _ProfileState extends State<Profile> {
final String currentUserId = currentUser?.id;
bool isLoading = false;
int postCount = 0;
bool isFollowing = false;
int followerCount = 0;
int followingCount = 0;
List<Post> posts = [];
#override
void initState() {
super.initState();
getProfilePosts();
getFollowers();
getFollowing();
checkIfFollowing();
}
checkIfFollowing() async {
DocumentSnapshot doc = await followersRef
.document(widget.profileId)
.collection('userFollowers')
.document(currentUserId)
.get();
setState(() {
isFollowing = doc.exists;
});
}
getFollowers() async {
QuerySnapshot snapshot = await followersRef
.document(widget.profileId)
.collection('userFollowers')
.getDocuments();
setState(() {
followerCount = snapshot.documents.length;
});
}
getFollowing() async {
QuerySnapshot snapshot = await followingRef
.document(widget.profileId)
.collection('userFollowing')
.getDocuments();
setState(() {
followingCount = snapshot.documents.length;
});
}
getProfilePosts() async {
setState(() {
isLoading = true;
});
QuerySnapshot snapshot = await postsRef
.document(widget.profileId)
.collection('userPosts')
.orderBy('rating', descending: true)
.getDocuments();
setState(() {
isLoading = false;
postCount = snapshot.documents.length;
posts = snapshot.documents.map((doc) => Post.fromDocument(doc)).toList();
});
}
Column buildCountColumn(String label, int count) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
count.toString(),
style: TextStyle(fontSize: 22.0, fontWeight: FontWeight.bold),
),
Container(
margin: EdgeInsets.only(top: 4.0),
child: Text(
label,
style: TextStyle(
color: Colors.black,
fontSize: 15.0,
fontWeight: FontWeight.w400,
),
),
),
],
);
}
editProfile() {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EditProfile(currentUserId: currentUserId)));
}
Container buildButton({String text, Function function}) {
return Container(
padding: EdgeInsets.only(top: 2.0),
child: FlatButton(
onPressed: function,
child: Container(
width: 210.0,
height: 27.0,
child: Text(
text,
style: TextStyle(
color:
isFollowing ? Colors.white : Theme.of(context).primaryColor,
fontWeight: FontWeight.bold,
),
),
alignment: Alignment.center,
decoration: BoxDecoration(
color: isFollowing ? Theme.of(context).primaryColor : Colors.white,
border: Border.all(
color: Theme.of(context).primaryColor,
),
borderRadius: BorderRadius.circular(5.0),
),
),
),
);
}
buildProfileButton() {
bool isProfileOwner = currentUserId == widget.profileId;
if (isProfileOwner) {
return buildButton(
text: "Edit Profile",
function: editProfile,
);
} else if (isFollowing) {
return buildButton(
text: "Unfollow",
function: handleUnfollowUser,
);
} else if (!isFollowing) {
return buildButton(
text: "Follow",
function: handleFollowUser,
);
}
}
handleUnfollowUser() {
setState(() {
isFollowing = false;
});
followersRef
.document(widget.profileId)
.collection('userFollowers')
.document(currentUserId)
.get()
.then((doc) {
if (doc.exists) {
doc.reference.delete();
}
});
followingRef
.document(currentUserId)
.collection('userFollowing')
.document(widget.profileId)
.get()
.then((doc) {
if (doc.exists) {
doc.reference.delete();
}
});
activityFeedRef
.document(widget.profileId)
.collection('feedItems')
.document(currentUserId)
.get()
.then((doc) {
if (doc.exists) {
doc.reference.delete();
}
});
}
handleFollowUser() {
setState(() {
isFollowing = true;
});
followersRef
.document(widget.profileId)
.collection('userFollowers')
.document(currentUserId)
.setData({});
followingRef
.document(currentUserId)
.collection('userFollowing')
.document(widget.profileId)
.setData({});
activityFeedRef
.document(widget.profileId)
.collection('feedItems')
.document(currentUserId)
.setData({
"type": "follow",
"ownerId": widget.profileId,
"username": currentUser.username,
"userId": currentUserId,
"userProfileImg": currentUser.photoUrl,
"timestamp": timestamp,
});
}
buildProfileHeader() {
return FutureBuilder(
future: usersRef.document(widget.profileId).get(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return circularProgress();
}
User user = User.fromDocument(snapshot.data);
return Padding(
padding: EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
CircleAvatar(
radius: 40.0,
backgroundColor: Colors.grey,
backgroundImage: CachedNetworkImageProvider(user.photoUrl),
),
Expanded(
flex: 1,
child: Column(
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
buildCountColumn("Videos", postCount),
buildCountColumn("Followers", followerCount),
buildCountColumn("Following", followingCount),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[buildProfileButton()],
),
],
),
),
],
),
Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(top: 12.0),
child: Text(
user.username,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16.0,
),
),
),
Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(top: 4.0),
child: Text(
user.displayName,
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
),
Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(top: 2.0),
child: Text(
user.bio,
),
),
],
),
);
},
);
}
buildProfilePosts() {
if (isLoading) {
return circularProgress();
} else if (posts.isEmpty) {
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SvgPicture.asset('assets/images/no_content.svg', height: 260.0),
Padding(
padding: EdgeInsets.only(top: 20.0),
child: Text(
"No Posts",
style: TextStyle(
color: Colors.redAccent,
fontSize: 40.0,
fontWeight: FontWeight.bold),
),
),
],
),
);
}
return Column(
children: posts,
);
}
buildTogglePostOrientation() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
IconButton(
icon: Icon(Icons.videocam,
size: 30.0, color: Theme.of(context).primaryColor),
onPressed: null,
),
],
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: header(context, titleText: "PROFILE"),
body: ListView(
children: <Widget>[
buildProfileHeader(),
Divider(),
buildTogglePostOrientation(),
Divider(
height: 0.0,
),
buildProfilePosts(),
],
),
);
}
}
The debug console says that: A non-null String must be provided to a Text widget.
'package:flutter/src/widgets/text.dart':
Failed assertion: line 285 pos 10: 'data != null'
The relevant error-causing widget was
FutureBuilder
Instead of writing Text(description), write Text(description ?? '') so the Text widget will be empty if description is null.
When using the property of an object, instead of writing Text(user.bio) write Text(user?.bio ?? '') for the Text widget to get an empty string if user or user.bio is null.
You can Also make sure that the strings your using in the Text widget are never null.
Not related to the question but I see that you use a lot of functions to build your UI,
I suggest that you turn each of them to a separate widget to improve your app's performance. see this post to learn more.