0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

フレームレートとは?

Posted at

60fps, 120fpsというワードを知らない 

昔のFlutterの本を読んでいて、アニメーションがスムーズでなかったり、反応が遅かったりする話題が気になりました。
UIのパフォーマンスを見る際に重要なのが、フレームレートなるものだそうです。フレームレートとは、1秒間に見せるフレームの数です。  
パラパラ漫画をイメージするとわかりやすいそうです。

参考になりそうな情報:
https://app-best.jp/articles/description_fps/

Flutter公式の情報

学習内容 Flutter は、1 秒あたり 60 フレーム (fps) のパフォーマンス、または 120 Hz 更新が可能なデバイスで 120 fps のパフォーマンスを提供することを目指しています。60 fps の場合、フレームは約 16 ミリ秒ごとにレンダリングする必要があります。UI がスムーズにレンダリングされないと、ジャンクが発生します。たとえば、時々、フレームのレンダリングに 10 倍の時間がかかるため、フレームがドロップされ、アニメーションが目に見えてぎくしゃくします。

Flutter フレームワークは、60fps でスムーズでないアプリケーションを作成しにくいように設計されています。多くの場合、ジャンクが発生するのは、単純なバグが原因で、フレームごとに必要以上に UI が再構築されるためです。ウィジェット再構築プロファイラーは、このような種類のバグによるパフォーマンスの問題をデバッグして修正するのに役立ちます。

こんなコードを書くとパフォーマンスが下がるかも?

import 'package:flutter/material.dart';
import 'dart:math' as math;

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

enum ColorSchemeType {
  light,
  dark,
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
  // lateをAnimationControllerにつけると、初期化を遅らせることができる。..repeat()で繰り返しアニメーションを行う。
  late final AnimationController _controller = AnimationController(
    duration: const Duration(seconds: 10),
    vsync: this,
  )..repeat();

  // AnimationControllerを破棄する必要があるので、dispose()をオーバーライドする。
  // @override
  // void dispose() {
  //   _controller.dispose();
  //   super.dispose();
  // }

  int _counter = 0;
  ColorSchemeType _colorSchemeType = ColorSchemeType.light;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  void _toggleTheme() {
    setState(() {
      _colorSchemeType = _colorSchemeType == ColorSchemeType.light
          ? ColorSchemeType.dark
          : ColorSchemeType.light;
    });
  }

  @override
  Widget build(BuildContext context) {
    final isLightTheme = _colorSchemeType == ColorSchemeType.light;
    final theme = ThemeData(
      brightness: isLightTheme ? Brightness.light : Brightness.dark,
      colorScheme: isLightTheme
          ? ColorScheme.fromSeed(seedColor: Colors.deepPurple)
          : const ColorScheme.dark(),
      useMaterial3: true,
    );

    return MaterialApp(
      title: 'Flutter Demo',
      theme: theme,
      home: Scaffold(
        appBar: AppBar(
          actions: [
            IconButton(
              icon: Icon(isLightTheme ? Icons.dark_mode : Icons.light_mode),
              onPressed: _toggleTheme,
            ),
          ],
          backgroundColor: theme.colorScheme.inversePrimary,
          title: Text(widget.title),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              const Text(
                'You have pushed the button this many times:',
              ),
              Text(
                '$_counter',
                style: theme.textTheme.headlineMedium,
              ),
              Center(
                child: AnimatedBuilder(
                  animation: _controller, // AnimationControllerを渡す。
                  child: Container(
                    width: 200.0,
                    height: 200.0,
                    color: Colors.green,
                    child: const Center(
                      child: Text('くるくる回っちゃうもんね〜'),
                    ),
                  ),
                  builder: (BuildContext context, Widget? child) {
                    // Transform.rotateで回転させる。
                    return Transform.rotate(
                      angle: _controller.value * 2.0 * math.pi,
                      child: child,
                    );
                  },
                ),
              ),
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: _incrementCounter,
          tooltip: 'Increment',
          child: const Icon(Icons.add),
        ),
      ),
    );
  }
}

何度も赤い棒線が出てきた、ジャンクが多いことになります。 一瞬で消えたので、スクリーンショットに撮れませんでした💦

最後に

今回は、Flutterのフレームレートについてお勉強してみました。Flutterにはパフォーマンスを良くするために、推奨する方法があるようなので、それに従いましょう。

学習内容 Flutter は、1 秒あたり 60 フレーム (fps) のパフォーマンス、または 120 Hz 更新が可能なデバイスで 120 fps のパフォーマンスを提供することを目指しています。60 fps の場合、フレームは約 16 ミリ秒ごとにレンダリングする必要があります。UI がスムーズにレンダリングされないと、ジャンクが発生します。たとえば、時々、フレームのレンダリングに 10 倍の時間がかかるため、フレームがドロップされ、アニメーションが目に見えてぎくしゃくします。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?