Rafid Kotta
Rafid Kotta

Reputation: 750

Flutter is not rebuilding same widget with different parameters

I was working with bottom navigation with similar child widgets in which only parameters are changed. The problem only happens when widgets are of StatefulWidget else there is no problem, indications in bottomnavbar is changing but not the body.

Child 1: enter image description here

Child 2: enter image description here

Actual result: enter image description here

class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;

@override
_MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
Widget body;
@override
void initState() {
//    body = getBody(0);
super.initState();
}

@override
Widget build(BuildContext context) {
return Scaffold(
  appBar: AppBar(
    title: Text(widget.title),
    elevation: 0,
  ),
  body: body,
  bottomNavigationBar: BottomNavigationBar(
    currentIndex: _counter,
    onTap: (index){
      _counter = index;
      setState(() {
        body = getBody(index);
      });
    },items: [
    BottomNavigationBarItem(icon: Icon(Icons.language),title: 
 Text('HELLO')),
    BottomNavigationBarItem(icon: Icon(Icons.security),title: 
Text('BYE'))
  ]),
 );
}
Widget getBody(int pos){
if(pos==0){
//      return new Mx(category: 'ALPHA',type: '@',);
  return new MyTAbs(category: 'ALPHA',type: '@',);
}
else{
//      return new Mx(category:'BETA',type: '#',);
  return new MyTAbs(category:'BETA',type: '#',);
  }
 }
}
class Mx extends StatelessWidget{
final String type,category;
Mx({this.type,this.category});
@override
Widget build(BuildContext context) {
 return new Scaffold(
  backgroundColor: getColor(),
  body: new Center(
    child: Text(category+' '+type),
  ),
 );
}
Color getColor(){
if(category=='ALPHA'){
  return Colors.red;
}
else{
  return Colors.green;
  }
 }
}
class MyTAbs extends StatefulWidget{
final String type,category;
MyTAbs({this.type,this.category});
Tabs createState() => new Tabs(title: category,type: type);
}
class Tabs extends State<MyTAbs>{
final String title,type;
Tabs({this.title,this.type});
@override
Widget build(BuildContext context) {
// TODO: implement build
return new Scaffold(
  backgroundColor: getColor(),
  appBar: AppBar(
    title: Text(title+' '+type),
  ),
);
}
Color getColor(){
if(title=='ALPHA'){
  return Colors.red;
}
else{
  return Colors.green;
  }
 }
}

and I can't use statelessWidget because there's a dynamic tab section inside.

Upvotes: 18

Views: 9661

Answers (3)

Rafid Kotta
Rafid Kotta

Reputation: 750

Solved this issue by adding new Key as parameter and passed a UniqueKey like

return new MyTAbs(category: 'ALPHA',type: '@',key: UniqueKey(),);

MyTAbs class

class MyTAbs extends StatefulWidget{
  final String type,category;
  final Key key;
  MyTAbs({@required this.key,this.type,this.category});
  Tabs createState() => new Tabs(title: category,type: type,key: key);
}

Tabs class

class Tabs extends State<MyTAbs>{
  final String title,type;
  final Key key;
  Tabs({this.title,this.type,@required this.key});
  @override
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new Scaffold(
      backgroundColor: getColor(),
      appBar: AppBar(
        title: Text(title+' '+type),
      ),
    );
  }
  Color getColor(){
    if(title=='ALPHA'){
      return Colors.red;
    }
    else{
      return Colors.green;
    }
  }
}

little about Key

You can use keys to control which widgets the framework matches up with other widgets when a widget rebuilds. By default, the framework matches widgets in the current and previous build according to their runtimeType and the order in which they appear. With keys, the framework requires that the two widgets have the same key as well as the same runtimeType. more in flutter docs

Upvotes: 33

abdalmonem
abdalmonem

Reputation: 1422

your problem in "MyTAbs" passing parameters class

after edit it , now its work

you dont need to pass the date from "Stateful" class to the "State", just call it with "widget.parameterName" in the state your code after edit :

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  Widget body;
  @override
  void initState() {
//    body = getBody(0);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        elevation: 0,
      ),
      body: body,
      bottomNavigationBar: BottomNavigationBar(
          currentIndex: _counter,
          onTap: (index){
            _counter = index;
            setState(() {
              body = getBody(index);
            });
          },items: [
        BottomNavigationBarItem(icon: Icon(Icons.language),title:
        Text('HELLO')),
        BottomNavigationBarItem(icon: Icon(Icons.security),title:
        Text('BYE'))
      ]),
    );
  }
  Widget getBody(int pos){
    if(pos==0){
//      return new Mx(category: 'ALPHA',type: '@',);
      return new MyTAbs(category: 'ALPHA',type: '@',);
    }
    else{

//      return new Mx(category:'BETA',type: '#',);
      return new MyTAbs(category:'BETA',type: '#',);
    }
  }
}
class Mx extends StatelessWidget{
  final String type,category;
  Mx({this.type,this.category});
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      backgroundColor: getColor(),
      body: new Center(
        child: Text(category+' '+type),
      ),
    );
  }
  Color getColor(){
    if(category=='ALPHA'){
      return Colors.red;
    }
    else{
      return Colors.green;
    }
  }
}
class MyTAbs extends StatefulWidget{
  final String type,category;
  MyTAbs({this.type,this.category});
  Tabs createState() => new Tabs();
}
class Tabs extends State<MyTAbs>{


  @override
  Widget build(BuildContext context) {
    print(widget.type);
// TODO: implement build
    return new Scaffold(
      backgroundColor: getColor(),
      appBar: AppBar(
        title: Text(widget.category+' '+widget.type),
      ),
    );
  }
  Color getColor(){
    if(widget.category=='ALPHA'){
      return Colors.red;
    }
    else{
      return Colors.green;
    }
  }
}

Upvotes: 1

Andrii Turkovskyi
Andrii Turkovskyi

Reputation: 29458

Change your Tabs class

class Tabs extends State<MyTAbs> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      backgroundColor: getColor(),
      appBar: AppBar(
        title: Text(widget.category + ' ' + widget.type),
      ),
    );
  }

  Color getColor() {
    if (widget.category == 'ALPHA') {
      return Colors.red;
    } else {
      return Colors.green;
    }
  }
}

Class State (Tabs) created only once. So after that you can't call constructor with new parameters. But you have access to the widgets' fields

Upvotes: 1

Related Questions