Home > Net >  Flutter null safety migration error Null check operator used on a null value - occured at PageTransf
Flutter null safety migration error Null check operator used on a null value - occured at PageTransf

Time:03-03

I implemented PageView parallax effects in Flutter using github repo page-transformer . After Null safety migration I am facing the error below.

======== Exception caught by widgets library =======================================================
The following _CastError was thrown building PageTransformer(dirty, state: _PageTransformerState#a4851):
Null check operator used on a null value

I am relatively new to Dart and Flutter, and I know very little about ScrollMetrics

Below is the code file of page_transformer.dart

import 'package:flutter/material.dart';
import 'package:meta/meta.dart';

/// A function that builds a [PageView] lazily.
typedef PageView PageViewBuilder(
BuildContext context, PageVisibilityResolver visibilityResolver);

/// A class that can be used to compute visibility information about
/// the current page.
class PageVisibilityResolver {
  PageVisibilityResolver({
    ScrollMetrics? metrics,
    double? viewPortFraction,
  }) : this._pageMetrics = metrics!, //Error here <----- When the exception was thrown, this was the stack: #0 new PageVisibilityResolver
       this._viewPortFraction = viewPortFraction!;

  final ScrollMetrics _pageMetrics;
  final double _viewPortFraction;

  PageVisibility resolvePageVisibility(int pageIndex) {
    final double pagePosition = _calculatePagePosition(pageIndex);
    final double visiblePageFraction =
        _calculateVisiblePageFraction(pageIndex, pagePosition);

    return PageVisibility(
      visibleFraction: visiblePageFraction,
      pagePosition: pagePosition,
    );
  }

  double _calculateVisiblePageFraction(int index, double pagePosition) {
    if (pagePosition > -1.0 && pagePosition <= 1.0) {
      return 1.0 - pagePosition.abs();
    }

    return 0.0;
  }

  double _calculatePagePosition(int index) {
    final double viewPortFraction = _viewPortFraction ?? 1.0;
    final double pageViewWidth =
        (_pageMetrics?.viewportDimension ?? 1.0) * viewPortFraction;
    final double pageX = pageViewWidth * index;
    final double scrollX = (_pageMetrics?.pixels ?? 0.0);
    final double pagePosition = (pageX - scrollX) / pageViewWidth;
    final double safePagePosition = !pagePosition.isNaN ? pagePosition : 0.0;

    if (safePagePosition > 1.0) {
      return 1.0;
    } else if (safePagePosition < -1.0) {
      return -1.0;
    }

    return safePagePosition;
  }
}

 /// A class that contains visibility information about the current page.
  class PageVisibility {
    PageVisibility({
      required this.visibleFraction,
      required this.pagePosition,
    });

  final double visibleFraction;
  final double pagePosition;
}

class PageTransformer extends StatefulWidget {
  PageTransformer({
    required this.pageViewBuilder,
  });

  final PageViewBuilder pageViewBuilder;

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

class _PageTransformerState extends State<PageTransformer> {
  PageVisibilityResolver? _visibilityResolver;

  @override
  Widget build(BuildContext context) {
    final pageView = widget.pageViewBuilder(
        context, _visibilityResolver ?? PageVisibilityResolver());

    final controller = pageView.controller;
    final viewPortFraction = controller.viewportFraction;

    return NotificationListener<ScrollNotification>(
      onNotification: (ScrollNotification notification) {
        setState(() {
          _visibilityResolver = PageVisibilityResolver(
            metrics: notification.metrics,
            viewPortFraction: viewPortFraction,
          );
        });
        return false;     //need a check
      },
      child: pageView,
    );
  }
}

Below is the code file of intro_page_view.dart

import 'dart:math';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:tailor_ai/screens/main/main_page.dart';
import 'package:tailor_ai/screens/product/product_page.dart';
import 'package:flutter/material.dart';
import 'package:tailor_ai/models/product.dart';
import 'page_transformer.dart';
import 'intro_page_item.dart';

class IntroPageView extends StatelessWidget {
  final List<Product>? product;
  final _controller = new PageController(viewportFraction: 0.85);
  static const _kDuration = const Duration(milliseconds: 300);
  static const _kCurve = Curves.ease;
  final _kArrowColor = Colors.black.withOpacity(0.8);
  IntroPageView({Key? key,this.product}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: SizedBox.fromSize(
          size: const Size.fromHeight(500.0),
          child: PageTransformer(         //<-------------- The relevant error-causing widget was: PageTransformer PageTransformer
            pageViewBuilder: (context, visibilityResolver) {
              return PageView.builder(
                controller: _controller,
                itemCount: product!.length,
                itemBuilder: (context, index) {
                  //final item = product;
                  final pageVisibility =
                      visibilityResolver.resolvePageVisibility(index);
                  return InkWell(
                    onTap: () => Navigator.of(context)
                        .push(MaterialPageRoute(builder: (_) => ProductPage(
                        product: product![index]

                    ))),
                    child: Stack(
                      children: <Widget>[
                        IntroPageItem(product: product![index], pageVisibility: pageVisibility),
                      ],
                    ),
                  );
                },
              );
            },
          ),
        ),
      ),
    );
  }
}

you can find the entire code files for page_transformer project in above mentioned github link which is not updated for null safety.

terminal screenshot for reference

Your valuable time in response would be much appreciated.

CodePudding user response:

Here is the problem, you have this variable: final ScrollMetrics _pageMetrics; which is not nullable, on initialization, you assign it to this other variable ScrollMetrics? metrics, which is nullable. The error you get happened because metrics was null and you tried to assign it to _pageMetrics.

So why is metrics null? Well, you are supposed to pass the value of metrics on the constructor, but you didn't on this line:

final pageView = widget.pageViewBuilder(
        context, _visibilityResolver ?? PageVisibilityResolver());

So the solution is to either make _pageMetrics nullable or to pass metrics to the constructor.

Pro tip: When you have a named parameter on your constructor that should always be passed (that is to say, it should never be null) you can use the required keyword:

PageVisibilityResolver({
    required ScrollMetrics metrics,
    required double viewPortFraction,
  }) : this._pageMetrics = metrics, 
       this._viewPortFraction = viewPortFraction;

Of course you could also give them a default value.

  • Related