Flutter和原生交互学习
PlatformChannel功能简介
PlatformChannel分为BasicMessageChannel、MethodChannel以及EventChannel三种。其各自的主要用途如下:
- BasicMessageChannel: 用于传递数据。Flutter与原生项目的资源是不共享的,可以通过BasicMessageChannel来获取Native项目的图标等资源。
- MethodChannel: 传递方法调用。Flutter主动调用Native的方法,并获取相应的返回值。比如获取系统电量,发起Toast等调用系统API,可以通过这个来完成。
- EventChannel: 传递事件。这里是Native将事件通知到Flutter。比如Flutter需要监听网络情况,这时候MethodChannel就无法胜任这个需求了。EventChannel可以将Flutter的一个监听交给Native,Native去做网络广播的监听,当收到广播后借助EventChannel调用Flutter注册的监听,完成对Flutter的事件通知。
其实可以看到,无论传方法还是传事件,其本质上都是数据的传递,不过上层包的一些逻辑不同而已。
flutter
import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class ChannelPage extends StatefulWidget { @override State<StatefulWidget> createState() { return new _ChannelPageState(); } } class _ChannelPageState extends State<ChannelPage> { //获取到插件与原生的交互通道 static const jumpPlugin = const MethodChannel('com.example.jump/plugin'); static const counterPlugin = const EventChannel('com.example.counter/plugin'); var _count; StreamSubscription _counterSub; @override void initState() { super.initState(); _startCounterPlugin(); } @override void dispose() { super.dispose(); _endCounterPlugin(); } void _startCounterPlugin(){ if(_counterSub == null){ _counterSub = counterPlugin.receiveBroadcastStream().listen(_onCounterEvent,onError: _onCounterError); } } void _endCounterPlugin(){ if(_counterSub != null){ _counterSub.cancel(); } } void _onCounterError(Object error) { setState(() { _count = "计时器异常"; print(error); }); } void _onCounterEvent(Object event) { setState(() { _count = event; }); } Future<Null> _jumpToNative() async { String result = await jumpPlugin.invokeMethod('oneAct'); print(result); } Future<Null> _jumpToNativeWithValue() async { Map<String, String> map = { "flutter": "这是一条来自flutter的参数" }; String result = await jumpPlugin.invokeMethod('twoAct', map); print(result); } @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: new Text("Channel"), centerTitle: true, ), body: new Center( child: new ListView( children: <Widget>[ new Padding( padding: const EdgeInsets.only(left: 10.0, top: 10.0, right: 10.0), child: new RaisedButton( textColor: Colors.black, child: new Text('跳转到原生界面'), onPressed: () { _jumpToNative(); }), ), new Padding( padding: const EdgeInsets.only( left: 10.0, top: 10.0, right: 10.0), child: new RaisedButton( textColor: Colors.black, child: new Text('跳转到原生界面(带参数)'), onPressed: () { _jumpToNativeWithValue(); }), ), new Padding( padding: const EdgeInsets.only( left: 10.0, top: 10.0, right: 10.0), child: new Text('这是一个从原生发射过来的数据:$_count'), ), ], ) ), ); } }
android
package com.example.flutter_app.plugins; import android.app.Activity; import android.util.Log; import io.flutter.plugin.common.EventChannel; import io.flutter.plugin.common.PluginRegistry; public class FlutterPluginCounter implements EventChannel.StreamHandler { public static String CHANNEL = "com.example.counter/plugin"; static EventChannel channel; private Activity activity; private FlutterPluginCounter(Activity activity) { this.activity = activity; } public static void registerWith(PluginRegistry.Registrar registrar) { channel = new EventChannel(registrar.messenger(), CHANNEL); FlutterPluginCounter instance = new FlutterPluginCounter(registrar.activity()); channel.setStreamHandler(instance); // basicMessageChannel = new BasicMessageChannel<String> ("foo", StringCodec.INSTANCE); } @Override public void onListen(Object o, final EventChannel.EventSink eventSink) { eventSink.success(123456); } @Override public void onCancel(Object o) { Log.i("FlutterPluginCounter", "FlutterPluginCounter:onCancel"); } }
package com.example.flutter_app.plugins; import android.app.Activity; import android.content.Intent; import com.example.flutter_app.OneActivity; import com.example.flutter_app.TwoActivity; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.PluginRegistry; public class FlutterPluginJumpToAct implements MethodCallHandler { public static String CHANNEL = "com.example.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 call, MethodChannel.Result result) { //通过MethodCall可以获取参数和方法名,然后再寻找对应的平台业务,本案例做了2个跳转的业务 //接收来自flutter的指令oneAct if (call.method.equals("oneAct")) { //跳转到指定Activity Intent intent = new Intent(activity, OneActivity.class); activity.startActivity(intent); //返回给flutter的参数 result.success("success"); } //接收来自flutter的指令twoAct else if (call.method.equals("twoAct")) { //解析参数 String text = call.argument("flutter"); //带参数跳转到指定Activity Intent intent = new Intent(activity, TwoActivity.class); intent.putExtra(TwoActivity.VALUE, text); activity.startActivity(intent); //返回给flutter的参数 result.success("success"); } else { result.notImplemented(); } } }
package com.example.flutter_app; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; public class OneActivity extends Activity implements View.OnClickListener { private Button mGoFlutterBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_one); mGoFlutterBtn = findViewById(R.id.go_flutter); mGoFlutterBtn.setOnClickListener(this); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.go_flutter: Intent intent = new Intent(this, MainActivity.class); startActivity(intent); break; } } }
package com.example.flutter_app; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class TwoActivity extends Activity{ private TextView mTextView; public static final String VALUE = "value"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_two); mTextView = findViewById(R.id.text); String text = getIntent().getStringExtra(VALUE); mTextView.setText(text); } }
package com.example.flutter_app; import android.os.Bundle; import com.example.flutter_app.plugins.FlutterPluginCounter; import com.example.flutter_app.plugins.FlutterPluginJumpToAct; import io.flutter.app.FlutterActivity; import io.flutter.plugins.GeneratedPluginRegistrant; public class MainActivity extends FlutterActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); FlutterPluginJumpToAct.registerWith(this.registrarFor(FlutterPluginJumpToAct.CHANNEL));//注册 FlutterPluginCounter.registerWith(this.registrarFor(FlutterPluginCounter.CHANNEL));//注册 } }
activity_one.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:id="@+id/go_flutter" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="去Flutter界面"></Button> </LinearLayout>
activity_two.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/text" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout>
效果:
最后,关注【码上加油站】微信公众号后,有疑惑有问题想加油的小伙伴可以码上加入社群,让我们一起码上加油吧!!!
posted on 2019-08-14 17:02 LoaderMan 阅读(3754) 评论(0) 编辑 收藏 举报