skip to Main Content

I made a Loader widget which shows a loading indicator if isLoading = true and shows a child widget only if isLoading = false.

The problem is when I use nullable data in the child, even though isLoading = true should prevent the child from being rendered, Flutter still gives me Null check operator used on a null value and a red screen.

Example:

class Example extends StatelessWidget {
  const Example({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    String? data = null; // Just an example

    return Loader(
      isLoading: data == null,
      child: Text(data!), // Flutter will parse this even though Loader never attempted to render it
    );
  }
}

This is my Loader widget:


class Loader extends StatelessWidget {
  const Loader({
    Key? key,
    required this.isLoading,
    required this.child,
  }) : super(key: key);

  final bool isLoading;
  final Widget child;

  @override
  Widget build(BuildContext context) {
    if (isLoading) {
      return CircularProgressIndicator();
    else {
      return child;
    }
  }
}

Note: I want the Loader as a wrapper to clean up my code, because my isLoading, my Loader and the data are much more complicated.

3

Answers


  1. This happened when try to parse the code, even if that part of code not rendered, because dart null safety policy not accept ! on a null value. So this is not the issue in Loader widget, this is inside the child that you try to pass. Try set default value like this:

    return Loader(
      isLoading: data == null,
      child: Text(data ?? ''), //<--- add this
    );
    
    Login or Signup to reply.
  2. You can set a default value to be shown in the Text widget when it’s null using the ?? like this:

      return Loader(
      isLoading: data == null,
      child: Text(data ?? "default data"), 
    );
    
    Login or Signup to reply.
  3. You could refactor your Loader to use a builder instead:

    class Loader extends StatelessWidget {
      const Loader({
        Key? key,
        required this.isLoading,
        required this.builder,
      }) : super(key: key);
    
      final bool isLoading;
      final WidgetBuilder builder;
    
      @override
      Widget build(BuildContext context) {
        if (isLoading) {
          return CircularProgressIndicator();
        } else {
          return builder(context);
        }
      }
    }
    

    Then use it like

    class Example extends StatelessWidget {
      const Example({
        Key? key,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        String? data = null; // Just an example
    
        return Loader(
          isLoading: data == null,
          builder: (_) => Text(data!),
        );
      }
    }
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search