一款零侵入的高效Flutter混合栈管理方案,你值得拥有!

block(1)

//初始化FlutterEngine

var engine = FlutterEngine(context.applicationContext)

//初始化BasicMessageChannel

messageChannel = BasicMessageChannel(

engine.dartExecutor,

FLUTTER_MIX_STACK_CHANNEL,

StringCodec.INSTANCE

)

//添加消息监听

messageChannel?.setMessageHandler(messageHandler)

this.initCallback = block

//开始运行dart代码

engine.dartExecutor.executeDartEntrypoint(

DartExecutor.DartEntrypoint.createDefault()

)

//缓存FlutterEngine

FlutterEngineCache.getInstance().put(FLUTTER_ENGINE, engine)

} else {

block(0)

}

}

FlutterEngineCache已经帮我们封装好了FlutterEngine的缓存功能,不过要怎么使用这个缓存呢?

官方提供的FlutterActivity类中有一个withCachedEngine的静态方法,可以帮助我们获取使用缓存的Intent实例,也可以继承FlutterActivity重写getCachedEngineId方法,达到FlutterEngine复用的效果,直接启动FlutterActivity就可以加载Flutter页面,非常的简单方便,但是如果有一些稍微复杂的场景时,FlutterActivity就有些不太够用了。

第二个问题,Flutter 2.0 为我们提供了三种Flutter容器,分别是FlutterActivity(FlutterFragmentActivity)、FlutterFragment和FlutterView,以满足我们不同场景下的使用,从这三个类注释文档的丰富程度上来看,官方是非常推荐我们直接使用FlutterActivity的。简单看下源码就能发现,不管是FlutterActivity还是FLutterFragment,都是基于FlutterView实现的。如果项目有指定的基类需要继承或者要实现原生UI+Flutter UI的情况,或是想要更早的预热Flutter的Widget,FlutterView无疑会更灵活一些,所以这里我就选择使用了普通的Activity+FlutterView,伪代码如下:

class HostActivity : AppCompatActivity(){

var flutterEngine //缓存中拿到的FlutterEngine

var flutterChannel // BasicMessageChannel 下面会有专门的介绍

var flutterView

onCreate(){

//在onCreate方法调用之初,就提前预热FlutterEngine,可以使Widget加载更流畅

flutterEngine.lifecycleChannel.appIsResumed()

//同样在onCreate中发送消息给FluuterEngine,提前替换我们要加载的Widget,方式有过渡效果

flutterChannel.sendMessage(routePath)

super.onCreate()

setContentView(flutterView = createFlutterView())

}

onResume(){

super()

flutterEngine.lifecycleChannel.appIsResumed()

}

onPause(){

super()

flutterEngine.lifecycleChannel.appIsPaused()

}

onDestroy(){

super()

flutterView.detachFromFlutterEngine()

}

}

第三个问题,监听FlutterEngine里Widget栈信息的变化,在MaterialApp初始化的时候,有一个navigatorObservers的参数,支持我们添加navigator的变化信息(Navigator是Flutter提供的页面切换类)。

void main() {

//这里使用了Get框架来演示,但这不是必须的

var getApp = GetMaterialApp(

initialRoute: RouterMapper.ROUTER_HOME,

getPages: [

GetPage(

name: RouterMapper.ROUTER_HOST, //空白的HostView

page: () => Host(),

transition: Transition.rightToLeft),

],

navigatorObservers: [RouteNavigatorObserver()],

);

runApp(getApp);

RouterHelper.registerApp(); //在这里注册消息监听

}

class RouteNavigatorObserver extends NavigatorObserver {

@override

void didPush(Route route, Route? previousRoute) {

// 有Widget入栈 可以从route中获取name信息并同步到Native

}

@override

void didPop(Route route, Route? previousRoute) {

// 有Widget出栈 可以从route中获取name信息并同步到Native

}

@override

void didReplace({Route? newRoute, Route? oldRoute}) {

// 新的Widget替换了前一个Widget 可以从newRoute&oldRoute中获取name信息并同步到Native

}

@override

void didRemove(Route route, Route? previousRoute) {

// 一个Widget被remove了,一般不建议这么做

}

}

通过继承NavigatorObserver类并注册到navigatorObservers中,我们实现了对FlutterEngine中路由信息变化的监听,那么接着来下一个问题,我们如何把消息同步给Native?

**第四个问题,**Flutter提供了三种方式用来和Native交互数据,分别是BasicMessageChannel,MethodChannel和EventChannel,其中前两个是可以双向传递数据的,EventChannel只支持Native给Flutter传递数据,常用语系统消息的一个通知。MethodChannel用来传递方法调用,BasicMessageChannel用来传二进制数据,更适合我们的试用场景,接下来我们需要在Flutter和Native层住的BasicMessageChannel用来数据的交互。

那我们分别在Flutter和Native层创建BasicMessageChannel:

//Flutter

class RouterHelper {

//注册消息通道

static final _routerMessageChannel =

BasicMessageChannel<String?>(“flutter_router_channel”, StringCodec());

static registerApp() {

//防止下面空异常

WidgetsFlutterBinding.ensureInitialized();

//注册消息监听

_routerMessageChannel.setMessageHandler((String? message) async {

if (message != null) {

//native层传递过来的消息

}

});

}

}

//Kotlin

fun initMessageChannel(){

var messageChannel = BasicMessageChannel(

engine.dartExecutor,

“flutter_router_channel”,

StringCodec.INSTANCE)

messageChannel.setMessageHandler{ message, reply ->

//处理Flutter发送的消息

}

}

消息的发送由BasicMessageChannel提供的send方法实现,在上面的一个问题中,我们已经通过监听Navigator来判断Flutter中页面的变化信息,接下来就要在监听方法中,把对应的信息发送到Native层进行处理,在Native层我们可以抽象出来一个接口,让HostActivity实现这接口,通过面向接口编程的方式,把消息分发到当前活跃的HostActivity中。而HostActivity中维护了一个栈来记录Flutter中栈信息的变化。

/**

  • flutter路由变化回调

*/

interface RouteCallback {

//flutter route入栈消息

fun onPush(route: String)

//flutter route出栈消息

fun onPop(route: String)

//flutter route栈替换消息

fun onReplace(newRoute: String, oldRoute: String)

//flutter route被移除的消息

fun onRemove(route: String)

//flutter申请打开Native页面的消息

fun routeNative(nativeRoute: String, params: HashMap<String, Any>? = null)

//flutter route出栈消息

fun getLifecycleOwner(): LifecycleOwner

}

class HostActivity : AppCompatActivity(), RouteCallback {

//记录flutter的路由栈信息

private val routeStack: Stack by lazy {

Stack()

}

//TODO RouteCallback接口的实现方法,在方法中对routeStack进行入栈和出栈操作

}

最后一个问题,我们需要用户进行返回操作的时候,Widget页面要和HostActivity保持同步,例如当前HostActivity只打开了一个Widget,那么这个Widget退出的时候,HostActivity也要同步finish掉,即使FlutterEngine中还存在其他的Widget。我们可以通过HostActivity中维护的routeStack来实现。

override fun onBackPressed() {

//判断当前栈的长度,如果当前HostActivity栈的长度小于等于1,那么Activity就要finsih

if (routeStack.size <= 1) {

super.onBackPressed()

flutterEngine.navigationChannel.popRoute()

}

//正常执行Navigator的pop操作

else {

flutterEngine.navigationChannel.popRoute()

}

}

当然还有一个问题需要注意,有些Widget的返回并不是通过返回键处理的,那我们就需对onPop方法进行一些特殊处理:

override fun onPop(route: String) {

//正常处理出栈逻辑

if (routeStack.isEmpty() && !isFinishing) {

//如果已经全部出栈,则当前HostActivity的业务已完成

finish()

}

}

这样,就能把HostActivity和该宿主内打开的Widget进行关联,做到共同进退,主要的逻辑实现起来也不负责,也不需要使用任何第三方的框架,这样就有了很大的灵活性,尤其是对Flutter来说,Flutter的生态还不是十分成熟,避免使用侵入性过大的框架,也为以后技术的迭代留有足够的空间。


缺点和不足

虽然通过对Flutter内栈信息变化的监听和通过BasicMessageChannel的消息同步来做好混合栈管理,但是目前依然有一些问题需要解决。

1:Flutter和Native页面的返回值监听,OneActivity打开了一个HostActivity并想要在HostActivity退出的时候给OneActivity一个返回值,这个功能实例代码中还没有实现,等有空继续完善该框架。

如何做好面试突击,规划学习方向?

面试题集可以帮助你查漏补缺,有方向有针对性的学习,为之后进大厂做准备。但是如果你仅仅是看一遍,而不去学习和深究。那么这份面试题对你的帮助会很有限。最终还是要靠资深技术水平说话。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。建议先制定学习计划,根据学习计划把知识点关联起来,形成一个系统化的知识体系。

学习方向很容易规划,但是如果只通过碎片化的学习,对自己的提升是很慢的。

我搜集整理过这几年字节跳动,以及腾讯,阿里,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精力),包含知识脉络 + 分支细节

img

在搭建这些技术框架的时候,还整理了系统的高级进阶教程,会比自己碎片化学习效果强太多。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值