根据不同变量显示Flutter叠加

fwzugrvs  于 2023-01-27  发布在  Flutter
关注(0)|答案(2)|浏览(72)

我有一个名为TestMain的flutter屏幕,它有一个支架和白色背景。支架主体应该在某些事件发生时发生变化。事件存储为布尔值。有“isLocked”和“isPaused”,它们由Riverpod流提供程序发出,还有“isCheating”,当Applifecyle事件被触发时发生变化。所有三个布尔值都存储为Riverpod状态提供程序。因为它的全球可访问性。
这是我的“isCheatingProvider”:final isCheatingProvider = StateProvider.autoDispose<bool>((ref) => false);“isPausedProvider”和“isLockedProvider”相同。
这是测试主屏幕

class TestMain extends ConsumerStatefulWidget {
  const TestMain({super.key});

  @override
  ConsumerState<TestMain> createState() => _TestMainScreenState();
}

class _TestMainScreenState extends ConsumerState<TestMain>
    with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) async {
    super.didChangeAppLifecycleState(state);

    final isCheating = ref.watch(isCheatingProvider.notifier);

    switch (state) {
      case AppLifecycleState.resumed:
      case AppLifecycleState.inactive:
        await sendCheatingAttempt(ref);
        setState(() {
          isCheating.state = true;
        });
        break;
      case AppLifecycleState.paused:
        await sendCheatingAttempt(ref);
        setState(() {
          isCheating.state = true;
        });
        break;
      case AppLifecycleState.detached:
        await sendCheatingAttempt(ref);
        setState(() {
          isCheating.state = true;
        });
        break;
    }
  }

  @override
  Widget build(BuildContext context) {
    final List<Item> items = ref.watch(itemsProvider);
    final AsyncValue<dynamic> wsTestListenerMessage =
        ref.watch(testListenerProvider);

    final isLocked = ref.watch(isLockedProvider.notifier);
    final isPaused = ref.watch(isPausedProvider.notifier);
    final isCheating = ref.watch(isCheatingProvider.notifier);

    wsTestListenerMessage.when(
      loading: () => {},
      error: (err, stack) => print('Test State Error: $err'),
      data: (message) async {
        Future.delayed(const Duration(seconds: 0), () {
          if (message["lock"] == true) {
            isLocked.state = true;
          }
          if (message["unlock"] == true) {
            isLocked.state = false;
          }
          if (message["paused"] == true) {
            isPaused.state = true;
          }
          if (message["resumed"] == true) {
            isPaused.state = false;
          }
        });
      },
    );

    return Scaffold(
      backgroundColor: Colors.white,
      body: SafeArea(
          child: isPaused.state
              ? const ErrorOverlay(text: 'paused')
              : isLocked.state || isCheating.state
                  ? const ErrorOverlay(text: 'cheating')
                  : const TestView()),
    );
  }
}

但是它不起作用。不管我怎么做。我在if语句周围添加了Future.delayed(const Duration(seconds: 0), () {},因为它抱怨在build方法中更改了提供者。我在didChangeAppLifecycleState()中使用了setState(),但是不能在侦听器中使用它,因为侦听器会被一遍又一遍地调用。它不应该超过一次地开放。
(ErrorOverlay是一个自定义小部件,只在中间用红色大字母显示文本)

vxf3dgd4

vxf3dgd41#

  • 删除setState,这将不执行任何操作
  • 使用ref.read(provider.notifier).state设置状态
  • 用于手表ref.watch(isCheatingProvider)

通过改变所有这一切是好的测试在我身边:

final isCheatingProvider = StateProvider.autoDispose<bool>((ref) => false);

class TestMain extends ConsumerStatefulWidget {
  const TestMain({key});

  @override
  ConsumerState<TestMain> createState() => _TestMainScreenState();
}

class _TestMainScreenState extends ConsumerState<TestMain>
    with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) async {
    super.didChangeAppLifecycleState(state);

    final isCheating = ref.read(isCheatingProvider.notifier);

    switch (state) {
      case AppLifecycleState.resumed:
      case AppLifecycleState.inactive:
        isCheating.state = true;
        break;
      case AppLifecycleState.paused:
        isCheating.state = true;
        break;
      case AppLifecycleState.detached:
        isCheating.state = true;
        break;
    }
  }

  @override
  Widget build(BuildContext context) {
    final isCheating = ref.watch(isCheatingProvider);

    return Scaffold(
      backgroundColor: isCheating ? Colors.red : Colors.white,
      body: SafeArea(
          child: isCheating ? Text('cheat') : Text(' good')
      )
    );
  }
}
slsn1g29

slsn1g292#

您使用StateProvider的方式不正确。若要观看StateNotifier,您应该使用

final isCheating = ref.watch(isCheatingProvider);

以及更改提供程序使用

ref.read(productSortTypeProvider.notifier).state = value;

因此,您必须更改所有与提供程序相关的代码。

@override
void didChangeAppLifecycleState(AppLifecycleState state) async {
  super.didChangeAppLifecycleState(state);

  final isCheatingNotifier = ref.read(isCheatingProvider.notifier);

  switch (state) {
    case AppLifecycleState.resumed:
    case AppLifecycleState.inactive:
      await sendCheatingAttempt(ref);
      isCheatingNotifier.state = true;
      break;
    case AppLifecycleState.paused:
      await sendCheatingAttempt(ref);
      isCheatingNotifier.state = true;
      break;
    case AppLifecycleState.detached:
      await sendCheatingAttempt(ref);
      isCheatingNotifier.state = true;
      break;
  }
}

@override
Widget build(BuildContext context) {
  final List<Item> items = ref.watch(itemsProvider);
  final AsyncValue<dynamic> wsTestListenerMessage =
  ref.watch(testListenerProvider);

  final isLocked = ref.watch(isLockedProvider);
  final isPaused = ref.watch(isPausedProvider);
  final isCheating = ref.watch(isCheatingProvider);

  wsTestListenerMessage.when(
    loading: () => {},
    error: (err, stack) => print('Test State Error: $err'),
    data: (message) async {
      Future.delayed(const Duration(seconds: 0), () {
        final isLockedNotifier = ref.read(isLockedProvider.notifier);
        final isPausedNotifier = ref.read(isPausedProvider.notifier);

        if (message["lock"] == true) {
          isLockedNotifier.state = true;
        }
        if (message["unlock"] == true) {
          isLockedNotifier.state = false;
        }
        if (message["paused"] == true) {
          isPausedNotifier.state = true;
        }
        if (message["resumed"] == true) {
          isPausedNotifier.state = false;
        }
      });
    },
  );

  return Scaffold(
    backgroundColor: Colors.white,
    body: SafeArea(
        child: isPaused
            ? const ErrorOverlay(text: 'paused')
            : isLocked || isCheating
            ? const ErrorOverlay(text: 'cheating')
            : const TestView()),
  );
}

相关问题