liangxianzhe/creator

watcher performance in version 0.3.0

Closed this issue · 4 comments

Number of setState is increasing every change in v03.0 compared to v0.2.2
please run this code in both versions.

import 'package:creator/creator.dart';
import 'package:flutter/material.dart';

class CreatorWatcherTest extends StatelessWidget {
  const CreatorWatcherTest({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    var selectedNumbers = <int>[];
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Wrap(
            children: numberGroupsList
                .map((group) => Watcher(((context, ref, child) {
                      final selected = ref.watch(selectedNumbersCreator.map(
                          (p0) =>
                              group.any((element) => p0.contains(element))));
                      print('building...');
                      return ChoiceChip(
                          selected: selected,
                          label: Text.rich(TextSpan(
                              style: TextStyle(
                                height: 1.5,
                              ),
                              children: group
                                  .map(
                                    (number) => TextSpan(
                                      text: '\t$number\t',
                                    ),
                                  )
                                  .toList())));
                    })))
                .toList(),
          ),
          StatefulBuilder(
            builder: (context, setState) {
              return SingleChildScrollView(
                  scrollDirection: Axis.horizontal,
                  child: Row(
                      children: [1, 2, 3, 4, 5, 6, 7, 8, 9].map((e) {
                    final selected = selectedNumbers.contains(e);

                    return InkWell(
                      onTap: () {
                        final s = [...selectedNumbers];
                        selected ? s.remove(e) : s.add(e);
                        selectedNumbers = s;
                        context.ref
                            .set(selectedNumbersCreator, selectedNumbers);
                        setState(
                          () {},
                        );
                      },
                      child: Card(
                        color: selected ? Colors.green : null,
                        child: Padding(
                          padding: const EdgeInsets.symmetric(
                              horizontal: 16.0, vertical: 4),
                          child: Text(e.toString()),
                        ),
                      ),
                    );
                  }).toList()));
            },
          ),
        ],
      ),
    );
  }
}

final selectedNumbersCreator =
    Creator<List<int>>.value([], name: 'selectedNumbers');
final numberGroupsList = <List<int>>[
  [1, 2, 3],
  [2, 5],
  [6, 7],
  [7, 8, 9],
  [3, 4, 5]
];

Hi @MdSaLaMa , thanks for reporting and the repro. I fixed the issue and just release 0.3.1. Please let me know if you still see any issue.

Now it make sense, thank you.

Is there any difference in performance if I used args like this:
final selected = ref.watch(selectedNumbersCreator.map( (p0) => group.any((element) => p0.contains(element)), args: group, // name: 'selected $group', ));

xx.map is a temp creator, as described in https://github.com/liangxianzhe/creator#creator-equality

In your example, the temp creator is cheap to construct, so it is fine to not use args. But if in real world, the temp creator is expensive to construct, you could use args. Though args should be globally unique. I would suggest something like args: ["number_group", ...group], unless you make sure group is unique value.