vintage / scratcher

Scratch card widget which temporarily hides content from user.
https://pub.dev/packages/scratcher
MIT License
572 stars 67 forks source link

if image is null, crash #29

Closed sleepreading closed 3 years ago

sleepreading commented 3 years ago
Scratcher(
  ...
  image: null,  // or do not assign this parameter
)

result:

type 'Null' is not a subtype of type 'FutureOr<Image>' See also: https://flutter.dev/docs/testing/errors

I found the problem code here:

// scratcher-2.0.0/lib/widgets.dart
void initState() {
  if (widget.image == null) {
    final completer = Completer<ui.Image>()..complete();  // <-- here
  }
}

environment:

Flutter 2.0.3 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 4d7946a68d (12 days ago) • 2021-03-18 17:24:33 -0700
Engine • revision 3459eb2436
Tools • Dart 2.12.2

Android Sdk API Verison: 30
Emulator: Pixel XL
vintage commented 3 years ago

@sleepreading Thanks for the report! I couldn't reproduce the issue locally, but got a potential fix for it. Mind to check if it got resolved in version 2.0.1 https://pub.dev/packages/scratcher ?

Proberts commented 3 years ago

Had same issue. Change widgets.dart line (around line number 127) from:

image: snapshot.data

to

image: widget.image == null ? null : snapshot.data,

vintage commented 3 years ago

To solve the issue I would need a reproducible example (gist/repo/snippet). I cannot reproduce the issue by simply passing down image: null https://github.com/vintage/scratcher/blob/master/example/lib/basic.dart#L70

vintage commented 3 years ago

Closing it due to inactivity.

sleepreading commented 3 years ago

@vintage sorry for responsing too late

///
/// https://github.com/vintage/scratcher
///
class ScratcherDemo extends StatefulWidget {
  ScratcherDemo({Key? key}) : super(key: key);

  static const String routeName = "/scratch";
  static const String title = "刮刮卡";
  static const String url = "https://pub.flutter-io.cn/packages/scratcher";

  @override
  _ScratcherDemoState createState() => _ScratcherDemoState();
}

class _ScratcherDemoState extends State<ScratcherDemo> {
  final scratchKey = GlobalKey<ScratcherState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("scratcher"),
        actions: <Widget>[PluginButton(ScratcherDemo.title, ScratcherDemo.url)],
      ),
      body: SingleChildScrollView(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            ListTile(title: Text("默认用法")),
            Center(
              child: Scratcher(
                brushSize: 30,
                threshold: 50,
                color: Colors.grey,
                // image: Image.asset('assets/images/avatar_bk.jpg'),  // <--- comment this line would reproduce the issue
                onChange: (value) {
                  debugPrint("当前刮开比例: $value%");
                },
                onThreshold: () {
                  debugPrint("已触发设置的全部刮开阈值");
                },
                child: Container(
                  height: 300,
                  width: 300,
                  color: Colors.blue,
                ),
              ),
            ),
            Container(
              height: 20.pt,
            ),
            ListTile(title: Text("自定义")),
            Center(
              child: Scratcher(
                key: scratchKey,
                brushSize: 30.pt,
                threshold: 50,
                color: Colors.pink,
                image: Image.asset('assets/images/avatar_bk.jpg'),
                onChange: (value) {
                  debugPrint("当前刮开比例: $value%");
                },
                onThreshold: () {
                  debugPrint("已触发设置的全部刮开阈值");
                  scratchKey.currentState!.reveal(duration: Duration(milliseconds: 500));
                },
                child: Container(
                  width: 300.pt,
                  height: 150.pt,
                  child: ImageUtil.load(
                    'assets/images/avatar.jpg',
                    fit: BoxFit.cover,
                  ),
                ),
              ),
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                RaisedButton(
                  child: Text("重置"),
                  onPressed: () {
                    scratchKey.currentState!.reset();
                  },
                ),
                RaisedButton(
                  child: Text("刮开"),
                  onPressed: () {
                    scratchKey.currentState!.reveal(duration: Duration(milliseconds: 500));
                  },
                )
              ],
            )
          ],
        ),
      ),
    );
  }
}
pcvdheuvel commented 3 years ago

I had the same issue. The _imageLoader has a nullable type but the completer was created without the nullable type. I created a PR which solves this #31

vintage commented 3 years ago

The fix will be included in the next release. In the meantime feel free to use github version :+1:

vintage commented 3 years ago

2.1.0 has been just released https://pub.dev/packages/scratcher