Flutter call setState() to update UI in another class
Solution 1
I managed to make it work, by making both classes into one and calling a function to draw the messagecards, thank you all for your help and attention
Solution 2
You can only use setState
in a StatefulWidget
.
class MessageCard extends StatefulWidget {
@override
_MessageCardState createState() => _MessageCardState();
}
class _MessageCardState extends State<MessageCard> {
@override
Widget build(BuildContext context) {
// your build method here
}
}
Solution 3
Stateless widget can not change the state once its rendered. To use setState and re-render the widget StatefulWidget is used.
Just change your MessageCard from Stateless Widget to StatefulWidget
class MessageCard extends StatefulWidget {
final Mensagem message;
final int messageLenght;
final List<Mensagem> messageList;
var i;
MessageCard(
{@required this.message,
@required this.messageLenght,
@required this.messageList});
@override
_MessageCardState createState() => _MessageCardState();
}
class _MessageCardState extends State<MessageCard> {
@override
Widget build(BuildContext context) {
// your build method here
}
}
Also, now "to use your MessageCard properties" like message, messageLenght, messageList, in _MessageCardState you have to use a property like widget.message, widget.messageList and widget.messageLenght respectively.
Solution 4
can this work to refresh the ui?
_getMessages() async {
_HomePageState()._messages = await mensagemRepo.getMessages();
print('loaded messages: ${_messages?.length}');
setState(() {
_HomePageState()._messagesList();
});
}
The code for _messagesList() is:
SliverChildBuilderDelegate _messagesList() {
int count() {
if (_errorMsg != '')
return 1;
else
return _messages == null ? 0 : _messages.length;
}
return SliverChildBuilderDelegate(
(BuildContext context, int index) {
print("i: $index");
if (_errorMsg != '') {
return Padding(
padding: EdgeInsets.all(20),
child: ErrorMessage(
error: _errorMsg,
),
);
} else {
return _MessageCard(
message: this._messages[index],
messageLength: this._messages.length,
messageList: this._messages);
}
},
childCount: count(),
);
}
Solution 5
Well, you can't set value for something that doesn't exist. Stateless by name itself makes it clear that it can't hold any state. Changing the widget to a stateful widget would work.
André Sousa
Updated on December 16, 2022Comments
-
André Sousa over 1 year
I am trying to call a setState when a button is pressed so the ui can show the new list but even using functions i cant use setState or it will give me the error saying im calling setState inside a constructor.
This is my code for the statlessWidget:
class _MessageCard extends StatelessWidget { final Mensagem message; final int messageLenght; final List<Mensagem> messageList; var i; _MessageCard( {@required this.message, @required this.messageLenght, @required this.messageList}); @override Widget build(BuildContext context) { return Center( child: Container( width: 600, child: InkWell( child: Container( width: 900, color: Colors.grey[200], child: Padding( padding: const EdgeInsets.fromLTRB(12, 0, 12, 0), child: Center( child: Container( width: 600, child: Column( children: <Widget>[ ListTile( leading: CircleAvatar( child: Icon( Icons.notifications, color: Colors.red[400], ), backgroundColor: Colors.grey[200], ), title: Text( (this.message.vDescricao ?? '').trim(), style: TextStyle( fontSize: 14, color: Colors.black, ), ), subtitle: Text( (this.message.vData ?? '').trim() + ' ' + (this.message.vHora ?? '').trim(), style: TextStyle( color: Colors.red[400], fontSize: 13, ), ), trailing: FlatButton( child: Text( Translations.of(context) .trans('finishmessageshort'), ), onPressed: () => _showDeleteAlertMessage( this.message.vNumero, context)), ), Divider( color: Colors.black54, ), ], ), ), ), ), ), ), )); } Future _showDeleteAlertMessage(String id, BuildContext context) { return showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: new Text( Translations.of(context).trans('finishmessage') + '?', ), actions: <Widget>[ FlatButton( child: new Text( Translations.of(context).trans('closealert'), ), onPressed: () { Navigator.of(context).pop(); }), FlatButton( child: new Text(("Ok")), onPressed: () => {_deleteMessage(id), Navigator.of(context).pop()}, ) ], ); }); } _deleteMessage(String id) async { for (i = 0; i < this.messageLenght; i++) { if (this.messageList[0].vNumero == this.message.vNumero) { this.messageList.removeAt(i); _HomePageState().mensagemRepo.confirmMessage(this.message.vNumero); await _HomePageState()._getMessages(); return this.messageList; } } } }
And this is my _getMessages()
_getMessages() async { setState(() { _loading = true; _errorMsg = ''; }); try { _messages = await mensagemRepo.getMessages(); print('loaded messages: ${_messages?.length}'); } catch (e) { _errorMsg = e.toString(); } setState(() { _loading = false; });
}
How can i make it so i can use this setState?
Thank you for your time and attention
Edit: Now updates List but not UI, because im not able to set HomePage state from MessageCard
-
Golden Lion almost 3 yearssetState can only be used in a stateful widget. if you want to communicate between classes use a void call back function and pass the pointer function to the dependent widget. Otherwise use a notification and change notification broadcast stream.
-
-
André Sousa over 4 yearsif i use it like that i cant call the messageCard build in my homepage or do i need to call the messagecardState?
-
Benjamin over 4 yearsCall
MessageCard()
in your build method, it will be fine. ThecreateState
method will call_MessageCardState
for you. -
André Sousa over 4 yearsand what if i wanted to access my other homepage widget? can i call setState inside my messagecard?
-
Jay Mungara over 4 yearsMessageCard will be out of picture when you use StatefulWidget. You don't need to create and execute any functions, variables inside your MessageCard class. Whatever you have to perform will be done in your State class which is _MessageCardState . As name suggests, state class is used to manage and change your widget state and you can use it only inside _MessageCardState.
-
André Sousa over 4 yearsso there is no way for me to update the state of another class inside the MessageCard class?
-
Jay Mungara over 4 years_MessageCardState is the class which manages state of the MessageCard. So, ultimately whatever state you are changing is used to change the state of the MasterClass. Don't get confused with having two class MessageCard and _MessageCardState. They are ultimately interconnected.
-
André Sousa over 4 yearsI can clear them from the list but i cant seem to update the ui in the HomePage class which is the main class
-
Jay Mungara over 4 yearsupdate your list when data updates using setState() method. Update your question.