美文网首页
Android与Flutter数据交互

Android与Flutter数据交互

作者: 一个多洋 | 来源:发表于2019-04-22 14:50 被阅读0次
    • 先看一下效果图吧(图一):上面是android原生,下面是flutter页面

      图一
    • 好 让我们一步一步来

    - 1.创建flutter module

    在android项目同级的目录里按住shift+右键,然后选择在此处打开 Powershell窗口(s)
    //或者在dos里cd到指定目录也行

    然后输入flutter create -t module my_flutter

    创建好后目录如下(图二):

    图二
    - 2.配置android工程(将Flutter模块作为依赖添加到主项目)

    settings.gradle文件里添加:

    setBinding(new Binding([gradle: this]))
    //我们的flutter目录
    evaluate(new File(
            settingsDir.parentFile,
            'my_flutter/.android/include_flutter.groovy'
    ))
    

    app目录的build.gradle下添加:

    dependencies {
        ...
        implementation project(':flutter')
    }
    

    添加之后同步下代码,然后我们就可以在android项目里调用flutter页面了

    - 3.android添加flutter布局

    改一下android:MainActivity.java里代码

    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    //        setContentView(R.layout.activity_main)
            
            //获取flutterView
            val flutterView = Flutter.createView(this, lifecycle, "route1")
            setContentView(flutterView)
        }
    }
    

    Flutter.createView方法里前两个参数是不变的,后面的"route1"可以获取指定的flutter页面,后面讲
    现在我们先运行一下看一下效果。。。

    • 运行的时候报了个错误(图三):


      图三

    需要在app目录的build.gradle下指定下jdk版本:

    android {
        ...
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }
    }
    

    再同步下,就可以运行了,运行效果(图四):


    图四

    获取flutterView还有一种方法:

    //获取flutterView 第二种方法
    val tx = supportFragmentManager.beginTransaction()
    //第一个参数填入flutterView要存放的布局id
    tx.replace(R.id.---, Flutter.createFragment("route1"))
    tx.commit()
    

    这两种方法都设置了"route1"这个参数,我们来看一下这个参数在flutter里怎么用吧:
    修改flutter main.dart里代码:

    import 'dart:ui';
    
    import 'package:flutter/material.dart';
    
    void main() => runApp(_widgetForRoute(window.defaultRouteName));
    
    Widget _widgetForRoute(String route) {
      switch (route) {
        case 'route1':
          return MyApp1();
          break;
        default:
          return MyApp();
          break;
      }
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: Text('MyApp'),
            ),
          ),
        );
      }
    }
    
    class MyApp1 extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: Text('MyApp1'),
            ),
          ),
        );
      }
    }
    

    这里的window需要导包,现在知道那个参数的作用了吧,我们可以根据那个参数跳转不同的flutter页面

    • 到这里android和flutter的基础配置就结束了,接下来我们进行数据传递
    - 4.数据传递

    写之前我们先修改下android activity_main.xml的布局(图五):

    图五

    MainActivity.java

    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            //获取flutterView
            val flutterView = Flutter.createView(this, lifecycle, "route1")
            llMainBottom.addView(flutterView)
        }
    }
    

    flutter页面的布局也修改下:

    import 'dart:ui';
    
    import 'package:flutter/material.dart';
    
    void main() => runApp(_widgetForRoute(window.defaultRouteName));
    
    Widget _widgetForRoute(String route) {
      switch (route) {
        case 'route1':
          return MyApp1();
          break;
        default:
          return MyApp();
          break;
      }
    }
    
    //App
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: Text('MyApp'),
            ),
          ),
        );
      }
    }
    
    //App1
    class MyApp1 extends StatefulWidget {
      @override
      _MyApp1State createState() => _MyApp1State();
    }
    
    class _MyApp1State extends State<MyApp1> {
      String _text = '你好 世界!';
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            body: Stack(
              alignment: FractionalOffset(0.5, 0.95),
              children: <Widget>[
                Center(
                  child: Text(_text),
                ),
                RaisedButton(
                  child: Text('修改android'),
                  onPressed: () {
                    
                  },
                ),
              ],
            ),
          ),
        );
      }
    }
    
    • 运行效果就和我们最上面的一样了,这里就不贴了,传输数据Flutter向我们提供了3个方法:
      -MethodChannel
      - EventChannel
      - BasicMessageChannel
      我这边示例一下MethodChannel的使用,其他两种方法有点类似

    • 我们点击android按钮,然后传输数据到flutter那边

    android发送:

    //发送msg给flutters
    MethodChannel(flutterView, "com.yang.test001").invokeMethod("android","Hello World!")
    

    • "com.yang.test001"相当于唯一标识,flutter那边接受用
    • invokeMethod方法里传的是键值对,flutter接受时可根据key取值

    flutter 接收:

      @override
      void initState() {
        super.initState();
        MethodChannel('com.yang.test001').setMethodCallHandler((handler) {
          //根据key判断android传过来的值
          switch (handler.method) {
            case 'android':
              setState(() {});
              var msg = handler.arguments;
              _text = msg.toString();
              break;
          }
        });
      }
    

    initState方法里进行监听,然后根据key进行判断,再setState(() {});改变下值就ok了
    android接受flutter的值同理...

    • 当我们android项目混合了flutter后,可以进行热重载(我这边测试只能更改flutter代码才有效果)
      :进入我们创建的my_flutter目录里,再shift+右键,然后选择在此处打开 Powershell窗口(s),然后输入:
    flutter attach
    

    会看到如下界面(图六):


    图六

    然后在android工程里启动我们的app(图七):


    图七

    启动后在shell窗口会看到如下信息(图八):


    图八

    之后修改flutter代码,在终端输入r就可以热重载了,R是热重启。没用的话先输入一遍R,再输入r,应该就可以看到效果了,再没用就反复多试试,感觉有点延迟,还有只能重载flutter代码,所以用处嘛,就一丢丢而已了。。

    • 所有的代码也贴一下吧:

    android

    class MainActivity : AppCompatActivity() {
        private lateinit var mMethodChannel: MethodChannel   //flutter连接
        private val METHOD_CHANNER = "com.yang.test001"      //与flutter连接的标识
        private var mIsSendFlutter = false
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            initView()
            initListener()
        }
    
        private fun initView() {
            //绑定flutterView 第一种方法
            val flutterView = Flutter.createView(this, lifecycle, "route1")
            llMainBottom.addView(flutterView)
    
    //        //第二种方法
    //        val tx = supportFragmentManager.beginTransaction()
    //        tx.replace(R.id.llMainBottom, Flutter.createFragment("route1"))
    //        tx.commit()
    
            //初始化MethodChannel
            mMethodChannel = MethodChannel(flutterView, METHOD_CHANNER)
        }
    
        private fun initListener() {
            //接受flutter消息监听
            mMethodChannel.setMethodCallHandler(object : MethodChannel.MethodCallHandler {
                override fun onMethodCall(p0: MethodCall, p1: MethodChannel.Result) {
                    //根据收到的消息key进行接收
                    when (p0.method) {
                        "flutter" -> {
                            val msg = p0.arguments
                            tvMain.text = msg.toString()
                        }
                        else -> {
    
                        }
                    }
                }
            })
    
            btnMain.setOnClickListener {
                //发送msg给flutter
                mMethodChannel.invokeMethod("android", if (mIsSendFlutter) {
                    "你好 世界!"
                } else {
                    "Hello World!"
                })
                mIsSendFlutter = !mIsSendFlutter
            }
        }
    }
    

    flutter

    import 'dart:ui';
    
    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    
    void main() => runApp(_widgetForRoute(window.defaultRouteName));
    
    Widget _widgetForRoute(String route) {
      switch (route) {
        case 'route1':
          return MyApp1();
          break;
        default:
          return MyApp();
          break;
      }
    }
    
    //App1
    class MyApp1 extends StatefulWidget {
      @override
      _MyApp1State createState() => _MyApp1State();
    }
    
    class _MyApp1State extends State<MyApp1> {
      MethodChannel _methodChannel = MethodChannel('com.yang.test001'); //与android连接
      String _text = '你好 世界!';
      bool _isSendAndroid = false;
    
      @override
      void initState() {
        super.initState();
        _methodChannel.setMethodCallHandler(_handler);
      }
    
      //接收android监听
      Future<dynamic> _handler(MethodCall call) {
        switch (call.method) {
          case 'android':
            setState(() {});
            var msg = call.arguments;
            _text = msg.toString();
            break;
        }
      }
    
      //发送消息给android
      void _sendMessage() {
        //flutter 相当于key 后面是内容
        _methodChannel.invokeListMethod(
            'flutter', _isSendAndroid ? 'Hello World!' : '你好 世界!');
        _isSendAndroid = !_isSendAndroid;
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            body: Stack(
              alignment: FractionalOffset(0.5, 0.95),
              children: <Widget>[
                Center(
                  child: Text(_text),
                ),
                RaisedButton(
                  child: Text('修改android'),
                  onPressed: () {
                    _sendMessage();
                  },
                ),
              ],
            ),
          ),
        );
      }
    }
    
    //默认App
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            body: Center(
              child: Text('myApp'),
            ),
          ),
        );
      }
    }
    

    相关文章

      网友评论

          本文标题:Android与Flutter数据交互

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