Flutter生命周期与ViewModel管理插件an_lifecycle_viewmodel的使用

发布于 1周前 作者 itying888 来自 Flutter

Flutter生命周期与ViewModel管理插件an_lifecycle_viewmodel的使用

使用说明

1lifecycle_viewmodel 是一个用于管理依赖于 anlifecycle 的 ViewModel 的包,类似于 Androidx ViewModel。

注意:该包将更名为 an_viewmodel。

1.1 准备生命周期环境

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    // 使用 LifecycleApp 包裹默认的 App
    return LifecycleApp(
      child: MaterialApp(
        title: 'ViewModel Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        navigatorObservers: [
          // 使用 LifecycleNavigatorObserver.hookMode() 注册路由事件变化
          LifecycleNavigatorObserver.hookMode(),
        ],
        home: const MyHomePage(title: 'ViewModel Home Page'),
      ),
    );
  }
}

当前使用的 PageView 和 TabBarViewPageView 应该被替换为 LifecyclePageView 和 LifecycleTabBarView。或者你可以用 LifecyclePageViewItem 包裹项目。可以参考 anlifecycle 获取指导。

1.2 使用 viewModelsvm 来注入或获取现有的的 ViewModel

class ViewModelHome with ViewModel {
  final ValueNotifier<int> counter = ValueNotifier<int>(0);

  ViewModelHome(Lifecycle lifecycle) {
    /// 将 ValueNotifier 与 Lifecycle 关联,并在生命周期结束时自动调用 dispose。
    counter.bindLifecycle(lifecycle);
  }

  void incrementCounter() {
    counter.value++;
  }
}

class MyHomePage extends StatelessWidget {
  final String title;

  const MyHomePage({super.key, required this.title});

  [@override](/user/override)
  Widget build(BuildContext context) {
    // 在当前环境中获取 ViewModel
    final ViewModelHome viewModel = context.viewModels();

    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text(
              'You have pushed the button this many times:',
            ),
            AnimatedBuilder(
              animation: viewModel.counter,
              builder: (_, __) =&gt; Text(
                '${viewModel.counter.value}',
                style: Theme.of(context).textTheme.headlineMedium,
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: const HomeFloatingButton(),
    );
  }
}

/// 模拟子控件 可以在 state 中直接使用
class HomeFloatingButton extends StatefulWidget {
  const HomeFloatingButton({super.key});

  [@override](/user/override)
  State&lt;HomeFloatingButton&gt; createState() =&gt; _HomeFloatingButtonState();
}

class _HomeFloatingButtonState extends State&lt;HomeFloatingButton&gt; {
  // 在 state 中获取 ViewModel
  late final vm = viewModelsOfState&lt;ViewModelHome&gt;();

  [@override](/user/override)
  Widget build(BuildContext context) {
    return FloatingActionButton(
      onPressed: vm.incrementCounter,
      tooltip: 'Increment',
      child: const Icon(Icons.add),
    );
  }
}

额外信息


示例代码

import 'package:an_lifecycle_cancellable/an_lifecycle_cancellable.dart';
import 'package:an_lifecycle_viewmodel/an_lifecycle_viewmodel.dart';
import 'package:anlifecycle/anlifecycle.dart';
import 'package:flutter/material.dart';

void main() {
  /// 提前声明 ViewModelHome 的创建方式
  ViewModelProvider.addDefFactory2(ViewModelHome.new);
  runApp(const MyApp());
}

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return LifecycleApp(
      child: MaterialApp(
        title: 'ViewModel Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        navigatorObservers: [
          LifecycleNavigatorObserver.hookMode(),
        ],
        home: const MyHomePage(title: 'ViewModel Demo Home Page'),
      ),
    );
  }
}

class ViewModelHome with ViewModel {
  final ValueNotifier<int> counter = ValueNotifier<int>(0);

  ViewModelHome(Lifecycle lifecycle) {
    counter.bindLifecycle(lifecycle);
  }

  void incrementCounter() {
    counter.value++;
  }
}

class MyHomePage extends StatelessWidget {
  final String title;

  const MyHomePage({super.key, required this.title});

  [@override](/user/override)
  Widget build(BuildContext context) {
    // 获取当前环境下的 ViewModel
    final ViewModelHome viewModel = context.viewModels();

    // 也可使用 当前提供的构建工厂
    // final ViewModelHome viewModel =
    //     context.viewModels(factory2: ViewModelHome.new);

    // 从路由页来缓存 ViewModel
    // final ViewModelHome viewModel1 = context.viewModelsByRoute();

    // 从 App 全局来缓存 ViewModel
    // final ViewModelHome viewModel1 = context.viewModelsByApp();

    // 当还有引用时 下次获取依然是同一个 当没有任何引用的时候 会执行清理 vm
    // final ViewModelHome viewModel1 = context.viewModelsByRef();

    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text(
              ' You have pushed the button this many times:',
            ),
            AnimatedBuilder(
              animation: viewModel.counter,
              builder: (_, __) =&gt; Text(
                '${viewModel.counter.value}',
                style: Theme.of(context).textTheme.headlineMedium,
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: const HomeFloatingButton(),
    );
  }
}

/// 模拟子控件 可以在 state 中直接使用
class HomeFloatingButton extends StatefulWidget {
  const HomeFloatingButton({super.key});

  [@override](/user/override)
  State&lt;HomeFloatingButton&gt; createState() =&gt; _HomeFloatingButtonState();
}

class _HomeFloatingButtonState extends State&lt;HomeFloatingButton&gt; {
  // 获取 vm 可以在 state 中直接使用
  late final vm = viewModelsOfState&lt;ViewModelHome&gt;();

  [@override](/user/override)
  Widget build(BuildContext context) {
    return FloatingActionButton(
      onPressed: vm.incrementCounter,
      tooltip: 'Increment',
      child: const Icon(Icons.add),
    );
  }
}

更多关于Flutter生命周期与ViewModel管理插件an_lifecycle_viewmodel的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter生命周期与ViewModel管理插件an_lifecycle_viewmodel的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,管理生命周期和ViewModel是开发高效应用的关键部分。an_lifecycle_viewmodel 插件能够帮助你更好地管理这些需求。下面是一个关于如何使用 an_lifecycle_viewmodel 插件的示例代码,展示了Flutter生命周期管理与ViewModel的结合。

首先,确保你已经在 pubspec.yaml 文件中添加了 an_lifecycle_viewmodel 依赖:

dependencies:
  flutter:
    sdk: flutter
  an_lifecycle_viewmodel: ^最新版本号 # 请替换为实际的最新版本号

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

接下来,让我们创建一个简单的示例,展示如何使用 an_lifecycle_viewmodel

1. 创建一个ViewModel类

首先,创建一个ViewModel类,用于管理应用的状态和数据。

import 'package:an_lifecycle_viewmodel/an_lifecycle_viewmodel.dart';

class MyViewModel extends BaseViewModel {
  String _message = "Hello, Flutter!";
  String get message => _message;

  void updateMessage(String newMessage) {
    _message = newMessage;
    notifyListeners(); // 通知监听器数据已更改
  }
}

2. 创建Flutter Widget并使用ViewModel

接下来,在你的Flutter Widget中使用这个ViewModel。

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:an_lifecycle_viewmodel/an_lifecycle_viewmodel.dart';
import 'my_view_model.dart'; // 导入之前创建的ViewModel

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider<MyViewModel>(
          create: (_) => MyViewModel(),
          // 使用 an_lifecycle_viewmodel 提供的 LifecycleProvider 包装 ChangeNotifierProvider
          lazy: false, // 确保ViewModel在应用启动时立即创建
        ).withLifecycleOwner(context), // 绑定生命周期
      ],
      child: MaterialApp(
        home: MyHomePage(),
      ),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final MyViewModel model = Provider.of<MyViewModel>(context);

    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Lifecycle with ViewModel'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              model.message,
              style: TextStyle(fontSize: 24),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                model.updateMessage("Message Updated!");
              },
              child: Text('Update Message'),
            ),
          ],
        ),
      ),
    );
  }
}

3. 理解代码

  • MyViewModel: 这是一个简单的ViewModel类,包含一个字符串 _message 和一个更新消息的方法 updateMessage。当消息更新时,调用 notifyListeners() 通知监听器。
  • MyApp: 在 MyApp 中,我们使用 MultiProvider 来提供 MyViewModelChangeNotifierProvider 用于创建和提供 MyViewModel 实例,并使用 withLifecycleOwner 方法将其与Flutter的生命周期绑定。
  • MyHomePage: 在 MyHomePage 中,我们通过 Provider.of<MyViewModel>(context) 获取ViewModel实例,并在UI中使用它。当用户点击按钮时,会调用 updateMessage 方法更新消息。

这样,你就创建了一个简单的Flutter应用,它使用 an_lifecycle_viewmodel 插件来管理ViewModel的生命周期。这个插件确保ViewModel在应用的生命周期内正确创建和销毁,从而帮助你管理应用的状态和数据。

回到顶部