precache static method

Future<void> precache({
  1. bool group = true,
  2. bool ripple = true,
})

Compiles the package's shaders now, so that the first glass on screen is drawn through its optics rather than without them.

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await GlassHost.precache();
  runApp(const MyApp());
}

What it changes. A host otherwise starts compiling in its initState — FragmentProgram.fromAsset is a future — and until a program lands, the glass that needs it draws a stand-in:

  • a surface with a proxy and no surface program draws the captured, blurred backdrop clipped to its shape: no tint, no rim, no bend (RenderGlassSurface.paintsWithOptics counts the difference). A faded surface, such as a soft GlassScrollEdge, draws nothing;
  • a fused GlassGroup with no group program draws nothing at all, and its members leave their glass to it;
  • a touched surface under a GlassRipple with no ripple program draws the surface program, which is the picture without the wave.

The content on the glass — a bar's title, a button's icon — is drawn in every case. Once this future completes, every host mounted afterwards finds the programs in the cache and hands them to its surfaces in its initState, before its first frame.

What it does not change. A capture reads the frame that was just painted, so the very first frame of a host has no proxy and its glass draws only its content, precached or not; the first frame that has a proxy is the one this makes glass. The lower rungs (GlassTier.cheap, GlassTier.opaque) read no program and do not need it.

Shares the loads a host starts on its own, so it is idempotent, costs nothing once the programs are in, and never compiles one twice — called after a host has mounted, it waits for the load already in flight. group and ripple leave out the blend group's program and the ripple's, for an application that uses neither; every host still loads the group program itself when it mounts. Completes with a load's error if one fails.

Note: the shaders are declared in this package's own pubspec, so an application adds nothing to its flutter: shaders: for them.

See also:

Implementation

static Future<void> precache({bool group = true, bool ripple = true}) async {
  // What is cached is not waited on: the load that filled it is done, and
  // its future belongs to the zone that started it — in a widget test, the
  // fake clock of a test that may have ended, which nothing flushes again.
  await Future.wait(<Future<ui.FragmentProgram>>[
    if (_GlassHostState._cachedProgram == null) _GlassHostState._loadBase(),
    if (group && _GlassHostState._cachedGroupProgram == null) _GlassHostState._loadGroup(),
    if (ripple && GlassProxyHandle._cachedRippleProgram == null) GlassProxyHandle._loadRipple(),
  ]);
}