![](/img/trans.png)
[英]Dart Null safety error : Null check operator used on a null value
[英]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.