Giter VIP home page Giter VIP logo

warmup_routine's Introduction

Update:

Don't use this. The iOS jank issue relating to shader warmup is now largely mitigated by shader pre-compilation as described here. Huge thanks to the Flutter team!

warmup_routine

A library for handling animation warmup generically as discussed in: flutter/flutter#76180

This solution is not very scalable for applications with many animations to warm up and is meant mostly as an example of an approach applications could take to warmup their animations until a more permanent solution is available.

Usage

Warmup overlay

The most common way to warmup animations is to use a pseudo splash screen that executes the animations while the application is starting up.

import 'package:warmup_routine/warmup_overlay.dart';
import 'package:warmup_routine/warmup_animation.dart';

// Example of showing an overlay under which the animations are executing.
class WarmupOverlayExample extends StatefulWidget {
  _WarmupOverlayExampleState createState() => _WarmupOverlayExampleState();
}

class _WarmupOverlayExampleState extends State<WarmupOverlayExample> {
  bool _shouldShowOverlay = true;

  @override
  Widget build(BuildContext context) {
    if (_shouldShowOverlay) {
      return WarmupOverlay(
        onComplete: () {
          setState(() {
            _shouldShowOverlay = false;
          });
        },
        builder: (context) {
          return Container(
            child: Center(
              child: CircularProgressIndicator(),
            ),
          );
        },
        animations: [
          WarmupAnimation(
            builder: (context, complete) {
              // Replace with your animation of choice
              return OpenContainerAnimation(onComplete: complete);
            },
            repeat: 4,
          ),
        ],
      );
    }
  } else {
    // Start rest of application
    MyApp();
  }
}

Warmup routine

If an overlay is not desired, a warmup routine can be executed anywhere in your existing directly:

class WarmupRoutineExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return WarmupRoutine(
      animations: [
        WarmupAnimation(
          builder: (context, complete) {
            // Replace with your animation of choice
            return OpenContainerAnimation(onComplete: complete);
          },
          repeat: 4,
        ),
      ],
      onComplete: () {
        // Start rest of application
      },
    );
  }
}

Navigator example

// The overlay will remain on top of the application above navigation events, so Navigator.push/pop
// can be warmed up as well:

class NavigationWarmupScreen extends StatefulWidget {
  final Function onComplete;

  NavigationWarmupScreen({@required this.onComplete});

  _NavigationWarmupScreenState createState() => _NavigationWarmupScreenState();
}

class _NavigationWarmupScreenState extends State<NavigationWarmupScreen> {
  initState() {
    super.initState();

    WidgetsBinding.instance.addPostFrameCallback((_) {
      Navigator.push(
        context,
        MaterialPageRoute(
          builder: (BuildContext context) {
            return YourWidget();
          },
          fullscreenDialog: true,
        ),
      );

      Future.delayed(
        // Adjust duration as needed
        Duration(milliseconds: 400),
        () {
          Navigator.pop(context);
          Future.delayed(
            Duration(milliseconds: 400),
            () {
              widget.onComplete();
            },
          );
        },
      );
    });
  }

  @override
  build(context) {
    return Container();
  }
}

class WarmupOverlayNavigationExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return WarmupOverlay(
      onComplete: () {
        // Start rest of application
      },
      builder: (context) {
        return Container(
          child: Center(
            child: CircularProgressIndicator(),
          ),
        );
      },
      animations: [
        WarmupAnimation(
          builder: (context, complete) {
            return NavigationWarmupScreen(onComplete: complete);
          },
          repeat: 2,
        ),
      ],
    );
  }
}

Full examples in GitHub repo

warmup_routine's People

Contributors

danreynolds avatar

Stargazers

Dooee avatar Danah avatar  avatar  avatar  avatar Emre ŞURK avatar Shawn avatar Lord Norlan Mumar avatar  avatar Stephen Akinyemi avatar Guillaume Balas avatar  avatar Alex Sant'Anna avatar Roc Boronat avatar Alex Maslov avatar  avatar  avatar Ali Haq avatar  avatar  avatar ibrahim alazzawi avatar Jeremy Whiteley avatar DCnative avatar Jérémie Yardin avatar Joe Robertson avatar Davide Dessì avatar Simone Campitelli avatar  avatar Byron Jones avatar Mykhailo Konovalov avatar Piotr Krawczyk avatar kartik garasia avatar Systrom avatar Andrew Coutts avatar Francesco Iapicca avatar Cícero Santos avatar  avatar  avatar Hady Saleh avatar David Chen avatar Liber Da Silva avatar Ali Akhtar avatar

Watchers

James Cloos avatar  avatar  avatar Liber Da Silva avatar  avatar Davide Dessì avatar  avatar

warmup_routine's Issues

Support null safety

This is a request to add support for null safety to package:warmup_routine

God bless you - where do I make start the App

First of all thank you for saving us all and making it so easy.

I have a question, I'm using your example to test the Open Container and returning the rest of my app inside the "onComplete" function, but I'm still seeing the blue container overlaying on top of my app. I'm sure that the problem is on my end and I'm doing something wrong. I know that you're making a new example so I'll wait for that and see if I can find my error there or I'll wait for your answer if you'll respond.

Anyway thank you so much again, you're saving us from many struggles

A couple of interesting findings

Hi,
thank you for the amazing preliminary work in tackling this issue with this workaround.

I have a couple of hints to share with you regarding the best approach to perform the warmup routine as fast and efficiently as possible:

  1. The animations can be stacked, you don't need to play them sequentially. Even more I've discovered that you can also stack the same animation twice o three times with a little delay between them in order to maximize the chance of hitting all the frames and thus all the needed frames.
  2. You can place the warmup overlays below all the other visible overlays, as long as you create the OverlayEntry with maintainsState = true.
  3. if you instead apply a transform that moves your overlay entry outside the screen, the shaders will be optimized away.
  4. You can actually execute all the routine inside a completely separate engine. The interesting thing is that this enables you to keep the "real" flutter view that you are displaying completely responsive even during this animation dance. Below some example code to possibily launch early inside the appdelegate:
    let engine = FlutterEngine(name: "warmup")
    engine.run(withEntrypoint: "warmup")
    let warmupController = FlutterViewController(engine: engine, nibName: nil, bundle: nil)

    
    let rootBounds = controller.view.bounds
    warmupController.view.frame = rootBounds.applying(.init(translationX: rootBounds.width, y: 0))
    controller.addChild(warmupController)
    controller.view.addSubview(warmupController.view)
    warmupController.didMove(toParent: controller)
    
    DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(15)) {
      warmupController.willMove(toParent: nil)
      warmupController.view.removeFromSuperview()
      warmupController.removeFromParent()
    }

Example for navigator animation

Thanks for this package! It would be great if you could add more examples.

I'm especially interested in the preloading of the default navigator animation.

Does the animations array work?

On WarmupOverlay, there exists a prop called animations, which is an array. Just wondering if that means that we can pass multiple animations to that array and they are run sequentially/in parallel?

I can't seem to get it to work.

I think this is handled on warmup_routine.dart, where I see the following:

class _WarmupAnimationState extends State<WarmupRoutine> {
  int _animationIndex = 0;

  _onWarmupAnimationComplete() {
    if (_animationIndex < widget.animations.length - 2) {
      setState(() {
        _animationIndex += 1;
      });
    } else {
      widget.onComplete();
    }
  }

  @override
  build(context) {
    return WarmupAnimationData(
      onComplete: _onWarmupAnimationComplete,
      child: widget.animations[_animationIndex],
    );
  }
}

I dont understand this line, however if (_animationIndex < widget.animations.length - 2) { ?

Am I missing something?

Thanks for the package, btw!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.