I have experience a weird behaviour in Flutter Stateful widget. I am initializing a local list from the class's final list variable using widget.variable_name. I have incorporated a function to delete an item from the local list but it affects the class variable too. How is this even possible?
Here is the code:
import 'package:flutter/material.dart';
class Test extends StatefulWidget {
const Test({
required this.fruits
});
final List<String> fruits;
static const String routeName = '/test';
static Route route({required List<String> fruits}){
return MaterialPageRoute(
settings: RouteSettings(name: routeName),
builder: (_) => Test(fruits: fruits,)
);
}
@override
State<Test> createState() => _TestState();
}
class _TestState extends State<Test> {
List<String>? _fruits;
void deleteFruit(name){
setState((){
_fruits!.remove(name);
print("_fruits: ${widget.fruits}");
print("widget.fruits: ${widget.fruits}");
});
}
@override
void initState() {
super.initState();
setState(() {
_fruits = widget.fruits;
print("Initial fruits: $_fruits");
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
child: Column(
children:
(_fruits != null) ?
_fruits!.map((e) => ListTile(
leading: IconButton(
icon: Icon(Icons.remove),
onPressed: (){
deleteFruit(e);
}),
title: Text(e),
),
).toList() : []
),
),
);
}
}
I am routing to this stateful widget from another widget using
Navigator.pushNamed(context, '/test',arguments: ["apple","mango","orange"]);
When I delete an item say "mango" from the list, the output is as follows,
_fruits : ["apple","orange"]
widget.fruits : ["apple","orange"] \\I was expecting to get ["apple","mango","orange"]
CodePudding user response:
I suspect the instance of object is passed by reference in your case. Try creating new list like
_fruits = widget.fruits.toList();
Also while feeding on constructor, you can DO
Test(fruits: yourItems.toList(),
You can check Is Dart pass by reference
CodePudding user response:
One should see that Dart it isn't a language that copy the value of variables. So when you pass the fruits down the state, you'll be sending the reference of that list, and that reference points out to the original object. To solve this, you need to copy the list before remove, and assign the new copy to the _fruits variable at the state.
class _TestState extends State<Test> {
List<String>? _fruits;
...
@override
void initState() {
super.initState();
setState(() {
_fruits = [...widget.fruits]; // Copies the objects reference to a new List
print("Initial fruits: $_fruits");
});
}
...