Flutter:KeepAlive ParentDataWidget 的错误使用

问题描述 投票:0回答:1

尝试保持抽屉处于活动状态(打开/关闭抽屉时不要重建):

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      drawer: const AutomaticKeepAlive(
        child: Drawer(
          child: MyWidget(),
        ),
      ),
    );
  }
}

class MyWidget extends StatefulWidget {
  const MyWidget({super.key});

  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget>
    with AutomaticKeepAliveClientMixin {
  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    super.build(context);

    return const Column(
      children: [
        Text('Input Name:'),
        SizedBox(
          width: 50,
          height: 30,
          child: TextField(),
        ),
      ],
    );
  }
}

运行时错误:

════════ Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown while applying parent data.:
Incorrect use of ParentDataWidget.
The ParentDataWidget KeepAlive(keepAlive: false) wants to apply ParentData of type KeepAliveParentDataMixin to a RenderObject, which has been set up to accept ParentData of incompatible type ParentData.
Usually, this means that the KeepAlive widget has the wrong ancestor RenderObjectWidget. Typically, KeepAlive widgets are placed directly inside SliverWithKeepAliveWidget or TwoDimensionalViewport widgets.
The offending KeepAlive is currently placed inside a Semantics widget.
The ownership chain for the RenderObject that received the incompatible parent data was:
  Semantics ← Drawer ← NotificationListener<KeepAliveNotification> ← KeepAlive ← AutomaticKeepAlive ← _FocusInheritedScope ← Semantics ← FocusScope-[GlobalKey#b1269] ← RepaintBoundary ← Align ← ⋯
flutter keep-alive drawer
1个回答
0
投票

当您关闭抽屉时,AutomaticKeepAlive 也会与其所有子项一起被处置。

要保留抽屉小部件,您将需要一个全局键,并且需要将抽屉对象移动到隐藏在小部件树中的某个位置,以便抽屉不会被释放。

这是示例代码。

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final GlobalKey drawerKey = GlobalKey();
  bool isDrawerOpened = false;

  Widget get drawer => Drawer(
        key: drawerKey,
        child: const MyWidget(),
      );

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Visibility(
          visible: !isDrawerOpened,
          child: drawer,
        ),
        Scaffold(
          
          appBar: AppBar(
            backgroundColor: Theme.of(context).colorScheme.inversePrimary,
            title: Text(widget.title),
          ),
          onDrawerChanged: (isOpened) {
            Future.delayed(Duration.zero, () {
              isDrawerOpened = isOpened;
              setState(() {});
            });
          },
          drawer: isDrawerOpened ? drawer : const Drawer(),
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              setState(() {});
            },
            child: const Icon(Icons.add),
          ),
        ),
      ],
    );
  }
}

class MyWidget extends StatefulWidget {
  const MyWidget({super.key});

  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  @override
  Widget build(BuildContext context) {
    return const Column(
      children: [
        Text('Input Name:'),
        SizedBox(
          width: 50,
          height: 30,
          child: TextField(),
        ),
      ],
    );
  }
}

© www.soinside.com 2019 - 2024. All rights reserved.