繁体   English   中英

Flutter null 安全迁移错误 Null 检查在 null 值上使用的运算符 - 发生在 PageTransformer ScrollMetrics object

[英]Flutter null safety migration error Null check operator used on a null value - occured at PageTransformer ScrollMetrics object

我在 Flutter 中使用 github repo page-transformer实现了 PageView 视差效果。 Null 安全迁移后,我面临以下错误。

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

我对Dart和Flutter比较陌生,对ScrollMetrics知之甚少

下面是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,
    );
  }
}

下面是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),
                      ],
                    ),
                  );
                },
              );
            },
          ),
        ),
      ),
    );
  }
}

您可以在上面提到的 github 链接中找到 page_transformer 项目的完整代码文件,该链接未针对 null 安全进行更新。

终端截图供参考

非常感谢您宝贵的回复时间。

这是问题所在,您有这个变量: final ScrollMetrics _pageMetrics; 不是可空的,在初始化时,您将它分配给另一个变量ScrollMetrics? metrics ScrollMetrics? metrics ,可以为空 你得到的错误发生是因为metrics是 null 并且你试图将它分配给_pageMetrics

那么为什么metrics是null呢? 好吧,你应该在构造函数上传递指标的值,但你没有在这一行:

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

因此解决方案是使_pageMetrics可以为空或将metrics传递给构造函数。

专业提示:当您的构造函数上有一个应始终传递的命名参数时(也就是说,它永远不应该是 null ),您可以使用required关键字:

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

当然你也可以给它们一个默认值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM