Flutter Hooks 和异步调用

Flutter Hooks and async calls

前面有一些菜鸟问题。

我在我的应用程序中使用了 Flutter Hooks,但在尝试将 hooks 用于异步调用时遇到了困难。

例如,如何通过useMemoized(或任何其他带钩子的异步数据)获取SharedPreferences?

SharedPreferences preferences = useMemoized(() async => await SharedPreferences.getInstance());

上面的代码不起作用,因为“无法将参数类型 'Future Function()' 分配给参数类型 'SharedPreferences Function()'。”,但如何完成它?

我希望存储 SharedPreferences 实例以用于读取和写入值。


下面展示了我如何完成工作的真实示例,但我想知道是否有更好的方法。

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:location/location.dart';
import 'package:shared_preferences/shared_preferences.dart';

class LocationWidget extends HookWidget {
  const LocationWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final Location location = useMemoized(() => Location());
    final ValueNotifier<bool> isLocationEnabled = useState(false);
    final ValueNotifier<bool> isServiceEnabled = useState(false);
    final ValueNotifier<PermissionStatus> permissionStatus = useState(PermissionStatus.denied);

    useEffect(() {
      Future<void>.microtask(() async {
        final SharedPreferences preferences = await SharedPreferences.getInstance();
        isLocationEnabled.value = preferences.getBool('trackingEnabled') ?? false;

        isServiceEnabled.value = await location.serviceEnabled();
        permissionStatus.value = await location.hasPermission();
      });
    }, <Location>[location]);

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Text(
          'Location',
          style: Theme.of(context).textTheme.headline6,
        ),
        const SizedBox(height: 5.0),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: <Widget>[
            const Text('Tracking service'),
            Switch(
              value: isLocationEnabled.value,
              activeTrackColor: Colors.amberAccent,
              activeColor: Colors.amber,
              onChanged: (bool value) async {
                if (value) {
                  if (permissionStatus.value == PermissionStatus.denied) {
                    permissionStatus.value = await location.requestPermission();
                  }

                  if (permissionStatus.value == PermissionStatus.granted) {
                    if (!isServiceEnabled.value) {
                      isServiceEnabled.value = await location.requestService();
                    }

                    value = isServiceEnabled.value ? value : !value;
                  }
                }

                final SharedPreferences preferences = await SharedPreferences.getInstance();
                preferences.setBool('trackingEnabled', value);

                isLocationEnabled.value = value;
              },
            ),
          ],
        ),
      ],
    );
  }
}

我认为你目前的代码已经足够了,但如果你想使用 useMemoized 我建议这样做。

final future = useMemoized(SharedPreferences.getInstance);
final snapshot = useFuture(future, initialData: null);

useEffect(() {
  final preferences = snapshot.data;
  if (preferences == null) {
    return;
  }
  preferences.getBool('');
}, [snapshot.data]);