簡體   English   中英

檢查 Stateless 小部件是否在 flutter 中被處理

[英]Check if Stateless widget is disposed in flutter

當我的無狀態小部件構建時,我使用以下代碼按順序播放一些聲音:

await _audioPlayer.play(contentPath1, isLocal: true);
await Future.delayed(Duration(seconds: 4));
await _audioPlayer.play(contentPath2, isLocal: true);
await Future.delayed(Duration(seconds: 4));
await _audioPlayer.play(contentPath3, isLocal: true);

當用戶在完成播放聲音之前關閉當前小部件時,即使在使用以下代碼關閉當前路由后聲音仍然有效:

Navigator.pop(context);

我的解決方法是使用布爾變量來指示關閉操作是否已完成。

播放聲音代碼:

await _audioPlayer.play(contentPath1, isLocal: true);
if (closed) return;
await Future.delayed(Duration(seconds: 4));
if (closed) return;
await _audioPlayer.play(contentPath2, isLocal: true);
if (closed) return;
await Future.delayed(Duration(seconds: 4));
if (closed) return;
await _audioPlayer.play(contentPath3, isLocal: true);

關閉當前小部件:

closed = true;
_audioPlayer.stop();

如果我的小部件關閉,是否有更好的方法來停止異步方法?

如果您將小部件更改為 StatefulWidget,那么您可以擁有如下功能:

void _playSounds() {
  await _audioPlayer.play(contentPath1, isLocal: true);
  await Future.delayed(Duration(seconds: 4));
  if (!mounted) return;

  await _audioPlayer.play(contentPath2, isLocal: true);
  await Future.delayed(Duration(seconds: 4));
  if (!mounted) return;

  await _audioPlayer.play(contentPath3, isLocal: true);
}

然后在 dispose 方法中處理播放器:

@override
void dispose() {
  _audioPlayer?.dispose();
  super.dispose();
}

mounted getter 目前已合並到 master 頻道中,但在穩定頻道中仍不可用。

https://github.com/flutter/flutter/pull/111619

同時,我們有 2 個選項

  1. 直接使用 Stateful Widget(作為公認的答案)
  2. 使用 builder 方法實現一個有狀態的 Widget 包裝器,以在包裝器中傳遞已mounted的 getter。

包裝小部件

import 'package:flutter/material.dart';

class PrimitiveWrapper<T> {
  T value;

  PrimitiveWrapper(this.value);
}

class MountedWrapper extends StatefulWidget {
  final Widget Function(BuildContext context, PrimitiveWrapper<bool> mounted) builder;

  const MountedWrapper({
    required this.builder,
    super.key,
  });

  @override
  State<MountedWrapper> createState() => _MountedWrapperState();
}

class _MountedWrapperState extends State<MountedWrapper> {
  @override
  Widget build(BuildContext context) {
    return widget.builder.call(context, PrimitiveWrapper(mounted));
  }
}

用法

class SubmitBtn extends StatelessWidget {

  ...

  Future<void> onSubmit(WidgetRef ref, BuildContext context, PrimitiveWrapper<bool> mounted) async {
    ...

    await topicRepo.add(topic);

    if (!mounted.value) {
      return;
    }

    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(
        content: Text('Created topic'),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return MountedWrapper(
      builder: (context, mounted) {
        return Consumer(
          builder: (context, ref, child) {
            return ElevatedButton(
              onPressed: () {
                onSubmit(ref, context, mounted);
              },
              child: const Text('Create'),
            );
          },
        );
      },
    );
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM