flutter_boost中關(guān)于Flutter頁面打開原生頁面并取得返回結(jié)果的分析

以下分析基于flutter_boost分支feature/flutter_1.9_androidx_upgrade

在Android當(dāng)activityA打開activityB之后砾莱,如果想要在activityA中拿到activityB的結(jié)果丹壕,一般是通過onActivityResutl()方法獲得。

這在Flutter當(dāng)中相當(dāng)于Future职辅。原生flutter中取得這個(gè)future很簡(jiǎn)單厌均。因?yàn)閺膄lutterA跳轉(zhuǎn)到flutterB唬滑,其實(shí)還是在一個(gè)activity中實(shí)現(xiàn)的,只需要

      var future = Navigator.of(context).pushNamed("destRouteName");

就可以拿到這個(gè)future棺弊。


但是如果用到了混合棧晶密,比如flutterA-->activityB這樣的話,在flutterA中想要取得activityB的返回結(jié)果模她,就相對(duì)麻煩了稻艰。這里提供的是解決flutter_boost中出現(xiàn)此類問題的方案。

一 分析

1:Flutter側(cè)

在flutter_boost中缝驳,如果在flutterA中想要打開flutterB頁面连锯。在flutterA中可以調(diào)用

var future =await FlutterBoost.singleton.open("flutterB");
future.then((result){
  print($result);
});

此時(shí)如果是默認(rèn)情況下归苍,那么當(dāng)flutterB頁面關(guān)閉時(shí)用狱,將會(huì)在flutterA中打印

{_resultCode__: -1, _requestCode__: -1}

當(dāng)我們?cè)趂lutterA中調(diào)用了FlutterBoost.singleton.open("flutterB")實(shí)際上是進(jìn)入了

  Future<Map<dynamic,dynamic>> open(String url,{Map<dynamic,dynamic> urlParams,Map<dynamic,dynamic> exts}){

    Map<dynamic, dynamic> properties = new Map<dynamic, dynamic>();
    properties["url"] = url;
    properties["urlParams"] = urlParams;
    properties["exts"] = exts;
    return channel.invokeMethod<Map<dynamic,dynamic>>(
        'openPage', properties);
  }

由于我們沒有傳入其他參數(shù),因此urlParamsexts都是null拼弃。方法體中夏伊,通過新創(chuàng)建一個(gè)Map<dynamic,dynamic> properties將所有參數(shù)組裝進(jìn)來。然后進(jìn)入

channel.invokeMethod<Map<dynamic,dynamic>>('openPage', properties);

這個(gè)channel是flutter_boost庫中的BoostChannel吻氧。而BoostChannel其實(shí)內(nèi)部維護(hù)了一個(gè)MethodChannel

class BoostChannel{
  final MethodChannel _methodChannel = MethodChannel("flutter_boost");
  ………
  Future<T> invokeMethod<T>(String method, [ dynamic arguments ]) async {
    assert(method != "__event__");
    return _methodChannel.invokeMethod<T>(method,arguments);
  }
}

2:Android側(cè)

上面在flutterA中打開一個(gè)flutterB頁面溺忧,通過調(diào)用flutter_boost內(nèi)部的open方法實(shí)現(xiàn)咏连。該open方法實(shí)際上是通過methodChannel來調(diào)用Android測(cè)的方法來最終打開flutterB頁面的。其實(shí)在flutter_boost中鲁森,任何一個(gè)flutter頁面都有一個(gè)NewBoostFlutterActivity與之對(duì)應(yīng)祟滴。當(dāng)調(diào)用找到了"openPage"方法時(shí)

 class BoostMethodHandler implements MethodChannel.MethodCallHandler {

        @Override
        public void onMethodCall(MethodCall methodCall, final MethodChannel.Result result) {

            FlutterViewContainerManager mManager = (FlutterViewContainerManager) NewFlutterBoost.instance().containerManager();
            switch (methodCall.method) {
                ……
                case "openPage": {
                    try {
                        Map<String, Object> params = methodCall.argument("urlParams");
                        Map<String, Object> exts = methodCall.argument("exts");
                        String url = methodCall.argument("url");

                        mManager.openContainer(url, params, exts, new FlutterViewContainerManager.OnResult() {
                            @Override
                            public void onResult(Map<String, Object> rlt) {
                                if (result != null) {
                                    result.success(rlt);
                                }
                            }
                        });
                    } catch (Throwable t) {
                        result.error("open page error", t.getMessage(), t);
                    }
                }
                break;
               ……
                default: {
                    result.notImplemented();
                }
            }
        }
    }

在openPage中取出參數(shù)。然后調(diào)用

mManager.openContainer(url, params, exts, new FlutterViewContainerManager.OnResult() {
    @Override
    public void onResult(Map<String, Object> rlt) {
        if (result != null) {
            result.success(rlt);
        }
    }
});

而剛才我們?cè)陉P(guān)閉flutterB頁面時(shí)歌溉,flutterA頁面中打印了

{_resultCode__: -1, _requestCode__: -1}

這個(gè)打印結(jié)果就是通過

result.success(rlt);

返回的垄懂。而這個(gè)onResult()方法是在FlutterViewContainerManager中調(diào)用的

void setContainerResult(IContainerRecord record,int requestCode, int resultCode, Map<String,Object> result) {
    IFlutterViewContainer target = findContainerById(record.uniqueId());
    if(target == null) {
        Debuger.exception("setContainerResult error, url="+record.getContainer().getContainerUrl());
    }
    if (result == null) {
        result = new HashMap<>();
    }
    result.put("_requestCode__",requestCode);
    result.put("_resultCode__",resultCode);
    final OnResult onResult = mOnResults.remove(record.uniqueId());
    if(onResult != null) {
        onResult.onResult(result);
    }
}

而setContainerResult()在兩個(gè)地方進(jìn)行了調(diào)用。

(1) 在onDestory()
 NewBoostFlutterAcitivity.onDestory();
    delegate.onDestroyView(); 
                mSyncer.onDestroy(); //IOperateSyncer的具體實(shí)現(xiàn)是ContainerRecord

在這個(gè)具體顯示中返回了-1

 @Override
public void onDestroy() {
    Utils.assertCallOnMainThread();
    if (mState != STATE_DISAPPEAR) {
        Debuger.exception("state error");
    }
    mState = STATE_DESTROYED;
    mProxy.destroy();
    mManager.removeRecord(this);
    mManager.setContainerResult(this,-1,-1,null);
}
(2)在onActivityResult()
NewBoostFlutterAcitivity.onActivityResult()
            delegate.onActivityResult(requestCode, resultCode, data);

在delegate中

void onActivityResult(int requestCode, int resultCode, Intent data) {
    mSyncer.onActivityResult(requestCode,resultCode,data);
    ……
    mSyncer.onContainerResult(requestCode,resultCode,result);
    ……
}

二:結(jié)論

在回顧一下問題痛垛,如果我們要在flutterA頁面中打開B頁面草慧,并且想要獲得B頁面的返回結(jié)果。需要區(qū)別B頁面是Flutter頁面還是Android原生頁面匙头。

1:B頁面是Flutter頁面

那就要根據(jù)實(shí)際情況重新在onDestory中返回不同的參數(shù)漫谷,而不是一刀切的返回-1,-1蹂析,null

setContainerResult(IContainerRecord record,int requestCode, int resultCode, Map<String,Object> result)
2:B頁面是原生頁面

由于methodChannel中的MethodChannel.Result對(duì)象只有在FlutterBoostPlugin中的OnResult中的onResult()中可以調(diào)用舔示。

            FlutterViewContainerManager mManager = (FlutterViewContainerManager) NewFlutterBoost.instance().containerManager();

 mManager.openContainer(url, params, exts, new FlutterViewContainerManager.OnResult() {
                            @Override
                            public void onResult(Map<String, Object> rlt) {
                                if (result != null) {
                                    result.success(rlt);
                                }
                            }
                        });

因此代碼如下

 FlutterViewContainerManager mManager = (FlutterViewContainerManager) NewFlutterBoost.instance().containerManager();

mManager.setContainerResult(參數(shù)設(shè)置);

參數(shù)需要自己設(shè)置。

上面的解決方案并不完善电抚,只能暫時(shí)解決業(yè)務(wù)問題斩郎。如果看官有更好的處理方案,歡迎指教喻频。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末缩宜,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子甥温,更是在濱河造成了極大的恐慌锻煌,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件姻蚓,死亡現(xiàn)場(chǎng)離奇詭異宋梧,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)狰挡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門捂龄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人加叁,你說我怎么就攤上這事倦沧。” “怎么了它匕?”我有些...
    開封第一講書人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵展融,是天一觀的道長。 經(jīng)常有香客問我豫柬,道長告希,這世上最難降的妖魔是什么扑浸? 我笑而不...
    開封第一講書人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮燕偶,結(jié)果婚禮上喝噪,老公的妹妹穿的比我還像新娘。我一直安慰自己指么,他們只是感情好仙逻,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著涧尿,像睡著了一般系奉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上姑廉,一...
    開封第一講書人閱讀 51,488評(píng)論 1 302
  • 那天缺亮,我揣著相機(jī)與錄音,去河邊找鬼桥言。 笑死萌踱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的号阿。 我是一名探鬼主播并鸵,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼扔涧!你這毒婦竟也來了园担?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤枯夜,失蹤者是張志新(化名)和其女友劉穎弯汰,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體湖雹,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡咏闪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了摔吏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鸽嫂。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖征讲,靈堂內(nèi)的尸體忽然破棺而出据某,到底是詐尸還是另有隱情,我是刑警寧澤稳诚,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布哗脖,位于F島的核電站,受9級(jí)特大地震影響扳还,放射性物質(zhì)發(fā)生泄漏才避。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一氨距、第九天 我趴在偏房一處隱蔽的房頂上張望桑逝。 院中可真熱鬧,春花似錦俏让、人聲如沸楞遏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽寡喝。三九已至,卻和暖如春勒奇,著一層夾襖步出監(jiān)牢的瞬間预鬓,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來泰國打工赊颠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留格二,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓竣蹦,卻偏偏與公主長得像顶猜,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子痘括,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容