Рубрики
Flutter

Как избежать перерисовок в Flutter с помощью Provider

Flutter является мощным фреймворком, который позволяет создавать красивые и быстрые мобильные приложения. Однако, при разработке приложений на Flutter может возникнуть проблема частых перерисовок экрана приложения. В этой статье мы рассмотрим, как избежать перерисовок в Flutter с помощью Provider.

Что такое перерисовки в Flutter?

Перерисовки в Flutter происходят, когда виджет перерисовывается на экране. Это может происходить во время изменения состояния приложения или при вызове метода setState(). Перерисовки могут замедлить работу приложения и потреблять большое количество ресурсов устройства.

Как избежать перерисовок в Flutter с помощью Provider?

Flutter Provider — это библиотека для управления состоянием в приложении. Она позволяет избежать перерисовок приложения путем использования Provider и Consumer. Рассмотрим несколько способов использования Provider для избежания перерисовок.

1. Использование Selector

Selector — это виджет, который позволяет выбирать только необходимые данные из Provider. Он позволяет избежать перерисовки всего экрана при изменении какого-то одного поля в Provider.

Для примера, предположим, что у нас есть класс Counter с полем count. Мы хотим отобразить значение поля count на экране. Для этого мы можем использовать Selector, чтобы избежать перерисовки всего экрана при изменении поля count:

class Counter {
  int count = 0;

  void increment() {
    count++;
  }
}

class CounterProvider with ChangeNotifier {
  Counter _counter = Counter();

  Counter get counter => _counter;

  void increment() {
    _counter.increment();
    notifyListeners();
  }
}

class CounterScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Selector<CounterProvider, int>(
          selector: (_, provider) => provider.counter.count,
          builder: (_, count, __) => Text(count.toString()),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Provider.of<CounterProvider>(context, listen: false).increment();
        },
        child: Icon(Icons.add),
      ),
    );
  }
}

2. Использование Consumer

Consumer — это виджет, который позволяет перерисовывать только ту часть экрана, которая изменилась. Он используется для обновления только той части экрана, которая зависит от состояния Provider.

Для примера, предположим, что у нас есть класс Task с полем title. Мы хотим отобразить список задач на экране. Когда пользователь добавляет новую задачу, мы хотим обновить только список задач, а не весь экран. Мы можем использовать Consumer для обновления только списка задач:

class Task {
  String title;

  Task(this.title);
}

class TaskProvider with ChangeNotifier {
  List<Task> _tasks = [];

  List<Task> get tasks => _tasks;

  void addTask(Task task) {
    _tasks.add(task);
    notifyListeners();
  }
}

class TaskScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          Expanded(
            child: Consumer<TaskProvider>(
              builder: (_, provider, __) => ListView.builder(
                itemCount: provider.tasks.length,
                itemBuilder: (_, index) => ListTile(
                  title: Text(provider.tasks[index].title),
                ),
              ),
            ),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          showDialog(
            context: context,
            builder: (_) => AlertDialog(
              title: Text('Add Task'),
              content: TextField(
                onChanged: (value) {
                  Provider.of<TaskProvider>(context, listen: false)
                      .addTask(Task(value));
                },
              ),
            ),
          );
        },
        child: Icon(Icons.add),
      ),
    );
  }
}

3. Использование ValueNotifier

ValueNotifier — это класс, который позволяет уведомлять слушателей только при изменении значения. Это позволяет избежать частых перерисовок, если изменения не влияют на отображение на экране.

Для примера, предположим, что у нас есть класс Theme с полем primaryColor. Мы хотим изменять цвет темы приложения без перерисовки всего экрана. Мы можем использовать ValueNotifier, чтобы избежать частых перерисовок:

class Theme {
  Color primaryColor;

  Theme(this.primaryColor);
}

class ThemeProvider with ChangeNotifier {
  ValueNotifier<Theme> _theme = ValueNotifier(Theme(Colors.blue));

  ValueNotifier<Theme> get theme => _theme;

  void changeThemeColor(Color color) {
    _theme.value = Theme(color);
  }
}

class ThemeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Consumer<ThemeProvider>(
          builder: (_, provider, __) => Container(
            width: 100,
            height: 100,
            color: provider.theme.value.primaryColor,
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Provider.of<ThemeProvider>(context, listen: false)
              .changeThemeColor(Colors.green);
        },
        child: Icon(Icons.color_lens),
      ),
    );
  }
}

Заключение

Использование Provider в Flutter позволяет избежать частых перерисовок экрана приложения и улучшить производительность приложения. Мы рассмотрели несколько способов использования Provider для избежания перерисовок, таких как Selector, Consumer и ValueNotifier. Надеемся, что эти советы помогут вам создать более бы