Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot clone a disposed image #75

Open
raulmabe opened this issue Aug 20, 2021 · 3 comments
Open

Cannot clone a disposed image #75

raulmabe opened this issue Aug 20, 2021 · 3 comments

Comments

@raulmabe
Copy link

raulmabe commented Aug 20, 2021

When using this plugin I get the following error sometimes.

Bad state: Cannot clone a disposed image.
      The clone() method of a previously-disposed Image was called. Once an Image object has been disposed, it can no longer be used to create handles, as the underlying data may have been released.
[log] #0      Image.clone (dart:ui/painting.dart:1758:7)
#1      ImageInfo.clone
package:flutter/…/painting/image_stream.dart:51
#2      ImageStreamCompleter.setImage
package:flutter/…/painting/image_stream.dart:618
#3      _rootRunUnary (dart:async/zone.dart:1362:47)
#4      _CustomZone.runUnary (dart:async/zone.dart:1265:19)
#5      _FutureListener.handleValue (dart:async/future_impl.dart:152:18)
#6      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:704:45)
#7      Future._propagateToListeners (dart:async/future_impl.dart:733:32)

I suspect it's caused by the delay property, as it's trying to screenshot from a widget that has already been disposed...

Plugin version: screenshot: ^1.2.3

Code sample

My whole dart file has a lot of unrelated business logic, so I am only posting the piece of code where I use the plugin.

  @override
  void initState() {
    super.initState();

    // ....

      WidgetsBinding.instance!.addPostFrameCallback((_) async {
        if (mounted) {
          pictureBytes = await screenshotController.captureFromWidget(
            LimitedBox(
              maxHeight: 2000,
              maxWidth: 1000,
              child: PlanImagePreview(
                args: PlanImagePreviewArgs(
                  parentContext: context,
                  plan: widget.plan,
                ),
              ),
            ),
            pixelRatio: context.mediaQuery.devicePixelRatio,
          );

         
        }
      });
  }
PlanPreview.dart
class PlanImagePreviewArgs {
  const PlanImagePreviewArgs({
    required this.parentContext,
    required this.plan,
  });
  final BuildContext parentContext;
  final PlanDTO plan;
}

class PlanImagePreview extends StatelessWidget {
  const PlanImagePreview({
    Key? key,
    required this.args,
  }) : super(key: key);

  static const String routeName = 'plan_preview';

  final PlanImagePreviewArgs args;

  PlanDTO get plan => args.plan;
  double get borderRadius => 16.0;
  double get blur => 10.0;
  BuildContext get parentContext => args.parentContext;

  Shadow get shadowText => const Shadow(
        color: Colors.black45,
        offset: Offset(0.0, 2.0),
        blurRadius: 4.0,
      );

  @override
  Widget build(BuildContext context) {
    final theme = parentContext.read<ThemeCubit>();

    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: AppTheme.getTheme(
        theme: theme.state.theme,
        flavor: Flavors.production,
      ),
      localizationsDelegates: const [
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      builder: (__, child) {
        return MultiBlocProvider(
          providers: [
            BlocProvider.value(value: theme),
          ],
          child: MediaQuery(
            data: parentContext.mediaQuery,
            child: DefaultTextStyle(
              style: parentContext.theme.textTheme.caption!
                  .copyWith(shadows: [shadowText]),
              child: child!,
            ),
          ),
        );
      },
      home: LimitedBox(
        maxHeight: parentContext.screen.height,
        maxWidth: parentContext.screen.width,
        child: AspectRatio(
          aspectRatio: 9 / 16,
          child: Stack(
            fit: StackFit.expand,
            children: [
              Positioned.fill(
                child: Container(
                  decoration: BoxDecoration(
                    image: DecorationImage(
                      image: NetworkImage(plan.pictures!.first.url!),
                      fit: BoxFit.cover,
                    ),
                    borderRadius: BorderRadius.circular(borderRadius),
                  ),
                  child: BackdropFilter(
                    filter: ui.ImageFilter.blur(
                      sigmaX: blur,
                      sigmaY: blur,
                    ),
                    child: Container(
                      color: Colors.black38,
                    ),
                  ),
                ),
              ),
              Positioned.fill(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: [
                    const Spacer(flex: 2),
                    _buildFromSizeFactor(
                      widthFactor: .4,
                      child: const DivenLogo(),
                    ),
                    const Spacer(
                      flex: 3,
                    ),
                    Expanded(
                      flex: 5,
                      child: Transform.scale(
                        scale: .9,
                        child: PlanCard(
                          margin: EdgeInsets.zero,
                          plan: plan,
                          height: 200,
                        ),
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.symmetric(
                          horizontal: 20.0, vertical: 30.0),
                      child: Text(
                        parentContext.l10n.divenSlogan,
                        style:
                            parentContext.theme.textTheme.headline5?.copyWith(
                          color: Colors.white,
                          fontFamily: 'Montserrat',
                          fontStyle: FontStyle.italic,
                          fontWeight: FontWeight.w300,
                          letterSpacing: 2.0,
                          fontSize: 28,
                          shadows: [shadowText],
                        ),
                        textAlign: TextAlign.center,
                      ),
                    ),
                    const Spacer(),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildFromSizeFactor({
    required Widget child,
    double? heightFactor,
    double? widthFactor,
    BoxFit fit = BoxFit.contain,
    Alignment alignment = Alignment.center,
  }) {
    return FractionallySizedBox(
      heightFactor: heightFactor,
      widthFactor: widthFactor,
      child: FittedBox(
        fit: fit,
        alignment: alignment,
        child: child,
      ),
    );
  }
}
@ritheshSalyan
Copy link
Collaborator

@raulmabe Can we get some sample code to test?

@raulmabe
Copy link
Author

raulmabe commented Aug 20, 2021

I updated my post to add sample code, although is incomplete to execute as my code has a lot of unrelated business logic and can't take time now to refactor it

@raulmabe
Copy link
Author

I am also getting this error when navigating across pages:


'package:flutter/src/painting/image_stream.dart': Failed assertion: line 122 pos 12: '(image.debugGetOpenHandleStackTraces()?.length ?? 1) > 0': is not true.


#0      _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:46:39)
#1      _AssertionError._throwNew (dart:core-patch/errors_patch.dart:36:5)
#2      ImageInfo.dispose (package:flutter/src/painting/image_stream.dart:122:12)
#3      ImageStreamCompleter._maybeDispose (package:flutter/src/painting/image_stream.dart:576:20)
#4      ImageStreamCompleterHandle.dispose (package:flutter/src/painting/image_stream.dart:447:17)
#5      _CachedImageBase.dispose.<anonymous closure> (package:flutter/src/painting/image_cache.dart:627:15)
#6      SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1144:15)
#7      SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1090:9)
#8      SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:998:5)
#9      _rootRun (dart:async/zone.dart:1354:13)
#10     _CustomZone.run (dart:async/zone.dart:1258:19)
#11     _CustomZone.runGuarded (dart:async/zone.dart:1162:7)
#12     _invoke (dart:ui/hooks.dart:163:10)
#13     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:259:5)
#14     _drawFrame (dart:ui/hooks.dart:126:31)

#0      new Image._.<anonymous closure> (dart:ui/painting.dart:1647:32)
#1      new Image._ (dart:ui/painting.dart:1649:6)
#2      Codec.getNextFrame.<anonymous closure> (dart:ui/painting.dart:1994:24)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants