Christian
Christian

Reputation: 1058

How to optimize SingleChildRenderObjectWidget for repeated use?

So I was looking for a way to create inner shadows and found this code.

It's exactly what I need in terms of looks but I have up to 40 widgets wrapped with this at a time which has a massive performance cost. (10 fps in release mode).

This is the desired look: enter image description here

So my question is: Is it possible to make this as efficient as a normal BoxShadow?

class InnerShadow extends SingleChildRenderObjectWidget {
  const InnerShadow({
    Key key,
    this.shadows = const <Shadow>[],
    Widget child,
  }) : super(key: key, child: child);

  final List<Shadow> shadows;

  @override
  RenderObject createRenderObject(BuildContext context) {
    final renderObject = _RenderInnerShadow();
    updateRenderObject(context, renderObject);
    return renderObject;
  }

  @override
  void updateRenderObject(
      BuildContext context, _RenderInnerShadow renderObject) {
    renderObject.shadows = shadows;
  }
}

class _RenderInnerShadow extends RenderProxyBox {
  List<Shadow> shadows;

  @override
  void paint(PaintingContext context, Offset offset) {
    if (child == null) return;
    final bounds = offset & size;

    context.canvas.saveLayer(bounds, Paint());
    context.paintChild(child, offset);

    for (final shadow in shadows) {
      final shadowRect = bounds.inflate(shadow.blurSigma);
      final shadowPaint = Paint()
        ..blendMode = BlendMode.srcATop
        ..colorFilter = ColorFilter.mode(shadow.color, BlendMode.srcOut)
        ..imageFilter = ImageFilter.blur(
            sigmaX: shadow.blurSigma, sigmaY: shadow.blurSigma);
      context.canvas
        ..saveLayer(shadowRect, shadowPaint)
        ..translate(shadow.offset.dx, shadow.offset.dy);
      context.paintChild(child, offset);
      context.canvas.restore();
    }

    context.canvas.restore();
  }
}

Upvotes: 0

Views: 1355

Answers (1)

Karim
Karim

Reputation: 1010

Use unique identifiers as keys Example

key:Key('SomeKey') or key:Key(SomeObject.id)

Upvotes: 1

Related Questions