Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug report] Looking up a deactivated widget's ancestor is unsafe. #52

Open
Rock-chan opened this issue Jul 31, 2023 · 26 comments
Open

Comments

@Rock-chan
Copy link

Version

4.1.2

Platforms

dart, Android, iOS

Device Model

iPhone X iOS16

flutter info

admin@admindeMacBook-Pro app % flutter doctor -v
[!] Flutter (Channel stable, 3.10.5, on macOS 12.6.6 21G646 darwin-x64, locale zh-Hans-CN)
    • Flutter version 3.10.5 on channel stable at /Users/admin/development/flutter
    ! Warning: `dart` on your path resolves to /usr/local/Cellar/dart/3.0.4/libexec/bin/dart, which is not inside your current Flutter SDK checkout at
      /Users/admin/development/flutter. Consider adding /Users/admin/development/flutter/bin to the front of your path.
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 796c8ef792 (7 weeks ago), 2023-06-13 15:51:02 -0700
    • Engine revision 45f6e00911
    • Dart version 3.0.5
    • DevTools version 2.23.1
    • Pub download mirror https://pub.flutter-io.cn
    • Flutter download mirror https://storage.flutter-io.cn
    • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades.

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.2)
    • Android SDK at /Users/admin/Library/Android/sdk
    • Platform android-33, build-tools 33.0.2
    • ANDROID_HOME = /Users/admin/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.2)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14C18
    • CocoaPods version 1.12.1

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2022.2)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)

[✓] VS Code (version 1.79.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.68.0

[✓] Connected device (3 available)
    • iPhone (4) (mobile) • 00008020-001C589A2203002E • ios            • iOS 16.3.1 20D67
    • macOS (desktop)     • macos                     • darwin-x64     • macOS 12.6.6 21G646 darwin-x64
    • Chrome (web)        • chrome                    • web-javascript • Google Chrome 115.0.5790.114

[!] Network resources             
    ✗ A network error occurred while checking "https://github.com/": Operation timed out

! Doctor found issues in 2 categories.

How to reproduce?

1、When you first go to the page which you use the widget, sometime it will show the error.
2、When you refresh your list, before the data getting, you hold the screen and then you will receive the error.

Logs

I/flutter ( 9284): Caught error: Looking up a deactivated widget's ancestor is unsafe.
I/flutter ( 9284): At this point the state of the widget's element tree is no longer stable.
I/flutter ( 9284): To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.
I/flutter ( 9284): Stack trace:
I/flutter ( 9284): package:flutter/src/widgets/framework.dart 4347:9 Element._debugCheckStateIsActiveForAncestorLookup.<fn>
I/flutter ( 9284): package:flutter/src/widgets/framework.dart 4361:6 Element._debugCheckStateIsActiveForAncestorLookup
I/flutter ( 9284): package:flutter/src/widgets/framework.dart 4396:12 Element.getElementForInheritedWidgetOfExactType
I/flutter ( 9284): package:flutter/src/widgets/inherited_model.dart 143:45 InheritedModel._findModels
I/flutter ( 9284): package:flutter/src/widgets/inherited_model.dart 191:5 InheritedModel.inheritFrom
I/flutter ( 9284): package:flutter/src/widgets/media_query.dart 1058:27 MediaQuery._maybeOf
I/flutter ( 9284): package:flutter/src/widgets/media_query.dart 1101:67 MediaQuery.maybeDevicePixelRatioOf
I/flutter ( 9284): package:flutter/src/widgets/scroll_position.dart 244:45 ScrollPosition.devicePixelRatio
I/flutter ( 9284): package:flutter/src/widgets/

Example code (optional)

No response

Contact

[email protected]

@zmtzawqlp
Copy link
Member

把你写的loaddata 代码发出来

@Rock-chan
Copy link
Author

WechatIMG70

@Rock-chan
Copy link
Author

71_1690799163.mp4

@Rock-chan
Copy link
Author

Rock-chan commented Jul 31, 2023

`import 'package:loading_more_list/loading_more_list.dart';

typedef LoadDataCallBack<C> = Future<C> Function(int offset);

typedef OnDataChangeListener<C> = void Function(List<C> data);

///
/// 数据源基类 封装上下拉刷新逻辑
///
class CustomLoadingMoreBase<T> extends LoadingMoreBase<T> {
  CustomLoadingMoreBase({required this.loadDataCallBack, this.pageSize = 10, this.onDataChangeListener});

  /// 加载数据的回调方法
  LoadDataCallBack loadDataCallBack;

  /// 数据变化的回调
  OnDataChangeListener? onDataChangeListener;

  /// 默认第一页
  int _offset = 1;

  /// 是否还有更多数据
  bool _hasMore = true;

  /// 默认一页10条数据
  int pageSize;

  @override
  bool get hasMore => _hasMore;

  @override
  Future<bool> refresh([bool clearBeforeRequest = false]) async {
    print('CustomLoadingMoreBase clearBeforeRequest=$clearBeforeRequest');
    _offset = 0;
    _hasMore = true;
    return super.refresh(clearBeforeRequest);
  }

  @override
  Future<bool> loadData([bool isloadMoreAction = false]) async {
    print('CustomLoadingMoreBase isloadMoreAction=$isloadMoreAction');
    bool isSuccess = false;
    bool hasError = false;
    var newOffset = _offset + 1;

    /// 集合数据
    List? list;
    try {
      var listData = await loadDataCallBack(newOffset);
      if (newOffset == 1) {
        clear();
      }

      /// 如果listData本身就是一个集合
      if (listData is List) {
        list = listData;
      } else {
        /// 否则看下集合数据是不是在dataList或logList字段里面
        late bool isInDataList, isInLogList;
        try {
          isInDataList = (listData?.dataList?.length ?? 0) > 0;
        } catch (e) {
          print('CustomLoadingMoreBase: is not InDataList');
        }

        if (isInDataList == true) {
          list = listData.dataList;
        } else {
          try {
            isInLogList = (listData?.logList?.length ?? 0) > 0;
          } catch (e) {
            print('CustomLoadingMoreBase: is not InLogList');
          }
          if (isInLogList == true) {
            list = listData.logList;
          }
        }
      }

      /// 操作集合数据
      if (list is List) {
        for (var item in list) {
          add(item);
        }
        _offset = newOffset;
        _hasMore = list.length >= pageSize;
      } else {
        _hasMore = false;
      }

      isSuccess = true;
    } catch (exception, stack) {
      hasError = true;
      print(exception);
      print(stack);
    }
    if (onDataChangeListener != null) {
      onDataChangeListener!(list ?? []);
    }
    return isloadMoreAction ? isSuccess : !hasError;
  }
}`

@zmtzawqlp
Copy link
Member

有没有能运行的最小的demo

@Rock-chan
Copy link
Author

@zmtzawqlp
Copy link
Member

截屏2023-08-01 11 41 26 没有重现你说的问题

When you refresh your list, before the data getting, you hold the screen and then you will receive the error. 你说的这个case 并没有在demo 中有所体现呢?

@chenyeju
Copy link

chenyeju commented Aug 1, 2023

试了下好像能复现,在首次加载页面数据的时候点住并向上滑动持续点住屏幕就会出现,只有首次构建该页面时操作才出现image

@Rock-chan
Copy link
Author

对的,应该就是每一次构建这个组件的时候,当数据还未加载完毕时,然后点住上滑就发生报错

@zmtzawqlp
Copy link
Member

重现不了,你再怎么拉,内部 有 isloading 属性,不会重复去请求的。请提供一个能够重现现象的 demo

@chenyeju
Copy link

chenyeju commented Aug 1, 2023

他这个就可以呀,我版本是 3.10.6 。进入时按住屏幕慢慢滑动就会复现了

@Rock-chan
Copy link
Author

大佬怎么样,复现出来了吗?

@zmtzawqlp
Copy link
Member

没有

@Rock-chan
Copy link
Author

7_1691394508.mp4

flutter版本3.10.6,你给的demo中complex->nestedScrollView这个demo中,tab2这个页面你在加载的时候就去上下滑动页面,就可以看到报错了。

@zmtzawqlp
Copy link
Member

QQ20230807-165259-HD.mp4

@chenyeju
Copy link

chenyeju commented Aug 8, 2023

2023-08-08.16.14.09.mov

复现+1

@zmtzawqlp
Copy link
Member

看起来更像是 NestedScrollView 的问题,之前老的flutter 版本会有这个问题吗?

@Rock-chan
Copy link
Author

3.3.9的版本没有这个问题,您可以试一下升到3.10.5,应该会有这个报错的

@zmtzawqlp
Copy link
Member

官方重现代码

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

void main() {
  runApp(MaterialApp(
    home: RefreshList(),
  ));
}

class RefreshList extends StatefulWidget {
  @override
  State<RefreshList> createState() => _RefreshListState();
}

class _RefreshListState extends State<RefreshList> {
  bool _isLoading = true;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    Future<void>.delayed(Duration(seconds: 2)).whenComplete(() {
      setState(() {
        _isLoading = false;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('RefreshList'),
      ),
      // AppBar
      body: NestedScrollView(
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            return [
              const SliverToBoxAdapter(
                child: SizedBox(
                  height: 90.0,
                ),
              ),
            ];
          },
          body: _isLoading
              ? CustomScrollView(
                  physics: AlwaysScrollableScrollPhysics(),
                  slivers: <Widget>[
                    SliverFillRemaining(
                      child: Center(
                          child: Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        crossAxisAlignment: CrossAxisAlignment.center,
                        children: <Widget>[
                          Container(
                            margin: const EdgeInsets.only(right: 0.0),
                            height: 30.0,
                            width: 30.0,
                            child: getIndicator(context),
                          ),
                          Text('loading...')
                        ],
                      )),
                    ),
                  ],
                )
              : ListView.builder(itemBuilder: (b, index) {
                  return Container(
                    child: Text('$index'),
                  );
                })),
    );
  }

  Widget getIndicator(BuildContext context) {
    final ThemeData theme = Theme.of(context);
    return theme.platform == TargetPlatform.iOS
        ? const CupertinoActivityIndicator(
            animating: true,
            radius: 16.0,
          )
        : CircularProgressIndicator(
            strokeWidth: 2.0,
            valueColor: AlwaysStoppedAnimation<Color>(theme.primaryColor),
          );
  }
}

@zmtzawqlp
Copy link
Member

官方issue追踪: flutter/flutter#132190

@Rock-chan
Copy link
Author

好的,感谢指出问题所在

@RockChen0321
Copy link

3.3.9的版本没有这个问题,您可以试一下升到3.10.5,应该会有这个报错的

大佬我用了你的demo去降级排查了一下,发现3.3.9以及2.10.5都会出现这个问题,所以具体哪个版本出问题我也不知道了

@zmtzawqlp
Copy link
Member

3.3.9的版本没有这个问题,您可以试一下升到3.10.5,应该会有这个报错的

大佬我用了你的demo去降级排查了一下,发现3.3.9以及2.10.5都会出现这个问题,所以具体哪个版本出问题我也不知道了

还是官方的锅吧。建议你们把 physics 改成 安卓的那个就没事。。我一直都用的安卓的

@zmtzawqlp
Copy link
Member

官方说下一个stable修复了。到时候大家再看看这个问题吧。有问题我再跟官方report

@Rock-chan
Copy link
Author

嗯嗯好的

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants