I found selectorDependency.selectors will add aspect many times and never clean.
inherited_provider.dart
@override
void updateDependencies(Element dependent, Object aspect) {
final dependencies = getDependencies(dependent);
// once subscribed to everything once, it always stays subscribed to everything
if (dependencies != null && dependencies is! _Dependency<T>) {
return;
}
if (aspect is _SelectorAspect<T>) {
final selectorDependency =
(dependencies ?? _Dependency<T>()) as _Dependency<T>;
if (selectorDependency.shouldClearSelectors) {
selectorDependency.shouldClearSelectors = false;
selectorDependency.selectors.clear();
}
if (selectorDependency.shouldClearMutationScheduled == false) {
selectorDependency.shouldClearMutationScheduled = true;
SchedulerBinding.instance.addPostFrameCallback((_) {
selectorDependency.shouldClearSelectors = true;
});
}
print('updateDependencies ${selectorDependency.selectors.length}');
selectorDependency.selectors.add(aspect);<--------------aspect leak
setDependencies(dependent, selectorDependency);
} else {
// subscribes to everything
setDependencies(dependent, const Object());
}
}
I also found this problem.
Could you give a way to reproduce the issue?
Could you give a way to reproduce the issue?
ok this is my test code.you can run it and click the items star, when click one item, it's ok, but when you click more, it will rebuild other item. see log _buildGoodsItem.
class ThirdPage2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Third Page')),
body: ChangeNotifierProvider(
create: (_) => GoodsList(),
child: Builder(builder: _buildGoodsListView),
),
);
}
Widget _buildGoodsListView(BuildContext context) {
print('_buildGoodsListView');
final model = Provider.of<GoodsList>(context,listen: false);
return ListView.builder(
itemCount: model.total,
itemBuilder: (context1, index)=>Builder(builder: (context2)=>_buildGoodsItem(context2,index)),
);
}
Widget _buildGoodsItem(BuildContext context, int index) {
print('_buildGoodsItem $index');
final name =
context.select((GoodsList model) => model.goodList[index].goodsName);
final liked =
context.select((GoodsList model) => model.goodList[index].isLiked);
// final model = context.select((GoodsList model) => model);
return ListTile(
title: Text(name),
trailing: GestureDetector(
onTap: () => context.read<GoodsList>().like(index),
child: Icon(liked? Icons.star : Icons.star_border),
),
);
}
}
class GoodsList with ChangeNotifier{
List<Goods> _goodList = List.generate(20, (index) => Goods(false,'Good No. $index'));
List<Goods> get goodList=>_goodList;
int get total=>_goodList.length;
like(int index){
var goods = _goodList[index];
_goodList[index]._isLiked = !goods.isLiked;
print('like index = $index');
notifyListeners();
}
}
class Goods{
Goods(this._isLiked,this._goodsName);
String _goodsName;
String get goodsName =>_goodsName;
bool _isLiked;
bool get isLiked => _isLiked;
}
Oh interesting. It sounds like the internal == comparison is performed on the wrong object
I'll investigate
Most helpful comment
Oh interesting. It sounds like the internal == comparison is performed on the wrong object
I'll investigate