本文主要尝试解决如下几个问题:
如何在在已经项目加入Flutter
混合跳转
混合栈问题
混合栈数据问题
跳转黑屏是因为debug的缘故,打release包则没有。
af.gif
1. 如何在在已经项目加入Flutter
直接参考这篇文章Add Flutter to existing apps
2. 混合跳转
首先:Android跳转到Flutter
创建一个FlutterActivity
直接继承FlutterActivity或者自定义一个CustomFlutterActivity,我用的自定义,是做了一些封装和flutter插件注册
public abstract class CustomFlutterActivity extends AppCompatActivity implements FlutterView.Provider, PluginRegistry, FlutterActivityDelegate.ViewFactory { private final FlutterActivityDelegate delegate = new FlutterActivityDelegate(this, this); private final FlutterActivityEvents eventDelegate; private final FlutterView.Provider viewProvider; private final PluginRegistry pluginRegistry; public CustomFlutterActivity() { this.eventDelegate = this.delegate; this.viewProvider = this.delegate; this.pluginRegistry = this.delegate;
} @Override
protected void onCreate(Bundle savedInstanceState) { if (injectRouter())
ARouter.getInstance().inject(this); super.onCreate(savedInstanceState); this.eventDelegate.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
registerCustomPlugin(this);
} protected boolean injectRouter() { return false;
} //省略部分代码
.........
......... private static void registerCustomPlugin(PluginRegistry registrar) {
FlutterPluginJumpToAct.registerWith(registrar.registrarFor(FlutterPluginJumpToAct.CHANNEL));
}
}做一个Flutter用的容器,通过容器统一管理需要跳转的Flutter界面
@Route(path = RouterPath.MainPath.MAIN_FLUTTER_CONTAINER, name = "FlutterContainerActivity")public class FlutterContainerActivity extends CustomFlutterActivity { private static String CHANNEL = "com.jzhu.msg/plugin"; private static int TIME_ONE_SECOND = 1000; @Autowired(name = "path")
String path; @Override
protected boolean injectRouter() { return true;
} @Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
initBasicMessageChannel();
} @Override
public FlutterView createFlutterView(Context context) {
WindowManager.LayoutParams matchParent = new WindowManager.LayoutParams(-1, -1);
FlutterNativeView nativeView = this.createFlutterNativeView();
FlutterView flutterView = new FlutterView(FlutterContainerActivity.this, (AttributeSet) null, nativeView);
flutterView.setInitialRoute(path);
flutterView.setLayoutParams(matchParent); this.setContentView(flutterView); return flutterView;
} private void initBasicMessageChannel() { switch (path) { case RouterPath.ModuleFlutterPath.FLUTTER_HOME:
initHomeBasicMessage(); break; case RouterPath.ModuleFlutterPath.FLUTTER_TEST:
initTestBasicMessage(); break;
}
} private void initTestBasicMessage() {
BasicMessageChannel channel = new BasicMessageChannel<String>(
getFlutterView(), CHANNEL, StringCodec.INSTANCE);
channel.setMessageHandler((o, reply) -> {
ToastUtils.show((String)o,3000);
reply.reply("FlutterContainerActivity:回条消息给你");
});
new Handler().postDelayed(() -> channel.send("FlutterContainerActivity:发条消息给你"), TIME_ONE_SECOND);
} private void initHomeBasicMessage() { //todo
}
}Flutter提供的页面
void main() {
runApp(new MaterialApp(
routes: <String, WidgetBuilder>{ '/homepage': (BuildContext context) => new MyHomePage(), '/testpage': (BuildContext context) => new TestPage(),
}, home: new MyHomePage()));
}路由
public interface RouterPath { interface MainPath{
String MAIN_FLUTTER_CONTAINER = "/main/FlutterContainerActivity";
String MAIN_TEST= "/main/TestActivity";
} interface ModuleFlutterPath{
String FLUTTER_HOME= "/homepage";
String FLUTTER_TEST= "/testpage";
}
}点击跳转
ARouter.getInstance() .build(RouterPath.MainPath.MAIN_FLUTTER_CONTAINER) .withString("path", RouterPath.ModuleFlutterPath.FLUTTER_HOME) .navigation();最后:Flutter跳转到Android
通过插件实现,用法参考我之前写一篇Flutter知识点: Flutter与原生(Android)的交互
3. 混合栈问题
如果是Android的页面跳转到Android页面,所以就是普通的Activity栈。
如果是Android的页面跳转到Flutter页面,那么都使用了我们的容器FlutterContainerActivity,所以就是普通的Activity栈,这里面遇到个坑,下面会提出并尝试解决。
如果是Flutter的页面跳转到Flutter页面,那么由Flutter自己内部的栈管理。
如果是Flutter的页面跳转到Android页面,那么自己管自己就好啦。
如果你把Flutter的页面全装到到容器FlutterContainerActivity展示,那就都是普通的Activity栈,省事!
混合跳转注意:
Android某些页面的启动模式Standard,SingleTop,SingleTask,SingleInstance
Flutter页面也存在一些特殊的跳转,popAndPushNamed,pushNamedAndRemoveUntil,popUntil,pushReplacementNamed
以上需要根据实际情况处理,存在特殊跳转,销毁等逻辑
开发中需要特别需要注意的一个问题:
跳转顺序:Android页面 -> Flutter页面(使用了FlutterContainerActivity)-> Flutter页面(原始)
期望结果:Flutter页面(原始)-> Flutter页面(使用了FlutterContainerActivity)-> Android页面
真实结果:Flutter页面(原始)-> Flutter页面(使用了FlutterContainerActivity)-> Flutter页面(homepage) -> Android页面
得到疑问:我们并没有启动homepage,为什么多了一个homepage?
代码猜想:Flutter栈里初始化了一个homepage, 其他Flutter的页面都在这个栈之上。
void main() {
runApp(new MaterialApp(
routes: <String, WidgetBuilder>{
............
}, home: new MyHomePage()));
}如何解决:使用SystemNavigator.pop(),
Tells the operating system to close the application, or the closest equivalent.
WillPopScope参考这篇Flutter学习中的问题记录: 如何监听实体/虚拟返回键和AppBar返回键
class _MyHomePageState extends State<MyHomePage> { static const jumpPlugin = const MethodChannel('com.jzhu.jump/plugin');
Future<Null> _jumpToNative() async { Map<String, String> map = {"path": "/main/TestActivity"}; String result = await jumpPlugin.invokeMethod('jump2act', map);
print(result);
}
Future<bool> _requestPop() {
SystemNavigator.pop(); return new Future.value(false);
}
@override
Widget build(BuildContext context) { return new WillPopScope(
child: new Scaffold(
appBar: new AppBar(
title: new Text("Home Page"),
), body: new Center(
child: new RaisedButton(
child: new Text("跳到TestActivity"), onPressed: _jumpToNative),
), // This trailing comma makes auto-formatting nicer for build methods.
), onWillPop: _requestPop);
}
}4. 混合栈数据问题,以插件的方式解决 。
MethodChannel,EventChanneld的数据传输,用法参考我之前写一篇Flutter知识点: Flutter与原生(Android)的交互
主要举例BasicMessageChannel和BinaryMessages
1_Sd6s3EDGkU8TBS9xLc4Zvw.png
FlutterContainerActivity中初始化,监听,发送
为什么要延迟发送?
因为FlutterView可能还没初始化,这时候无法接收消息
private static String CHANNEL = "com.jzhu.msg/plugin"; private static String CHANNEL_BINARY = "com.jzhu.msg.binary/plugin"; private static int TIME_ONE_SECOND = 1000; private void initTestBasicMessage() {
BasicMessageChannel channel = new BasicMessageChannel<String>(
getFlutterView(), CHANNEL, StringCodec.INSTANCE);
channel.setMessageHandler((o, reply) -> {
ToastUtils.show((String)o,3000);
reply.reply("FlutterContainerActivity:回条消息给你");
}); new Handler().postDelayed(() -> channel.send("FlutterContainerActivity:发条消息给你"), TIME_ONE_SECOND);
ByteBuffer message = ByteBuffer.allocateDirect(256);
message.putDouble(3.14);
message.putInt(123456789); new Handler().postDelayed(() -> getFlutterView().send(CHANNEL_BINARY,message), TIME_ONE_SECOND);
getFlutterView().setMessageHandler(CHANNEL_BINARY, (byteBuffer, binaryReply) -> {
byteBuffer.order(ByteOrder.nativeOrder()); double x = byteBuffer.getDouble(); int n = byteBuffer.getInt();
Log.i("zj", "Received: "+x+ " and "+ n);
binaryReply.reply(message);
});
}Flutter中监听,发送
static const channel = const BasicMessageChannel<String>('com.jzhu.msg/plugin', StringCodec());static const String channelBinary = 'com.jzhu.msg.binary/plugin';void _sendMsg2Android() async {
_replyMsg = await channel.send('TestPage:发条消息给你');
setState(() {}); final WriteBuffer buffer = WriteBuffer()
..putFloat64(3.14)
..putInt32(123456789); final ByteData message = buffer.done();
_replyBinaryMsg = await BinaryMessages.send(channelBinary, message);
_decodeData(message);
} void _initMessageHandler() {
channel.setMessageHandler((String message) async {
_receivedMsg = message;
setState(() {});
});
BinaryMessages.setMessageHandler(channelBinary, (ByteData message) async {
_decodeData(message);
});
} void _decodeData(ByteData message){ final ReadBuffer readBuffer = ReadBuffer(message); final double x = readBuffer.getFloat64(); final int n = readBuffer.getInt32();
print('Received $x and $n');
}
作者:老实巴交的读书人
链接:https://www.jianshu.com/p/5aa4f2a7ed0e
共同学习,写下你的评论
评论加载中...
作者其他优质文章

