Android已有项目接入Flutter及互相通信

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/qq_26936889/article/details/90768742

一.Android已有项目接入Flutter module(官方提供的module方式)

官方文档:https://github.com/flutter/flutter/wiki/Add-Flutter-to-existing-apps

1.创建Flutter module

(1)在已有的flutter项目中 输入命令:flutter create -t module moduleName,将生成的module复制到原生项目中

(2)或者在已有Android项目中输入上面命令,同样会生成一个module

2.在Android项目工程的settings.gradle增加以下配置

setBinding(new Binding([gradle: this]))

evaluate(new File(

        settingsDir.parentFile,

        'AndroidFlutterProject/flutter_module/.android/include_flutter.groovy'

))

1

2

3

4

5

flutter_module和app是同一级

AndroidFlutterProject:是Android项目的工程名

flutter_module:是刚才通过命令生成的module

3.在app的build.gradle增加以下依赖

implementation project(':flutter')

1

注意:原生项目中minSdkVersion 至少为16,否则编译不过

通过以上三步就将Flutter集成到原生项目中了。

二:Android原生调Flutter代码

Flutter提供两种引入方法:一个是View,会默认生成一个View,一个是FlutterFragment方式。

View方式:可以自己设置新View的大小,位置

FlutterView flutterView = Flutter.createView(this, getLifecycle(), "路由信息,自己自定义");

FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(100, 100);

layout.leftMargin = 0;

layout.topMargin = 0;

addContentView(flutterView, layout);

1

2

3

4

5

FlutterFragment方式:

setContentView(R.layout.activity_main);

FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();

fragmentTransaction.replace(R.id.fl_flutter_view, Flutter.createFragment("路由信息,自己自定义"));

fragmentTransaction.commit();

1

2

3

4

通过以上任意一种方式,都会调用fluttermodule中lib包下main.dart这个文件,我们可以在这个文件下面配置路由信息,控制页面跳转展示。

void main() => runApp(widgetForRoute(window.defaultRouteName));

Widget widgetForRoute(String route) {

  switch (route) {

    case '路由信息,自己自定义':

      return Center(

        child: Text('route: $route', textDirection: TextDirection.ltr),

      );

      return Center(

        child: Text('Unknown route: $route', textDirection: TextDirection.ltr),

      );

  }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

三:Flutter调用Android原生代码

Flutter调用原生主要使用插件方式,通过MethodChannel的方式。

1.在Application onCreate方法中进行初始化,关键

FlutterMain.startInitialization(this);

1

2.实现插件,创建一个类实现MethodChannel.MethodCallHandler,在onMethodCall回调方法中对Flutter指令分发处理。

public class FlutterPluginJumpToAct implements MethodChannel.MethodCallHandler {

    //channel信息,可以自己随便定义

    public static String CHANNEL = "com.qyh.jump/plugin";

    static MethodChannel channel;

    private Activity activity;

    private FlutterPluginJumpToAct(Activity activity) {

        this.activity = activity;

    }

    // 此方法需要外界进行调用注册

    public static void registerWith(PluginRegistry.Registrar registrar) {

        channel = new MethodChannel(registrar.messenger(), CHANNEL);

        FlutterPluginJumpToAct instance = new FlutterPluginJumpToAct(registrar.activity());

        //setMethodCallHandler在此通道上接收方法调用的回调

        channel.setMethodCallHandler(instance);

    }

    @Override

    public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {

        //通过methodCall可以获得参数和方法名,原生这面做对应业务

        //result可以给Flutter设置回调

        // "test1":是Flutter代码设置的调用指令

        if (methodCall.method.equals("test1")) {

            // do something

            result.success("suc");

        }

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

3.在Activity中注册,此Activity需要继承FlutterActivity

public class MainActivity extends FlutterActivity  {

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        GeneratedPluginRegistrant.registerWith(this);

        registerCustomPlugin(this);

    }

    private static void registerCustomPlugin(PluginRegistry registrar) {

        FlutterPluginJumpToAct.registerWith(registrar.registrarFor(FlutterPluginJumpToAct.CHANNEL));

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

FlutterActivity继承的是Activity,如果想用其他Activity,比如AppCompatActivity,我们可以创建抽象Base类,继承AppCompatActivity实现FlutterView.Provider, PluginRegistry, FlutterActivityDelegate.ViewFactory一系列方法。然后让我们的Activity直接继承这个基类就可以了。

4.在Flutter代码中实现跳转逻辑编写

void main() => runApp(widgetForRoute(window.defaultRouteName));

Widget widgetForRoute(String route) {

    // com.qyh.jump/plugin是原生代码中定义好的,要对应起来

  const jumpPlugin = const MethodChannel('com.qyh.jump/plugin');

  //test1 就是我们Flutter代码回调原生的指令名字

  jumpPlugin.invokeMethod('test1');

}

1

2

3

4

5

6

7

8

当Flutter代码执行到widgetForRoute(),会回调到插件FlutterPluginJumpToAct类的onMethodCall回调方法中,我们就可以通过methodCall.method获取到指令(test1)名,进行原生逻辑编写了,以上步骤就是Flutter调用原生代码的方法。

4.1.在Flutter代码中给原生传递参数

Flutter代码中通过Map的方式对数据进行拼接,然后回传给原生

void main() => runApp(widgetForRoute(window.defaultRouteName));

Widget widgetForRoute(String route) {

  // com.qyh.jump/plugin是原生代码中定义好的,要对应起来

  const jumpPlugin = const MethodChannel('com.qyh.jump/plugin');

  Map<String, String> mapData = {"flutterKey1": "flutterValue1","flutterKey2": "flutterValue2"};

  jumpPlugin.invokeMethod('test1',mapData);

}

1

2

3

4

5

6

7

8

原生代码中通过methodCall.arguments获取,解析

@Override

public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {

    //通过methodCall可以获得参数和方法名,原生这面做对应业务

    if (methodCall.method.equals("test1")) {

        if (methodCall.arguments != null) {

            Map<String, String> arguments = (Map<String, String>) methodCall.arguments;

        }

    }

}

1

2

3

4

5

6

7

8

9

以上就是Android原生跟Flutter交互方式,在实际项目中我遇到一个实际问题,原生、Flutter混合开发会遇到栈混乱的情况,之后引入阿里的[flutter_boost] (https://github.com/alibaba/flutter_boost),详细接入可以参考开源库,下面总结一下我接入这个库遇到一些问题:

1.Android appcation中不能引用FlutterBoostPlugin

在原生项目 app下面gradle引入flutter_boost

implementation project(':flutter_boost')

1

2.v4 v7库版本冲突

将xservice_kit 、flutter_boost、 flutter_module、 app下gradle里版本统一。

3.Android接收Flutter中传参中文字符串乱码

String decodeValue = URLDecoder.decode(value, "UTF-8");

1

四、接入Flutter后调试问题

1.Android原生代码不能快速debug

解决方法:将Android Studio升级到最新版本,目前最新版本3.4.1

2.Flutter热加载

在flutter_module目录下 输入命令 flutter attach,这个时候会提示等待连接设备,然后 Run一次项目,当项目重新运行起来后,就可以在Terminal 中输入r(热加载)、R(热重启)命令进行愉快的开发了。

————————————————

版权声明:本文为CSDN博主「Android小工」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/qq_26936889/article/details/90768742

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容