以下分析基于flutter_boost分支feature/flutter_1.9_androidx_upgrade
uniqueId标志着flutter侧的一个页面。可以通过uniqueId来关闭指定页面。那么该如何获取呢?
1:Android侧创建
ContainerRecord中提供了创建uniqueId方法
public static String genUniqueId(Object obj) {
return System.currentTimeMillis() + "-" + obj.hashCode();
}
(1):当Android侧接收到来自Flutter侧的”openPage"请求时,调用了FlutterViewContainerManager.openContainer()方法中。生成了uniqueId。
void openContainer(String url, Map urlParams, Map exts,OnResult onResult) {
……
final String uniqueId = ContainerRecord.genUniqueId(url);
urlParams.put(IContainerRecord.UNIQ_KEY,uniqueId);
if(onResult != null) {
mOnResults.put(uniqueId,onResult);
}
NewFlutterBoost.instance().platform().openContainer(context,url,urlParams,requestCode,exts);
}
生成的uniqueId,被放到了urlParams这个Map中。随后被传入到了Platform.openContainer()方法中。Platform的实例是在NewFlutterBoost中创建的。而platform.openContainer()方法调用的则是我们在Application中自定义的route类中的方法。
public void openContainer(Context context, String url, Map urlParams, int requestCode, Map exts) {
router.openContainer(context, url, urlParams, requestCode, exts);
}
在Application中,实际上调用的有时PageRoute的openPageByUrl()
INativeRouter router = new INativeRouter() {
@Override
public void openContainer(Context context, String url, Map urlParams, int requestCode, Map exts) {
String assembleUrl = Utils.assembleUrl(url, urlParams);
PageRouter.openPageByUrl(context, assembleUrl, urlParams);
}
};
进入PageRoute就可以看到最终开始创建了NewBoostFlutterActivity,用来承载flutterView。
Intent intent = NewBoostFlutterActivity.withNewEngine().url(pageName.get(path)).params(params)
.backgroundMode(NewBoostFlutterActivity.BackgroundMode.opaque).build(context);
context.startActivity(intent);
此时我们来到NewBoostFlutterActivity的onCreate()中,其中与uniqueId相关的只有
setContentView(createFlutterView());
在创建FlutterView时,其实还是交给了委托类FlutterActivityAndFragmentDelegate
@NonNull
private View createFlutterView() {
return delegate.onCreateView(
null /* inflater */,
null /* container */,
null /* savedInstanceState */);
}
委托类在调用onCreateView进行flutterView的创建时,调用了IOperateSyncer接口的onCreate()。该接口的具体实现是ContainerRecord。
mSyncer.onCreate();
最终进入的是ContainerRecord的onCreate()实现。
@Override
public void onCreate() {
Utils.assertCallOnMainThread();
if (mState != STATE_UNKNOW) {
Debuger.exception("state error");
}
mState = STATE_CREATED;
mProxy.create();
}
在代理mProxy.create()中,开始进行methodChannel的native侧到flutter侧的通信。寻找“didInitPageContainer”该名字的方法。
private void create() {
if (mState == STATE_UNKNOW) {
invokeChannelUnsafe("didInitPageContainer",
mContainer.getContainerUrl(),
mContainer.getContainerUrlParams(),
mUniqueId
);
//Debuger.log("didInitPageContainer");
mState = STATE_CREATED;
}
}
……
public void invokeChannelUnsafe(String method, String url, Map params, String uniqueId) {
HashMap args = new HashMap<>();
args.put("pageName", url);
args.put("params", params);
args.put("uniqueId", uniqueId);
NewFlutterBoost.instance().channel().invokeMethodUnsafe(method, args);
}
最终就调到了FlutterBoostPlugin中的invokeMethod()
public void invokeMethod(final String name, Serializable args, MethodChannel.Result result) {
if ("__event__".equals(name)) {
Debuger.exception("method name should not be __event__");
}
mMethodChannel.invokeMethod(name, args, result);
}
2:Flutter侧接收
在ContainerCoordinator中,可以找到flutter被调用的方法“didInitPageContainer”
case "didInitPageContainer":
{
String pageName = call.arguments["pageName"];
Map params = call.arguments["params"];
String uniqueId = call.arguments["uniqueId"];
_nativeContainerDidInit(pageName, params, uniqueId);
}
break;
在_nativeContainerDidInit()中开始创建ContainerSettings
bool _nativeContainerDidInit(String name, Map params, String pageId) {
performContainerLifeCycle(_createContainerSettings(name, params, pageId),
ContainerLifeCycle.Init);
return true;
}
uniqueId于是就传入了Flutter侧。在flutter侧可以通过
String uniqueId=BoostContainer.of(context).uniqueId;
获得当前页面的uniqueId。