xuelongqy / flutter_easy_refresh

A flutter widget that provides pull-down refresh and pull-up load.
https://xuelongqy.github.io/flutter_easy_refresh/
MIT License
3.84k stars 628 forks source link

_onCanProcess空指针异常 #782

Closed wanggaowan closed 8 months ago

wanggaowan commented 8 months ago

_EasyRefreshState initState初始化数据时,Future中_callRefresh是延迟执行的,会存在_callRefresh还未执行时先执行了dispose()。 而_headerNotifier.dispose()会将_onCanProcess置为null,而IndicatorNotifier 中 bool get _canProcess => _onCanProcess!.call(); 强制不为null。最终执行_callRefresh报空指针异常

// _EasyRefreshState代码

@override
  void initState() {
    super.initState();
    // Refresh on start.
    if (widget.refreshOnStart && widget.onRefresh != null) {
      _isRefreshOnStart = true;
      Future(() {
        _ambiguate(WidgetsBinding.instance)!.addPostFrameCallback((timeStamp) {
          _callRefresh(
            overOffset: widget.callRefreshOverOffset,
            duration: null,
          );
        });
      });
    }
    _initData();
    widget.controller?._bind(this);
  }

@override
  void dispose() {
    _headerNotifier.dispose();
    _footerNotifier.dispose();
    _userOffsetNotifier.dispose();
    super.dispose();
  }

// _callRefresh最终执行的代码
Future callTask({
    required double overOffset,
    Duration? duration,
    Curve curve = Curves.linear,
    ScrollController? scrollController,
    bool force = false,
  }) {
    if (!force) {
      // 就是!_canProcess空指针异常
      if (modeLocked || noMoreLocked || secondaryLocked || !_canProcess) {
        return Future.value();
      }
    } else {
      _offset = 0;
      _mode = IndicatorMode.inactive;
      _processing = false;
    }
    return animateToOffset(
      offset: actualTriggerOffset + overOffset,
      mode: IndicatorMode.ready,
      duration: duration,
      curve: curve,
      scrollController: scrollController,
    );
  }

// IndicatorNotifier代码

// 强制_onCanProcess不会为null
bool get _canProcess => _onCanProcess!.call();

// 但是dispose里会置为null
@override
  void dispose() {
    _onCanProcess = null;
    _clampingAnimationController?.dispose();
    userOffsetNotifier.removeListener(_onUserOffset);
    _task = null;
    _modeChangeListeners.clear();
    _indicator.listenable?._unbind();
    _mounted = false;
    super.dispose();
  }
image
xuelongqy commented 8 months ago

3.3.2+4 已解决