Привет, Хабр!

У меня есть несколько советов по оптимизации производительности приложений на Flutter. Хотя фреймворк и имеет высокую производительность по умолчанию, неправильное написание кода может привести к проблемам с быстродействием. Давайте рассмотрим несколько важных моментов, которые помогут вам написать быстрый и эффективный код.

Использование кэширования и мемоизации

Кэширование и мемоизация - это техники, которые помогают уменьшить количество вычислений, кэшируя результаты предыдущих операций. Вот несколько советов по использованию кэширования и мемоизации:

  • Используйте Memoizer класс: этот класс позволяет кэшировать результаты вычислений, чтобы не повторять их при каждом обновлении экрана.

    import 'package:flutter/material.dart';
    import 'package:memoizer/memoizer.dart';
    
    class OptimizedWidget extends StatelessWidget {
      final _memoizer = Memoizer();
    
      @override
      Widget build(BuildContext context) {
        return FutureBuilder(
          future: _memoizer.runOnce(_expensiveComputation),
          builder: (context, snapshot) {
            // Использование кэшированного результата вычислений
            return Text(snapshot.data.toString());
          },
        );
      }
    
      Future<int> _expensiveComputation() async {
        // Дорогая операция вычисления
        await Future.delayed(Duration(seconds: 2));
        return 42; // Результат вычислений
      }
    }

Техники оптимизации графики и анимации

Графика и анимация могут быть ресурсоемкими и медленными, если не оптимизированы должным образом. Вот несколько советов по оптимизации графики и анимации:

  • Используйте Canvas: этот класс позволяет рисовать графику напрямую на канвасе, что может помочь уменьшить количество ненужных вычислений.

    import 'package:flutter/material.dart';
    
    class OptimizedWidget extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return CustomPaint(
          painter: OptimizedPainter(),
        );
      }
    }
    
    class OptimizedPainter extends CustomPainter {
      @override
      void paint(Canvas canvas, Size size) {
        // Рисование графики напрямую на канвасе
        canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), Paint()..color = Colors.red);
      }
    
      @override
      bool shouldRepaint(OptimizedPainter oldDelegate) => false;
    }
  • Используйте AnimatedBuilder: этот виджет позволяет анимировать графику и виджеты, используя оптимизированные алгоритмы анимации.

    import 'package:flutter/material.dart';
    
    class OptimizedWidget extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return AnimatedBuilder(
          animation: _animation,
          builder: (context, child) {
            // Анимация графики и виджетов с помощью оптимизированных алгоритмов
            return Transform.translate(
              offset: Offset(_animation.value, 0),
              child: child,
            );
          },
          child: Container(...),
        );
      }
    }

    Работа с большими наборами данных и сложными вычислениями

  • Используйте Isolate: этот класс позволяет выполнять вычисления в отдельном изоляте, что может помочь уменьшить нагрузку на основной поток приложения.

    import 'package:flutter/material.dart';
    import 'dart:async';
    
    class OptimizedWidget extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return FutureBuilder(
          future: _performExpensiveComputation(),
          builder: (context, snapshot) {
            // Использование результата вычислений из отдельного изолята
            return Text(snapshot.data.toString());
          },
        );
      }
    
      Future<int> _performExpensiveComputation() async {
        final isolate = await Isolate.spawn(_expensiveComputation, null);
        final result = await isolate.join();
        return result;
      }
    
      static int _expensiveComputation() {
        // Дорогая операция вычисления
        for (int i = 0; i < 1000000; i++) {
          // Вычисления
        }
        return 42;
      }
    }

Оптимизация деревьев виджетов и макетов

Одной из основных причин медленной производительности является неоптимизированное дерево виджетов. Вот несколько советов по оптимизации деревьев виджетов и макетов:

  • Используйте LayoutBuilder: этот виджет позволяет оптимизировать макет на основе ограничений, что может помочь уменьшить количество ненужных вычислений.

    import 'package:flutter/material.dart';
    
    class OptimizedWidget extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return LayoutBuilder(
          builder: (context, constraints) {
            // Оптимизация макета виджета на основе ограничений
            return ConstrainedBox(
              constraints: constraints,
              child: Container(...),
            );
          },
        );
      }
    }
  • Используйте ValueListenableBuilder: этот виджет позволяет оптимизировать обновление виджетов на основе изменений в модели данных.

    import 'package:flutter/material.dart';
    
    class OptimizedWidget extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return ValueListenableBuilder(
          valueListenable: _dataModel,
          builder: (context, value, child) {
            // Оптимизация обновления виджета на основе изменений в модели данных
            return Text(value.toString());
          },
        );
      }
    }

Заключение

Надеюсь, эта статья поможет вам понять основные принципы оптимизации Flutter-приложений и применить их в своей работе. Удачи в создании быстрых и эффективных Flutter-приложений!

Комментарии (4)


  1. ChessMax
    14.08.2024 09:21
    +1

    Используйте compute функцию: эта функция позволяет кэшировать результаты вычислений, чтобы не повторять их при каждом обновлении экрана.

    Функция compute не кэширует результаты.


    1. bagman2020 Автор
      14.08.2024 09:21
      +1

      Спасибо, что указал на ошибку, поправил)


      1. muryk
        14.08.2024 09:21

        Вряд ли достаточно заменить compute на Isolate. Запуск изолята на каждый чих довольно дорогое удовольствие. Лучше иметь один общий изолят для фоновых вычислений и отдавать туда задачи, прямо на сайте флаттера в начальных гайдах есть готовый код


  1. famostik
    14.08.2024 09:21

    Спасибо большое! Статья очень помогла, буду пересматривать свой код теперь…