首页 > 解决方案 > 钩子只能在颤振中小部件的构建方法中调用

问题描述

我正在使用flutter编写一个简单的页面,但是当我编译项目并运行调试时,它显示错误:

    Launching lib/main.dart on sdk gphone x86 arm in debug mode...
Running Gradle task 'assembleDebug'...
✓ Built build/app/outputs/flutter-apk/app-debug.apk.
Installing build/app/outputs/flutter-apk/app.apk...
Waiting for sdk gphone x86 arm to report its views...
Debug service listening on ws://127.0.0.1:42239/B45QwfJKV30=/ws
Syncing files to device sdk gphone x86 arm...

══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown building MyHomePage(dirty, state: _MyHomePageState#97d08):
Hooks can only be called from the build method of a widget that mix-in `Hooks`.

Hooks should only be called within the build method of a widget.
Calling them outside of build method leads to an unstable state and is therefore prohibited.
'package:flutter_hooks/src/framework.dart':
Failed assertion: line 142 pos 12: 'HookElement._currentHookElement != null'

The relevant error-causing widget was:
  MyHomePage file:///home/dolphin/AndroidStudioProjects/Cruise/lib/src/widgets/MyApp.dart:27:13

When the exception was thrown, this was the stack:
#2      Hook.use (package:flutter_hooks/src/framework.dart:142:12)
#3      use (package:flutter_hooks/src/framework.dart:19:32)
#4      useMemoized (package:flutter_hooks/src/primitives.dart:11:10)
#5      _MyHomePageState.build (package:Cruise/src/states/_MyHomePageState.dart:121:5)
#6      StatefulElement.build (package:flutter/src/widgets/framework.dart:4663:28)
#7      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4546:15)
#8      StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4719:11)
#9      Element.rebuild (package:flutter/src/widgets/framework.dart:4262:5)
#10     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4525:5)
#11     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4710:11)
#12     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4520:5)
...     Normal element mounting (132 frames)
#144    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3490:14)
#145    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5991:32)
...     Normal element mounting (273 frames)
#418    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3490:14)
#419    Element.updateChild (package:flutter/src/widgets/framework.dart:3258:18)
#420    RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:1174:16)
#421    RenderObjectToWidgetElement.mount (package:flutter/src/widgets/binding.dart:1145:5)
#422    RenderObjectToWidgetAdapter.attachToRenderTree.<anonymous closure> (package:flutter/src/widgets/binding.dart:1087:17)
#423    BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2620:19)
#424    RenderObjectToWidgetAdapter.attachToRenderTree (package:flutter/src/widgets/binding.dart:1086:13)
#425    WidgetsBinding.attachRootWidget (package:flutter/src/widgets/binding.dart:927:7)
#426    WidgetsBinding.scheduleAttachRootWidget.<anonymous closure> (package:flutter/src/widgets/binding.dart:908:7)
(elided 13 frames from class _AssertionError, class _RawReceivePortImpl, class _Timer, dart:async, and dart:async-patch)

════════════════════════════════════════════════════════════════════════════════════════════════════

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following assertion was thrown building MyHomePage(dirty, state: _MyHomePageState#97d08):
Hooks can only be called from the build method of a widget that mix-in `Hooks`.

Hooks should only be called within the build method of a widget.
Calling them outside of build method leads to an unstable state and is therefore prohibited.
'package:flutter_hooks/src/framework.dart':
Failed assertion: line 142 pos 12: 'HookElement._currentHookElement != null'

The relevant error-causing widget was: 
  MyHomePage file:///home/dolphin/AndroidStudioProjects/Cruise/lib/src/widgets/MyApp.dart:27:13
When the exception was thrown, this was the stack: 
#2      Hook.use (package:flutter_hooks/src/framework.dart:142:12)
#3      use (package:flutter_hooks/src/framework.dart:19:32)
#4      useMemoized (package:flutter_hooks/src/primitives.dart:11:10)
#5      _MyHomePageState.build (package:Cruise/src/states/_MyHomePageState.dart:121:5)
#6      StatefulElement.build (package:flutter/src/widgets/framework.dart:4663:28)
...
════════════════════════════════════════════════════════════════════════════════════════════════════

这是我被称为代码块:

@override
  Widget build(BuildContext context) {
    useMemoized(() => DeeplinkHandler.init(context));
    useEffect(() => DeeplinkHandler.cancel, const []);
}

显然我在构建块中被调用,为什么给出这个错误?我应该怎么做才能解决这个问题?这是整个项目。我正在使用 Fedora 32 + Android Studio。

标签: flutter

解决方案


Hooks 只能从 mix-in 的小部件的 build 方法中调用 Hooks

您的小部件_MyHomePageState似乎正在扩展 State<> (StatefulWidget) 而不是 HookWidget 或 HookState<>,请查看文档中提供的示例

class _TimeAlive extends Hook<void> {
  const _TimeAlive();

  @override
  _TimeAliveState createState() => _TimeAliveState();
}

class _TimeAliveState extends HookState<void, _TimeAlive> {
  DateTime start;

  @override
  void initHook() {
    super.initHook();
    start = DateTime.now();
  }

  @override
  void build(BuildContext context) {}

  @override
  void dispose() {
    print(DateTime.now().difference(start));
    super.dispose();
  }
}

如果您的小部件是 statefulWidget,请将其更改为如下所示(扩展 Hook 和 HookState)

class MyHomePage extends Hook<void>{
  MyHomePage({Key key}) : super(key: key);


  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends HookState<void, MyHomePage> {

  @override
  void initHook() {
    super.initHook();
    //initialize things here
  }

  @override
  void build(BuildContext context) {
     //your hook code here
     useMemoized(() => DeeplinkHandler.init(context));
     useEffect(() => DeeplinkHandler.cancel, const []);
     return Container();
  }

  @override
  void dispose() {
    //dispose things here
    super.dispose();
  }
}

推荐阅读