美文网首页Flutter
Flutter开发的传值(Eventbus)、导航和路由(Nav

Flutter开发的传值(Eventbus)、导航和路由(Nav

作者: 我打小就帅 | 来源:发表于2019-12-24 22:30 被阅读0次

前端开发的传值也是必须的,比如说跳转传值啊,这些再普通不过,在一切皆widget中Flutter中同样是必须要掌握的知识点

先介绍下Flutter中Eventbus的使用,Eventbus这个词语在Android过来的朋友再熟悉不过了,它用于Android的事件发布-订阅总线,应用程序内各个组件之间进行通信,那么在flutter中也可以这么理解的,下面通过实例介绍它的使用吧。

导入框架

dependencies:
  flutter:
    sdk: flutter
 #event_bus框架
  event_bus:  ^1.1.0

下面直接举个简单的例子吧,通过EventBusTest 2回传id值给EventBusTest


效果图.png

EventBusTest 的源码

import 'dart:async';

import 'package:flutter/material.dart';

import 'eventbus_manager/EventBusManage.dart';
import 'test_eventsbus2.dart';

class EventBusTest extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return EventBusState();
  }
}

class EventBusState extends State<EventBusTest> {
  var id = "";

  BuildContext mContext;
  StreamSubscription _subscription;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    //监听传id事件
    _subscription =
        JohwenEvent. eventBus.on<IdEvent>().listen((IdEvent data) => show(data.id));
    _subscription.resume();
  }

//刷新id
  void show(String val) {
    print("接收" + val);
    setState(() {
      id = val;
    });
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    print("接收${id} ");
    return Scaffold(
      appBar: AppBar(
        title: Text("eventbus接收"),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
          Builder(builder: (context) {
            return Text("EventBus回传的id: ${id}");
          }),
          RaisedButton(
            onPressed:(){
              Navigator.push(
                  context,
                  MaterialPageRoute(
                      builder: (context) => EventBusTest2()));
            },
            color: Colors.blue[400],
            child: new Text('eventbus发送',
                style: new TextStyle(color: Colors.white)),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    _subscription.cancel(); //  一定要取消 避免内存泄露
  }
}

EventBusTest 2源码

import 'package:flutter/material.dart';

import 'eventbus_manager/EventBusManage.dart';

class EventBusTest2 extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return EventBusState2();
  }

}

class EventBusState2  extends State<EventBusTest2>{
  TextEditingController idController = new TextEditingController();
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text("eventbus发送"),
      ),
      body:Column(
     children: <Widget>[
       new TextField(
         controller: idController,
         decoration: new InputDecoration(hintText: 'eventbus测试传id'),
       ),
       RaisedButton(
         onPressed: (){
           ///这里开始传值 调用fire方法
           eventBus.fire(IdEvent(idController.text.toString()));
           print("发送"+idController.text.toString());
         },
         color: Colors.blue[400],
         child: new Text('发送消息',
             style: new TextStyle(color: Colors.white)),
       )
     ],
      ) ,
    );
  }
}

初始化eventbus和事件


import 'package:event_bus/event_bus.dart';
//EventBus eventBus = new EventBus();

 

  EventBus eventBus = new EventBus();
 

/// Event 模拟传值 id
class IdEvent {
  String id;

  IdEvent(this.id);
}

这里我们需要注意的主要就几个知识点
1,EventBus其核心是基于Dart Streams(流),在这里定义了StreamSubscription _subscription;相当于订阅者, 所以要取消订阅,防止内存泄漏。如果想详细理解flutter 中Stream流,要详细看下其他篇章。
2,eventBus 的订阅方法fire ,万变不离其中,这里照着例子去做你想做的就行啦。

**Flutter导航,路由,传值的方式 **
1,通过 Navigator.pushNamed 导航。

先定义路由名称


 
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      child: MaterialApp(
        title: 'scoped',
        theme: ThemeData.dark(),
        home: TopPage(),
        routes: {
//        'objectRoute': (BuildContext context) => new ObjectPage(title: '数据操作'),
          'refresh': (BuildContext context) => new MainPage(),
          'login': (BuildContext context) => new LoginPage(),
          'objectRoute': (BuildContext context) => new ObjectPage(title: '数据操作'),
//        'indexpage': (BuildContext context) => new IndexPage(),
        },
      ),
    );
  }
}

使用

     Navigator.pushNamed(context, "objectRoute");

2,通过Navigator.push

    Navigator.push(
                       context,
                       MaterialPageRoute(
                           builder: (context) => AddThing()));
                 },

3,返回上一级页面

          Navigator.of(context).pop();

4,命名路由如何进行传值
这里摘自 https://cloud.tencent.com/developer/article/1489372

import 'package:flutter/material.dart';
import 'package:flutter_app_google/pages/SearchPage.dart';
import 'pages/tabs/Tabs.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {

  //配置命名路由信息
  final routes = {
    //如果需要传参,那么在配置的时候加上{arguments};如果不需要传参,则不用加{arguments}
    "/search": (context, {arguments}) => Searchpage(arguments: arguments,),
  };

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Tabs(),
        //统一处理命名路由
        onGenerateRoute: (RouteSettings settings) {
          final String name = settings.name;
          final Function pageContentBuilder = this.routes[name];
          if (pageContentBuilder != null) {//能寻找到对应的路由
            if (settings.arguments != null) {//页面跳转前有传参
              final Route route = MaterialPageRoute(
                  builder: (context) => pageContentBuilder(context,
                      arguments: settings.arguments));
              return route;
            } else {//页面跳转前没有传参
              final Route route = MaterialPageRoute(
                  builder: (context) => pageContentBuilder(context));
              return route;
            }
          }
        });
  }
}

第二步


import 'package:flutter/material.dart';

class Searchpage extends StatelessWidget {
  final arguments;//用于接收命名路由传递过来的参数值
  const Searchpage({Key key, this.arguments}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(//在最底层采取Scaffold组件
      appBar: AppBar(
        title: Text("搜索页面"),
      ),
      //获取命名路由传递过来的参数值
      body: Text("Search Page!传递过来的参数值是:${arguments != null ? arguments['info'] : '默认值'}"),
      floatingActionButton: FloatingActionButton(
        onPressed: (){
          //返回上一级页面
          Navigator.of(context).pop();
        },
        child: Text("back"),
      ),
    );
  }
}

第三步

 Navigator.pushNamed(context, "/search", arguments: {"info":"777"});

现在我们已经了解了命名路由传值该怎么去操作了,但是此时的代码看起来很乱,如果后期需要管理的命名路由多了,那么如果不做代码分离,而是直接像上面那样写的话,就会造成代码堆积,可读性变差,也不利于后期维护。所以,我们有必要做代码分离,那么该如何去做呢?

第1步,在lib文件夹下新建一个routes文件夹,然后在routes文件夹下新增一个 Routes.dart 文件

第2步 普通路由执行跳转页面的关键代码如下:

//Routes.dart

import 'package:flutter/material.dart';
import 'package:flutter_app_google/pages/SearchPage.dart';

//配置命名路由信息
final routes = {
  //如果需要传参,那么在配置的时候加上{arguments};如果不需要传参,则不用加{arguments}
  "/search": (context, {arguments}) => Searchpage(
        arguments: arguments,
      ),
};

//统一处理命名路由
var onGenerateRoute = (RouteSettings settings) {
  final String name = settings.name;
  final Function pageContentBuilder = routes[name];
  if (pageContentBuilder != null) {
    //能寻找到对应的路由
    if (settings.arguments != null) {
      //页面跳转前有传参
      final Route route = MaterialPageRoute(
          builder: (context) =>
              pageContentBuilder(context, arguments: settings.arguments));
      return route;
    } else {
      //页面跳转前没有传参
      final Route route =
          MaterialPageRoute(builder: (context) => pageContentBuilder(context));
      return route;
    }
  }
};

第3步 在main.dart中引入Routes.dart,并且使用暴露出来的接口

import 'package:flutter/material.dart';
import 'package:flutter_app_google/routes/Routes.dart' as prefix0;
import 'pages/tabs/Tabs.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Tabs(),
        //统一处理命名路由
        onGenerateRoute: prefix0.onGenerateRoute);
  }
}

现在我已经将命名路由的配置代码分离到 Routes.dart 文件中了,这样一分离,main.dart中的代码就简洁多了。其实,我们还可以对main.dart中的代码进一步进行优化,也就是说,我们还可以将 Tabs 这个主页面也通过命名路由进行管理,代码如下:


/Routes.dart
//配置命名路由信息
final routes = {
  //如果需要传参,那么在配置的时候加上{arguments};如果不需要传参,则不用加{arguments}
  "/": (context) => Tabs(),
  "/search": (context, {arguments}) => Searchpage(arguments: arguments),
};


//main.dart
void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        // home: Tabs(),
        initialRoute: "/",//初始化的时候加载的路由
        //统一处理命名路由
        onGenerateRoute: prefix0.onGenerateRoute);
  }
}

最后,我们再来看看有状态的组件如何进行路由传值:

import 'package:flutter/material.dart';

class DetailPage extends StatefulWidget {
  final Map arguments;//1,定义传值参数
  DetailPage({Key key, this.arguments}) : super(key: key);//2,重新写构造函数

  _DetailPageState createState() => _DetailPageState(arguments: arguments);//3,将参数值传递给_DetailPageState
}

class _DetailPageState extends State<DetailPage> {
  Map arguments;//4,定义传值参数
  _DetailPageState({this.arguments});//5,重新写构造函数
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("详情页面")),
      body: Text("hulalaDetail!~${this.arguments["name"]}")//6,获取到传递过来的值
    );
  }
}

好了 这个篇章Flutter开发的传值(Eventbus)、导航和路(Navigater,Router),大体就总结到这里了,有不对的,欢迎指正

相关文章

网友评论

    本文标题:Flutter开发的传值(Eventbus)、导航和路由(Nav

    本文链接:https://www.haomeiwen.com/subject/krlgnctx.html