Flutter热重载插件flutter_reload的使用

Flutter热重载插件flutter_reload的使用

flutter_reload 插件简化了错误处理,通过管理底层错误,让开发者可以专注于业务逻辑。

为什么使用 flutter_reload

我们喜欢并通常选择一种状态管理机制作为我们的基础架构。在许多情况下,例如使用网络API时,每个视图都需要一个“何时”条件来处理异常。

flutter_reload 尝试创建一个轻量级层来处理所有常见的错误情况。通过额外的保护措施 guard,我们不再需要为每个UI和模型管理每个异常情况,如网络错误、存储错误、编程异常等。我们称之为无异常意识的愉快开发体验。:D :)

带有异常意识的UI概念

Widget build(BuildContext context) {
  switch (result) {
    case loading:
      return Text('Loading view data...');
    case error:
      return Text('Load data failed.');
    case data(data):
      return Text('Yes!! Here is the $data!!');
  }
}

无异常意识的UI概念

Widget build(BuildContext context) {
  return GuardView(
    builder: (context) {
      return Text('Yes!! Here is the ${result.data}!!');
    }
  );
}

带有异常意识的Model概念

Future<void> createTodo(Todo todo) {
  try {
    state = Result.loading();
    final data = await todoService.createTodo();
    state = Result.success(Todo.fromJson(data));
  } catch (ex) {
    if (ex is NetworkException) {
      state = Result.error(ex);
    } else if ...
  }
}

无异常意识的Model概念

Future<void> createTodo(Todo todo) {
  await guard(() {
    final data = await todoService.createTodo();
    state = Result.success(Todo.fromJson(data));
  });
}

安装

请按照以下步骤安装此包:

  1. 在项目的 pubspec.yaml 文件中添加依赖:

    dependencies:
      flutter_reload: ^版本号
    
  2. 运行 flutter pub get 更新依赖。

安装完成后,你可以通过以下三个主要步骤轻松集成 flutter_reload

第一步:初始化配置

void main() {
  ReloadConfiguration.init(
    abnormalStateBuilder: globalAbnormalStateBuilder,
    exceptionHandle: globalExceptionHandle,
  );
  runApp(const MyApp());
}

Widget? globalAbnormalStateBuilder(BuildContext context, GuardState guardState,
    DataSupplier<FutureOr<void>> dataReloader) {
  switch (guardState) {
    case InitGuardState():
      return const Center(child: CircularProgressIndicator.adaptive());
    case OfflineGuardState():
      return const Center(child: Text('Offline...'));
    case ErrorGuardState<CustomException>(cause: CustomException cause):
      return Center(child: Text('Error: ${cause.message}'));
    case ErrorGuardState<Exception>(cause: var cause):
      return Center(child: Text('Error: $cause'));
    default:
      return null;
  }
}

void globalExceptionHandle(
  exception,
  stackTrace, {
  GuardStateController? guardStateController,
  GuardExceptionHandleResult Function(dynamic, dynamic)? onError,
  required bool silent,
}) {
  final errorHandlerResult = onError?.call(exception, stackTrace) ??
      GuardExceptionHandleResult.byDefault;

  if (guardStateController != null &&
      guardStateController.value is InitGuardState) {
    
    // TODO: 记录意外错误
    guardStateController.value = ErrorGuardState<Exception>(cause: exception);
  } else {
    if (errorHandlerResult == GuardExceptionHandleResult.mute) {
      return;
    } else {
      // TODO: 记录意外错误
      ScaffoldMessenger.of(rootContext!)
          .showSnackBar(SnackBar(content: Text('$exception')));
    }
  }
}

第二步:支持UI模型的重新加载生命周期

class MyViewModel extends GuardViewModel {
  final randomWords = <String>[];

  MyViewModel() : super(GuardState.init);

  @override
  FutureOr<void> reload() async {
    await guardReload(() async {
      randomWords..clear()..addAll(await myNetworkService.getRandomWordsFromServer());
      notifyListeners();
    });
  }
}

第三步:使用 GuardView() 构建UI

@override
Widget build(BuildContext context) {
  return GuardView(
    model: myViewModel,
    builder: (context) {
      return ListenableWidget(
        model: myViewModel,
        builder: (context) {
          return ListView.separated(
            itemBuilder: (BuildContext context, int index) {
              final rowData = myViewModel.randomWords[index];
              return ListTile(
                key: ValueKey(rowData),
                title: Text(rowData),
              );
            },
            separatorBuilder: (context, index) => const Divider(),
            itemCount: myViewModel.randomWords.length,
          );
        },
      );
    },
  );
}

示例

以下是几个示例项目:

  1. 新闻: 使用 ChangeNotifier 作为状态管理的 HackNews 演示。
  2. 新闻 Riverpod: 使用 Riverpod 作为状态管理的 HackNews 演示。
  3. 待办事项: 使用 ChangeNotifier 作为状态管理的常见待办事项应用演示。

架构

架构

生命周期

生命周期

LLM友好的框架

合并所有 Dart 文件

在Mac环境中合并所有 Dart 文件(核心+示例)到单个上下文中:

find ./packages/flutter_reload ./examples/news -name "*.dart" -print0 | xargs -0 cat > ~/Downloads/flutter_reload_source

此外,你可以将任何示例添加到 ./examples/news 中。

添加上下文到你的LLM引用中

[FLUTTER_RELAOD_SOURCE]

帮助编写一个带有 flutter_reload 的待办事项应用。你需要实现以下需求:

  1. 实现模型和UI的TODO CRUD操作。
  2. 支持持久化以保存模型的待办事项。

更多关于Flutter热重载插件flutter_reload的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter热重载插件flutter_reload的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,关于Flutter热重载插件flutter_reload的使用,下面是一个简单的代码案例来展示如何集成和使用这个插件。

首先,你需要在你的pubspec.yaml文件中添加flutter_reload依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_reload: ^x.y.z  # 请替换为最新版本号

然后运行flutter pub get来获取依赖。

接下来,你可以在你的Flutter应用中集成flutter_reload插件。以下是一个简单的例子:

  1. 创建主应用文件(main.dart
import 'package:flutter/material.dart';
import 'package:flutter_reload/flutter_reload.dart';

void main() {
  // 初始化 FlutterReload
  FlutterReload.initialize();

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Demo Home Page'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }

  // 监听热重载事件
  @override
  void initState() {
    super.initState();
    FlutterReload.addListener(() {
      print("Flutter app reloaded!");
      // 你可以在这里添加任何需要在热重载时执行的代码
    });
  }

  @override
  void dispose() {
    // 移除监听器
    FlutterReload.removeListener(() {});
    super.dispose();
  }
}
  1. 运行应用

使用flutter run命令运行你的应用。在开发过程中,当你对代码进行修改并保存后,Flutter会自动触发热重载。

  1. 热重载事件监听

在上述代码中,我们添加了FlutterReload.addListener来监听热重载事件。每次热重载发生时,控制台会打印出"Flutter app reloaded!"。你可以在这个回调中添加任何你需要在热重载时执行的代码,比如重置状态、清理资源等。

  1. 移除监听器

dispose方法中,我们移除了监听器。这是一个良好的实践,以确保在组件被销毁时不会留下任何悬挂的引用。

通过上述步骤,你就可以在你的Flutter应用中集成并使用flutter_reload插件来监听热重载事件。请注意,flutter_reload插件的具体用法可能会根据版本有所不同,请参考其官方文档和示例代码以获取最新和详细的信息。

回到顶部