Android与Flutter数据交互

2019-04-22  本文已影响0人  一个多洋
- 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页面

- 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: () {
                
              },
            ),
          ],
        ),
      ),
    );
  }
}

android发送:

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

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的值同理...

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'),
        ),
      ),
    );
  }
}
上一篇下一篇

猜你喜欢

热点阅读