首页 > 解决方案 > 使用 Navigator 时,如何解决在 null 上调用了“ancestorStateOfType”方法?

问题描述

我正在使用 firebase_dynamic_links: ^0.5.0 在我的颤振应用程序中实现设置密码功能。当管理员创建用户时,用户会收到一封电子邮件。在这封电子邮件中有一个动态链接。点击它后,如果他/她没有应用程序,用户将被重定向到 1.App 商店/Play 商店。2.如果应用程序已经安装,在应用程序中打开设置密码屏幕。firebase_dynamic_links 提供了两种方法:- 1.getInitialLink 未来检索打开应用程序的链接。2.onLink 一个回调来监听应用程序处于活动状态或后台时打开的链接。

当应用程序处于终止状态并按下链接时一切顺利,但是当应用程序处于后台时,导航不起作用。

void main() => runApp(MaterialApp(
    theme: new ThemeData(
      primaryColor: Colours.appThemeColour,
    ),
    onGenerateRoute: (RouteSettings settings) {
      switch (settings.name) {
        case '/': return new MyCustomRoute(
          builder: (_) => new SplashScreen(),
          settings: settings,
        );
        case '/setpassword': return new MyCustomRoute(
          builder: (_) => new SetPassword(settings.arguments),
          settings: settings,
        );
     ...


      }
    }
)
);

class SplashScreen extends StatefulWidget {

  @override
  _SplashScreenState createState() => new _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
Uri deepLink;


  _handleDeepLink(Uri deepLink) async{
    if (deepLink != null) {
      print("querParam=${deepLink.queryParameters["token"]}");
      if(deepLink.queryParameters["otp"].toString()=="1"){
        if(deepLink.queryParameters["token"]!=null){
          String _status =await _networkUtil.verifyUser(deepLink.queryParameters["token"].toString());
            Navigator.of(context).pushReplacementNamed('/setpassword',arguments: _status );


        }else{
          Navigator.of(context).pushReplacementNamed('/setpassword',arguments: "unknownError" );
        }
      }
      else{
        if(deepLink.queryParameters["token"]!=null){
          String _status =await _networkUtil.verifyUser(deepLink.queryParameters["token"].toString());
          SchedulerBinding.instance.addPostFrameCallback((_) {
            Navigator.of(context).pushReplacementNamed('/resetpassword');
          });
        }else{
          Navigator.of(context).pushReplacementNamed('/resetpassword');
        }
      }

    }
  }
}
  initDynamicLinks() async {

    final PendingDynamicLinkData data = await FirebaseDynamicLinks.instance.getInitialLink();
    final Uri deepLink = data?.link;

    if (deepLink != null) {
      _handleDeepLink(deepLink);

    }

    FirebaseDynamicLinks.instance.onLink(
        onSuccess: (PendingDynamicLinkData dynamicLink) async {
          final Uri deepLink = dynamicLink?.link;
          _handleDeepLink(deepLink);

        },
        onError: (OnLinkErrorException e) async {
          print('onLinkError');
          print(e.message);
        }
    );
  }
@override
initState(){
initDynamicLinks().then((){
...

});
}


当应用程序在后台并单击链接时,它应该导航到设置密码屏幕,但它(通过我在下面提到的一个例外)进入当应用程序移动到后台时打开的那个屏幕。

D/ViewRootImpl@5c26021MainActivity:MSG_WINDOW_FOCUS_CHANGED 0 D/SurfaceView(25703):Relayout 返回:oldFrame=[0,0][1440,2560] newFrame=[0,0][1440,2560] result=0x5 surface={Surface( name=null)/@0x54b5e07 isValid=false 0} D/ViewRootImpl@5c26021MainActivity:mHardwareRenderer.destroy()#1 D/ViewRootImpl@5c26021MainActivity:Relayout 返回:oldFrame=[0,0][1440,2560] newFrame=[0 ,0][1440,2560] result=0x5 surface={isValid=false 0} surfaceGenerationChanged=true D/InputTransport(25703): 输入通道被破坏: fd=92 D/ViewRootImpl@5c26021MainActivity: mHardwareRenderer.destroy()#1 D /ViewRootImpl@5c26021MainActivity:Relayout 返回:oldFrame=[0,0][1440,2560] newFrame=[0,0][1440,2560] result=0x1 surface={isValid=false 0} surfaceGenerationChanged=false D/ViewRootImpl@ 5c26021MainActivity:mHardwareRenderer。destroy()#1 D/ViewRootImpl@5c26021MainActivity:Relayout 返回:oldFrame=[0,0][1440,2560] newFrame=[0,0][1440,2560] result=0x1 surface={isValid=false 0} surfaceGenerationChanged =false D/SurfaceView(25703): Relayout 返回: oldFrame=[0,0][1440,2560] newFrame=[0,0][1440,2560] result=0x7 surface={Surface(name=null)/@ 0x54b5e07 isValid=true 543154356736} D/mali_winsys(25703): EGLint new_window_surface(egl_winsys_display*, void*, EGLSurface, EGLConfig, egl_winsys_surface**, egl_color_buffer_format*, EGLBolean) 返回 0x3000, [1440x2560]-3:1/70 格式): querParam=e144efdbd666e615a47ebe18e25a556d D/ViewRootImpl@5c26021MainActivity: Relayout 返回: oldFrame=[0,0][1440,2560] newFrame=[0,0][1440,2560] result=0x7 surface={isValid=true 542519654912} surfaceGeneration =true D/ViewRootImpl@5c26021MainActivity:mHardwareRenderer。initialize() mSurface={isValid=true 542519654912} hwInitialized=true D/mali_winsys(25703): EGLint new_window_surface(egl_winsys_display*, void*, EGLSurface, EGLConfig, egl_winsys_surface**, egl_color_buffer_format*, EGLBoolean) 返回 0x3000, [1440x2]-5格式:1 D/ViewRootImpl@5c26021MainActivity:MSG_WINDOW_FOCUS_CHANGED 1 D/ViewRootImpl@5c26021MainActivity:mHardwareRenderer.initializeIfNeeded()#2 mSurface={isValid=true 542519654912} V/InputMethodManager(25703):开始输入:tba=android.view.inputmethod。 EditorInfo@6fb193a nm:com.root.amployee ic=null I/InputMethodManager(25703):[IMM] startInputInner - mService.startInputOrWindowGainedFocus D/InputTransport(25703):输入通道构造:fd=93EGLSurface, EGLConfig, egl_winsys_surface**, egl_color_buffer_format*, EGLBolean) 返回 0x3000, [1440x2560]-format:1 D/ViewRootImpl@5c26021MainActivity: MSG_WINDOW_FOCUS_CHANGED 1 D/ViewRootImpl@5c26021MainActivity: mHardwareRenderer.initialize={mHardwareRenderer.initializeIfisValided=true) 542519654912} V/InputMethodManager(25703): 开始输入: tba=android.view.inputmethod.EditorInfo@6fb193a nm: com.root.amployee ic=null I/InputMethodManager(25703): [IMM] startInputInner - mService.startInputOrWindowGainedFocus D/ InputTransport(25703):输入通道构造:fd=93EGLSurface, EGLConfig, egl_winsys_surface**, egl_color_buffer_format*, EGLBolean) 返回 0x3000, [1440x2560]-format:1 D/ViewRootImpl@5c26021MainActivity: MSG_WINDOW_FOCUS_CHANGED 1 D/ViewRootImpl@5c26021MainActivity: mHardwareRenderer.initialize={mHardwareRenderer.initializeIfisValided=true) 542519654912} V/InputMethodManager(25703): 开始输入: tba=android.view.inputmethod.EditorInfo@6fb193a nm: com.root.amployee ic=null I/InputMethodManager(25703): [IMM] startInputInner - mService.startInputOrWindowGainedFocus D/ InputTransport(25703):输入通道构造:fd=93initializeIfNeeded()#2 mSurface={isValid=true 542519654912} V/InputMethodManager(25703):开始输入:tba=android.view.inputmethod.EditorInfo@6fb193a nm:com.root.amployee ic=null I/InputMethodManager(25703) :[IMM] startInputInner - mService.startInputOrWindowGainedFocus D/InputTransport(25703):输入通道构造:fd=93initializeIfNeeded()#2 mSurface={isValid=true 542519654912} V/InputMethodManager(25703):开始输入:tba=android.view.inputmethod.EditorInfo@6fb193a nm:com.root.amployee ic=null I/InputMethodManager(25703) :[IMM] startInputInner - mService.startInputOrWindowGainedFocus D/InputTransport(25703):输入通道构造:fd=93

E/flutter(25703):[错误:flutter/lib/ui/ui_dart_state.cc(148)]未处理的异常:NoSuchMethodError:方法'ancestorStateOfType'被调用为null。E/flutter(25703):接收者:null E/flutter(25703):尝试调用:ancestStateOfType('TypeMatcher'的实例) E/flutter(25703):#0 Object.noSuchMethod(dart:core-patch/object_patch.dart :50:5)

标签: flutterdartfirebase-dynamic-links

解决方案


这是图书馆本身的问题。因为context目前无法访问您访问的内容。所以我建议你在你的MaterialAppor中创建全局导航器状态CupertinoApp

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _navigatorKey = GlobalKey<NavigatorState>();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      key: _navigatorKey,
      home: Container(),
    );
  }
}

推荐阅读