Flutter框架性泛学习系列之二、Flutter应用层(Application Layer)下-状态管理与路由管理

任何知识体系,都需要系统的去学习,有一个大概的框架,学习才能如遇得水。知道自己学习的是什么,属于知识体系中的哪一环。
学习就应该首先有一个体系,然后不求甚解的将体系过一遍,最后再在体系中,填充各部分知识。

状态管理:

在Flutter应用开发中,状态管理是一个至关重要的概念。它涉及到应用中数据的管理、更新以及与用户界面的同步。在本文中,我们将深入探讨Flutter中的状态管理,包括状态管理的基本原理、常用的状态管理方式以及如何选择合适的状态管理方案。

1. 状态管理的基本原理

在Flutter中,状态是指应用程序的数据,而状态管理则是控制和更新这些数据的过程。Flutter的状态管理遵循一些基本原则:

  • 单一数据源: 应用的所有状态应该集中管理在一个地方,这样可以确保状态的一致性和可预测性。
  • 不可变性:状态应该是不可变的,即一旦创建就不能修改。这样可以避免意外的状态变更。
  • 可观察性:应用中的状态变化应该能够被观察到,以便及时更新用户界面。

常用的状态管理方式

Flutter提供了多种状态管理的方式,每种方式都有其适用的场景和优缺点。下面是几种常用的状态管理方式:

2.1 setState方法

Flutter中最简单的状态管理方式是使用setState方法。这种方式适用于简单的小型应用,通过setState方法可以在Widget内部管理状态,并触发UI的重新构建。

import 'package:flutter/material.dart';

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

class MyApp extends StatefulWidget {
  
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int _counter = 0;

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('setState示例'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                '按钮点击次数:',
              ),
              Text(
                '$_counter',
                style: Theme.of(context).textTheme.headline4,
              ),
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: _incrementCounter,
          tooltip: '增加',
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}

2.2 Provider库

Provider是Flutter官方推荐的状态管理库,它基于InheritedWidget和ChangeNotifier实现了状态共享和更新。使用Provider可以轻松地在应用中共享状态,并根据状态的变化更新用户界面。

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

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

class CounterModel extends ChangeNotifier {
  int _counter = 0;

  int get counter => _counter;

  void increment() {
    _counter++;
    notifyListeners();
  }
}

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => CounterModel(),
      child: MaterialApp(
        home: Scaffold(
          appBar: AppBar(
            title: Text('Provider示例'),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  '按钮点击次数:',
                ),
                Consumer<CounterModel>(
                  builder: (context, counterModel, child) {
                    return Text(
                      '${counterModel.counter}',
                      style: Theme.of(context).textTheme.headline4,
                    );
                  },
                ),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              Provider.of<CounterModel>(context, listen: false).increment();
            },
            tooltip: '增加',
            child: Icon(Icons.add),
          ),
        ),
      ),
    );
  }
}

2.3 Bloc库

Bloc是一种基于流(Stream)的状态管理库,它将应用程序的状态作为流发送到Widget,并通过事件和状态的转换来管理状态。Bloc适用于复杂的大型应用,可以有效地管理应用中的业务逻辑。

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

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

class CounterCubit extends Cubit<int> {
  CounterCubit() : super(0);

  void increment() => emit(state + 1);
}

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BlocProvider(
        create: (context) => CounterCubit(),
        child: CounterPage(),
      ),
    );
  }
}

class CounterPage extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Bloc示例'),
      ),
      body: BlocBuilder<CounterCubit, int>(
        builder: (context, state) {
          return Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  '按钮点击次数:',
                ),
                Text(
                  '$state',
                  style: Theme.of(context).textTheme.headline4,
                ),
              ],
            ),
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          BlocProvider.of<CounterCubit>(context).increment();
        },
        tooltip: '增加',
        child: Icon(Icons.add),
      ),
    );
  }
}

2.4 Redux库

Redux是一种基于单一不可变状态树的状态管理库,它借鉴了React中的Redux模式。Redux适用于需要严格的状态管理和可预测性的应用,但相对于其他方式来说,使用Redux可能需要更多的模板代码。

// 请注意,这里只提供了Redux的使用示例,实际上需要结合redux库来使用

import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';

void main() {
  final store = Store<int>(
    counterReducer,
    initialState: 0,
  );

  runApp(MyApp(store: store));
}

int counterReducer(int state, action) {
  if (action == 'increment') {
    return state + 1;
  }
  return state;
}

class MyApp extends StatelessWidget {
  final Store<int> store;

  MyApp({required this.store});

  
  Widget build(BuildContext context) {
    return StoreProvider<int>(
      store: store,
      child: MaterialApp(
        home: Scaffold(
          appBar: AppBar(
            title: Text('Redux示例'),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  '按钮点击次数:',
                ),
                StoreConnector<int, String>(
                  converter: (store) => store.state.toString(),
                  builder: (context, count) {
                    return Text(
                      count,
                      style: Theme.of(context).textTheme.headline4,
                    );
                  },
                ),
              ],
            ),
          ),
          floatingActionButton: StoreConnector<int, VoidCallback>(
            converter: (store) {
              return () => store.dispatch('increment');
            },
            builder: (context, callback) {
              return FloatingActionButton(
                onPressed: callback,
                tooltip: '增加',
                child: Icon(Icons.add),
              );
            },
          ),
        ),
      ),
    );
  }
}

3. 如何选择合适的状态管理方案

选择合适的状态管理方案取决于应用的规模、复杂度和团队的经验水平。以下是一些选择状态管理方案的考虑因素:

  • 应用规模: 对于小型应用,可以使用简单的setState方法来管理状态。而对于大型复杂应用,可能需要使用更强大的状态管理库来管理状态。
  • 开发团队: 开发团队的经验水平也是选择状态管理方案的重要因素。对于有经验的团队,他们可能更倾向于使用复杂的状态管理库来实现更高级的功能。
  • 学习曲线: 不同的状态管理库有不同的学习曲线,选择合适的状态管理方案还需要考虑团队成员的学习和适应能力。

结语

状态管理是Flutter应用开发中的核心概念之一,合适的状态管理方案能够帮助开发者更好地管理应用的状态,并构建出稳定、可维护的应用。通过本文的介绍,希望读者能够更深入地理解Flutter中的状态管理,并选择合适的方式来管理应用中的状态。

路由管理:

路由管理是应用层的重要组成部分,负责管理不同页面之间的切换和导航。Flutter提供了Navigator类和PageRoute类等API,用于实现路由管理。开发者可以使用这些API来定义页面之间的导航关系,并实现页面的跳转和传递参数等功能。

1. 路由管理的基本原理

在Flutter中,每个页面都是一个Widget,并且每个Widget都有一个路由名称(RouteName)。路由管理的基本原理是通过路由名称来识别和管理不同的页面,并通过Navigator来实现页面之间的跳转。

2. 常见的路由管理方式

2.1 基本路由

基本路由是Flutter中最简单的路由管理方式,通过Navigator.push和Navigator.pop方法来实现页面之间的跳转和返回。
基本路由是通过Navigator.push和Navigator.pop方法来实现页面之间的跳转和返回。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: FirstScreen(),
    );
  }
}

class FirstScreen extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('First Screen')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => SecondScreen()),
            );
          },
          child: Text('Go to Second Screen'),
        ),
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second Screen')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('Go back to First Screen'),
        ),
      ),
    );
  }
}

2.2 命名路由

命名路由是一种更灵活和可维护的路由管理方式,通过在应用的顶层定义路由表(RouteTable)来管理页面的路由名称和对应的Widget。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: '/',
      routes: {
        '/': (context) => FirstScreen(),
        '/second': (context) => SecondScreen(),
      },
    );
  }
}

class FirstScreen extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('First Screen')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pushNamed(context, '/second');
          },
          child: Text('Go to Second Screen'),
        ),
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second Screen')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('Go back to First Screen'),
        ),
      ),
    );
  }
}

2.3 路由传参

在Flutter中,我们可以通过Navigator.pushNamed方法将参数传递给目标页面,这样可以在目标页面中获取传递过来的参数,并进行相应的处理。在Flutter中,我们可以通过ModalRoute.of(context).settings.arguments来获取路由传递的参数。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: '/',
      routes: {
        '/': (context) => FirstScreen(),
        '/second': (context) => SecondScreen(),
      },
    );
  }
}

class FirstScreen extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('First Screen')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pushNamed(
              context,
              '/second',
              arguments: 'Hello from First Screen',
            );
          },
          child: Text('Go to Second Screen'),
        ),
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {
  
  Widget build(BuildContext context) {
    final String args = ModalRoute.of(context)?.settings.arguments as String;

    return Scaffold(
      appBar: AppBar(title: Text('Second Screen')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('Second Screen'),
            SizedBox(height: 20),
            Text(args),
            ElevatedButton(
              onPressed: () {
                Navigator.pop(context);
              },
              child: Text('Go back to First Screen'),
            ),
          ],
        ),
      ),
    );
  }
}

2.4 嵌套路由

Flutter支持嵌套路由,即在页面中嵌套其他页面,这样可以构建出复杂的导航结构和层次关系。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: '/',
      routes: {
        '/': (context) => HomeScreen(),
        '/profile': (context) => ProfileScreen(),
        '/settings': (context) => SettingsScreen(),
      },
    );
  }
}

class HomeScreen extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () {
                Navigator.pushNamed(context, '/profile');
              },
              child: Text('Go to Profile'),
            ),
            ElevatedButton(
              onPressed: () {
                Navigator.pushNamed(context, '/settings');
              },
              child: Text('Go to Settings'),
            ),
          ],
        ),
      ),
    );
  }
}

class ProfileScreen extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Profile')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('Go back to Home'),
        ),
      ),
    );
  }
}

class SettingsScreen extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Settings')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('Go back to Home'),
        ),
      ),
    );
  }
}

在这个示例中,我们有一个主页HomeScreen,它包含两个按钮,分别跳转到ProfileScreen和SettingsScreen。这两个页面都是嵌套在主页之中的子页面。

3. 如何灵活应对各种导航场景

3.1 页面跳转

在Flutter中,页面跳转是一种常见的导航场景,可以通过Navigator.pushNamed方法将用户导航到目标页面。

ElevatedButton(
  onPressed: () {
    Navigator.pushNamed(context, '/second');
  },
  child: Text('Go to Second Screen'),
),

3.2 页面返回

页面返回是另一种常见的导航场景,在Flutter中可以通过Navigator.pop方法将用户返回到上一个页面。

ElevatedButton(
  onPressed: () {
    Navigator.pop(context);
  },
  child: Text('Go back'),
),

3.3 路由替换

有时我们需要替换当前页面而不是添加新页面,这时可以使用Navigator.pushReplacementNamed方法来实现路由替换。

ElevatedButton(
  onPressed: () {
    Navigator.pushReplacementNamed(context, '/newPage');
  },
  child: Text('Replace with New Page'),
),

3.4 路由清空

有时我们需要清空路由栈并跳转到新页面,这时可以使用Navigator.pushNamedAndRemoveUntil方法来实现路由清空。

ElevatedButton(
  onPressed: () {
    Navigator.pushNamedAndRemoveUntil(context, '/home', (route) => false);
  },
  child: Text('Go to Home and clear route stack'),
),

总的来说,应用层是Flutter框架中与开发者直接交互的一层,负责实现应用的业务逻辑和用户界面。在应用层,开发者可以通过构建和组合Widgets、管理应用状态和路由,以及处理用户事件等方式,实现功能丰富、交互友好的Flutter应用程序。

  • 24
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值