flutter_boost中uniqueId在Flutter侧是如何获得的?

以下分析基于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<String, Object> urlParams, Map<String, Object> 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<String, Object> urlParams, int requestCode, Map<String, Object> exts) {
    router.openContainer(context, url, urlParams, requestCode, exts);
}

在Application中,实际上调用的有时PageRoute的openPageByUrl()

 INativeRouter router = new INativeRouter() {
            @Override
            public void openContainer(Context context, String url, Map<String, Object> urlParams, int requestCode, Map<String, Object> 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<String, Object> 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。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,408评论 4 371
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,690评论 2 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,036评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,726评论 0 221
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,123评论 3 296
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,037评论 1 225
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,178评论 2 318
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,964评论 0 213
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,703评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,863评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,333评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,658评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,374评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,195评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,988评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,167评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,970评论 2 279

推荐阅读更多精彩内容