Flutter与原生交互

Posted 一个小码农的成长史

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter与原生交互相关的知识,希望对你有一定的参考价值。

当我们在已有的项目改造成一个新的Flutter项目的话,要重写构架不仅花的时间很长,并且Flutter现在还是一个测试的版本,存在或多或少的bug。但是如果我们只是在项目的某个模块进行改造,或者是加入一个新模块时间比较赶,这个时候就可以使用Flutter与原生混合是编程。这样就可以在不影响现有的项目的基础上,优化自己的项目啦。

一.创建Flutter Module模式

我们使用命令来创建一个新的插件具体代码如下

D:\workSpace>flutter create -t module my_flutter
setBinding(new Binding([gradle: this]))
evaluate(new File(
       settingsDir.parentFile,
       'my_flutter/.android/include_flutter.groovy'
))

如上所示,我创建的项目名称是my_flutter,并且在原生项目的同级目录下,所以才是如上配置。此时就会自动生成一个名为flutter的Module。

3.在app.gradle引用flutter Module如下所示

implementation project(':flutter')

此时就配置完成了原生和Flutter Module。

.Flutter 与原生交互

1.原生代码的实现

首先我们在原生页面中创建一个activity,基础FlutterActivity,如下,然后再Activity中配置自己的FlutterView。具体实现代码如下:

public class FMyInfoActivity extends FlutterFragmentActivity {
    private MethodChannel mMethodChannel;
   private final static
String CHANNEL = "samples.flutter.io/test";
   private
FrameLayout fl;
   private
FlutterView flutterView;
   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       
setContentView(R.layout.f_me_myinfo_activity);
       
fl = findViewById(R.id.root);
       
flutterView = Flutter.createView(this, getLifecycle(), "myInfo");
       
fl.addView(flutterView);
       
FlutterView.FirstFrameListener[] listeners = new FlutterView.FirstFrameListener[1];
       
listeners[0] = () -> fl.setVisibility(View.VISIBLE);
       
flutterView.addFirstFrameListener(listeners[0]);
       
mMethodChannel = new MethodChannel(flutterView, CHANNEL);
   
}
}
  • 为了防止启动Flutteractivity出现黑屏,我们使用了监听了启动的第一帧,显示的则是布局的颜色。

  • 我们创建了一个FlutterView, 第三个参数为route路径,当原生页面启动此页面时,进入Flutter的main函数启动app,此时传入根据不同的route,进入不同的flutter页面。

  • 添加的MethodChannel起了与Flutter交互的桥梁的作用。

2.Flutter代码的实现

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

class MyApp extends StatelessWidget {
 final String route;

 
MyApp(this.route);

 
@override
 
Widget build(BuildContext context) {
   return MaterialApp(
     title: "测试项目",
     
home: _widgetForRoute(route),
   
);
 
}

 Widget _widgetForRoute(String route) {
   switch (route) {
     case "myinfo":
       return UserPageView();
     
default:
       return Center(
         child:
         Text('Unknown route: $route', textDirection: TextDirection.ltr),
       
);
   
}
 }
}

在main.dart中实现如下代码。

.使用MethodChannel与原生交互

methodChannel作为两边交互的桥梁。首先原生如何向Flutter传值呢,原生和Flutter都创建一个同一个名称的Channel,打通双方的传值通道,当Flutter需要原生的一个值时,此时Flutter向原生发送一个通道请求如下

MethodChannel platform = const MethodChannel("samples.flutter.io/test");
//获取原生过来的用户信息
_getUserInfo() {
 platform.invokeMethod("getUserInfo").then((result) {
   return json.decode(result);
 
}).then((jsonInfo) {
   setState(() {
     _userInfo = jsonInfo;
   
});
 
}).catchError((onError) {
   print("catchError\r\n" + onError.toString());
 
});
}
mMethodChannel.setMethodCallHandler((methodCall, result) -> {
       if (methodCall.method.equals("getUserInfo")) {
       String data = SPUtils.getString(AppConstans.USER_INFO, "");
       
result.success(data);
       
} else {
       result.notImplemented();
       
}
});

如上所示如果双方的methodChannel名称一致,此时原生返回一个result给Flutter,Flutter获取到参数,并改变参数的值,这个流程则是原生给Flutter传值。

2.原生如何获取Flutter的值呢?首先原生这边发送一个通道请求给Flutter如下所示:

mMethodChannel.invokeMethod("refreshInfo","");

第一个参数为请求的名称,第二个参数则为传递的参数,可以为空,此时Flutter获取到原生的请求,做出相对的回应,如下所示

platform.setMethodCallHandler((methodCall){
 if(methodCall.method=="refreshInfo"){
   _getUserInfo()
 }
});

此时就完成了原生对Flutter的调用了,如果要传递参数的话,只需在双方的

invokeMethod()方法的第二个参数传入你要传递的参数就好啦。


以上就是Flutter与原生混合开发的全部内容啦。

以上是关于Flutter与原生交互的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 驱动程序与原生元素交互

Flutter 专题49 图解 Flutter 与 Android 原生交互 #yyds干货盘点#

Flutter与原生交互

Flutter 调用原生

VUE 与 原生交互(iOS为主)

如何与来自 Flutter integration_test 的原生 UI 元素进行交互?