引入 Flutter 實(shí)戰(zhàn)開(kāi)發(fā)入門

本文目標(biāo)

  1. 將 Flutter 引入到日常的開(kāi)發(fā);
  2. 熟悉引入 Flutter 開(kāi)發(fā)后由開(kāi)發(fā)到交付產(chǎn)品的流程;

一個(gè)簡(jiǎn)單的流程圖,來(lái)表示一下引入 Flutter 后的開(kāi)發(fā)流程:


三個(gè) channel

通常情況下,在現(xiàn)有工程中接入 Flutter 是大部分開(kāi)發(fā)者的選擇,即混編。這既兼顧到了大部分開(kāi)發(fā)者以 Native 開(kāi)發(fā)的現(xiàn)狀,又能嘗一下螃蟹的味道。基于此,我們來(lái)看一下一個(gè)比較重要的概念 channel。

在混編過(guò)程中避免不了原生與 Flutter 側(cè)的數(shù)據(jù)傳遞和方法相互調(diào)用,F(xiàn)lutter 提供了三個(gè) channel 專門去解決這個(gè)比較重要的問(wèn)題。

這三個(gè) channel 分別是 MessageChannel,MethodChannel,EventChannel,下面分別看一下。

以 Flutter 與 iOS 混編為例,以源碼形式集成 Flutter Module ,執(zhí)行 pod install 之后會(huì)自動(dòng)生成以下三個(gè) channel 類。

FlutterBasicMessageChannel

作用:用于 Native 與 Flutter 傳遞數(shù)據(jù)。下面是該類提供的三個(gè)比較重要的方法。

// Native 向 Flutter 側(cè)傳遞數(shù)據(jù)
- (void)sendMessage:(id _Nullable)message;
 
// Native 向 Flutter 側(cè)傳遞數(shù)據(jù),并接收 Flutter 側(cè)的回調(diào)
- (void)sendMessage:(id _Nullable)message reply:(FlutterReply _Nullable)callback;
 
// 注冊(cè)一個(gè)回調(diào),用于接收 Flutter 側(cè)返回的回調(diào) 
- (void)setMessageHandler:(FlutterMessageHandler _Nullable)handler;

FlutterMethodChannel

作用:用于 Native 與 Flutter 之間方法的相互調(diào)用。下頁(yè)是該類提供的三個(gè)比較重要的方法。

// Native 調(diào)用 Flutter 側(cè)的方法,并傳參
- (void)invokeMethod:(NSString*)method arguments:(id _Nullable)arguments;
 
// Native 調(diào)用 Flutter 側(cè)的方法,并傳參,接收 Flutter 側(cè)返回的回調(diào)
- (void)invokeMethod:(NSString*)method
           arguments:(id _Nullable)arguments
              result:(FlutterResult _Nullable)callback;
 
// 監(jiān)聽(tīng) Flutter 側(cè)的方法回調(diào)并做相應(yīng)處理
- (void)setMethodCallHandler:(FlutterMethodCallHandler _Nullable)handler;

FlutterEventChannel

作用:Native 向 Flutter 側(cè)發(fā)送通知。下面是該類發(fā)送通知的核心方法。

// Native 向 Flutter 側(cè)發(fā)送通知,F(xiàn)lutter 側(cè)接收到通知后可以執(zhí)行相應(yīng)的操作
- (void)setStreamHandler:(NSObject<FlutterStreamHandler>* _Nullable)handler;

Flutter 與 Android 混編,以源碼形式集成 Flutter Module 時(shí),在 build 之后也會(huì)生成對(duì)應(yīng)的三個(gè) channel,含義和用法與上面是一樣的,就不再列出介紹了。

看完上面三個(gè) channel,是不是感覺(jué)這個(gè)交互方式有點(diǎn)熟悉。是不是跟 Native 接入 Hybrid 后兩者之間的交互方式是類似的的,區(qū)別在于 Native 無(wú)法向 Hybrid 直接發(fā)送通知。你細(xì)品!

三種開(kāi)發(fā)模式

三種開(kāi)發(fā)模式是本篇的重點(diǎn),但這里也不做具體詳細(xì)的介紹,只介紹其中的關(guān)鍵銜接之處。

Android 與 Flutter 混編

將 Flutter 集成到現(xiàn)有 Android 工程可能參考官方文檔,這里主要介紹一下 Android 與 Flutter 銜接的點(diǎn)。

在以 Flutter Module 源碼集成后,會(huì)生成一個(gè) FlutterView 的類,用于 Android 調(diào)起 Flutter 側(cè)的視圖。實(shí)例化 FlutterView 的一個(gè)對(duì)象并添加到 Android 端的殼 activity 中,即可以實(shí)現(xiàn) Android 加載 Flutter 側(cè)視圖的功能。關(guān)鍵代碼如下

FlutterView flutterView = new FlutterView(this);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
FrameLayout flContainer = findViewById(R.id.layout001);
flContainer.addView(flutterView, lp);

Native 與 Flutter 之間的數(shù)據(jù)傳遞,方法調(diào)用,通知?jiǎng)t以方法相互調(diào)用為例說(shuō)明。

MethodChannel nativeChannel = new MethodChannel(flutterEngine.getDartExecutor(), 'channel_native');
nativeChannel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
    @Override
    public void onMethodCall(MethodCall call, MethodChannel.Result result) {
      switch (call.method){
            case "openSecondNative":
                // 這里執(zhí)行具體的操作...
                result.success("成功打開(kāi)第二個(gè)原生頁(yè)面");
                break;
            case "backFirstNative":
                // 這里執(zhí)行具體的操作...
                result.success("成功返回第一個(gè)原生頁(yè)面");
                break;
            case "backAction":
                // 這里執(zhí)行具體的操作...
                result.success("成功通過(guò)虛擬按鍵返回第一個(gè)原生頁(yè)面");
                break;
            default :
                result.notImplemented();
                break;
 
        }
  }
});

iOS 與 Flutter 混編

將 Flutter 集成到現(xiàn)有 iOS 工程可能參考官方文檔,這里也主要介紹一下 Android 與 Flutter 銜接的點(diǎn)。

在以 Flutter Module 源碼集成后,會(huì)生成一個(gè) FlutterViewController 的類,用于 iOS 調(diào)起 Flutter 側(cè)的視圖。實(shí)例化 FlutterViewController 的一個(gè)對(duì)象并 push 或 present 該對(duì)象,即可以實(shí)現(xiàn) iOS 加載 Flutter 側(cè)視圖的功能。關(guān)鍵代碼如下

let flutterVC = FlutterViewController()
flutterVC.fd_prefersNavigationBarHidden = true
flutterVC.setInitialRoute(paramsJsonStr)
let messageChannel = FlutterMethodChannel(name: "channel_native", binaryMessenger: flutterVC.binaryMessenger)
messageChannel.setMethodCallHandler { [weak self] call, result in
    if call.method == "backToMineViewController" {
        self?.navigationController?.popViewController(animated: true)
        if let tmpArguments = call.arguments as? [AnyHashable: Any] {
            let message = tmpArguments["message"] as? String
            LoadingManager.showText(message)
        }
     } else if call.method == "didSelectCell" {
        if let tmpArguments = call.arguments as? [AnyHashable: Any] {
            self?.handleJump(with: tmpArguments)
        }
    }
}
flutterVC.hidesBottomBarWhenPushed = true
navigationController?.pushViewController(flutterMessageCenterVC, animated: true)

Native 與 Flutter 之間的數(shù)據(jù)傳遞,方法調(diào)用,通知也以他們之間的方法相互調(diào)用為例說(shuō)明??瓷戏酱a。

純 Flutter 開(kāi)發(fā)

對(duì)于一個(gè)全新的 App 來(lái)說(shuō),選擇純 Flutter 方式開(kāi)發(fā)或許是一個(gè)不錯(cuò)的選擇。
一是不用去踩混編的坑,二是越純粹越簡(jiǎn)單,包袱也少;
開(kāi)發(fā)完成之后,分別構(gòu)建各端上的包即可。
一處開(kāi)發(fā),到處運(yùn)行,簡(jiǎn)直不能太愛(ài)了!

構(gòu)建 ipa 或 apk 包

構(gòu)建包首先要注意的是需要支持哪些架構(gòu)類型,這關(guān)系到你的包發(fā)行的廣度的問(wèn)題。下面分別看一下 android 和 iOS 支持的架構(gòu)類型。

Android 支持的架構(gòu)

架構(gòu)類型 簡(jiǎn)介
arm64-v8a 第8代,64位,包含AArch32、AArch64兩個(gè)執(zhí)行狀態(tài)對(duì)應(yīng)32、64bit
armeabi 第5代 ARM v5TE,使用軟件浮點(diǎn)運(yùn)算,兼容所有ARM設(shè)備,通用性強(qiáng),速度慢
armeabi-v7a 第7代 ARM v7,使用硬件浮點(diǎn)運(yùn)算,具有高級(jí)擴(kuò)展功能(從2010年起)
x86 intel 32位,一般用于平板(從2011年起)
x86_64 intel 64位,一般用于平板(從2014年起)
mips 比較少見(jiàn)(目前市面幾乎沒(méi)有采用這種架構(gòu)的手機(jī))
mips64 比較少見(jiàn)(目前市面幾乎沒(méi)有采用這種架構(gòu)的手機(jī))

設(shè)置支持特定架構(gòu)的包,可以在主工程 app 文件夾下的 build.gradle 添加下面的代碼

defaultConfig {
    ndk {
        abiFilters "armeabi-v7a", "x86", "armeabi"
    }
}

iOS 支持的架構(gòu)

架構(gòu)類型 簡(jiǎn)介
armv7s iPhone5、iPhone5C、iPad4(iPad with Retina Display)
armv7 iPhone4、iPhone4S、iPad、iPad2、iPad3(The New iPad)、iPad mini、iPod Touch
armv6 iPhone, iPhone2, iPhone3G, 第一代、第二代 iPod Touch(一般不需要去支持)
arm64e iphone XS、iphone XS Max、iphoneXR、iphone11、iphone11 Pro
arm64 iPhone 5S、iPhone 6、iPhone 6 Plus、iPhone 6S、6S Plus、iPhone 7、7 Plus、iPad (2018)、iPhone 8、iPhone 8 Plus、and iPhone X
x86_64 Mac指令集:x86_64是針對(duì)x86架構(gòu)的64位處理器
i386 Mac指令集:i386是針對(duì)intel通用微處理器32位處理器

可以在 Xcode 中如下圖所示的位置設(shè)置支持的架構(gòu)類型


安裝

Android apk 包安裝

adb install xxx.apk

iOS ipa 包安裝

Enterprise 企業(yè)包,tf 包

最后

也許一開(kāi)始引入 Flutter 會(huì)面臨各種各樣的問(wèn)題。
比如學(xué)習(xí)成本,新技術(shù)的不完備性等風(fēng)險(xiǎn),但后期帶來(lái)的收益也是很可觀的。
業(yè)務(wù)是在不斷變化的,對(duì)高效率的追求卻是不變的!Flutter 也許會(huì)是一個(gè)相對(duì)不錯(cuò)的選擇!

推薦學(xué)習(xí)實(shí)踐:

Flutter、Android混合開(kāi)發(fā)實(shí)踐:
https://juejin.cn/post/6844904065881604109

Flutter、iOS混合開(kāi)發(fā)實(shí)踐:
https://juejin.cn/post/6844904087918477320

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 16宿命:用概率思維提高你的勝算 以前的我是風(fēng)險(xiǎn)厭惡者,不喜歡去冒險(xiǎn),但是人生放棄了冒險(xiǎn),也就放棄了無(wú)數(shù)的可能。 ...
    yichen大刀閱讀 8,174評(píng)論 0 4
  • 公元:2019年11月28日19時(shí)42分農(nóng)歷:二零一九年 十一月 初三日 戌時(shí)干支:己亥乙亥己巳甲戌當(dāng)月節(jié)氣:立冬...
    石放閱讀 7,526評(píng)論 0 2

友情鏈接更多精彩內(nèi)容