flutter_boost在iOS端的简单使用

Flutter简介(摘自Flutter github)

新一代Flutter-Native混合解决方案。 FlutterBoost是一个Flutter插件,它可以轻松地为现有原生应用程序提供Flutter混合集成方案。FlutterBoost的理念是将Flutter像Webview那样来使用。在现有应用程序中同时管理Native页面和Flutter页面并非易事。 FlutterBoost帮你处理页面的映射和跳转,你只需关心页面的名字和参数即可(通常可以是URL)。

接入

在配置文件pubspec.yaml中加入依赖:

  flutter_boost: ^0.0.420

flutter_boost:
    git:
      url: 'https://github.com/alibaba/flutter_boost.git'
      ref: '0.0.420'

iOS端的简单实用(swift工程)

Flutter端示例代码:
  • 1、工程中app首页(一般为main.dart)添加如下代码:
import 'package:flutter_boost/flutter_boost.dart';
import './pages/TestDemoPage.dart';

// 此处的platform以及messageChannel在具体的page页面会用到, 他们是全局的实例对象
const MethodChannel platform = const MethodChannel("infosearch.flutter.io/flutterCallNative");
const BasicMessageChannel messageChannel = const BasicMessageChannel("infosearch.flutter.io/basic", StandardMessageCodec());

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
    @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State{
@override
  void initState() {
    super.initState();
    FlutterBoost.singleton.registerPageBuilders({
      'searchinfo_demo': (pageName, params, _) => TestDemoPage(params: params),
      'searchinfo_news_favorites': (pageName, params, _) => NewsList(params: params, pageName: pageName),
      'searchinfo_news_collection': (pageName, params, _) => NewsList(params: params, pageName: pageName),
      'searchinfo_news_history': (pageName, params, _) => NewsList(params: params, pageName: pageName),
    });
    FlutterBoost.handleOnStartPage();
  }

  @override
  Widget build(BuildContext context) {
    return new CupertinoApp(
      title: "Flutter Boost demo",
      debugShowCheckedModeBanner: false,
      builder: FlutterBoost.init(postPush: _onRoutePushed),
      home: Container(),
    );
  }

  void _onRoutePushed(String pageName, String uniqueId, Map params, Route route, Future _) {
    print('flutter main page name is $pageName');
  }
}
  • 2、接main中注册的TestDemoPage.dart页面代码:
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_boost/flutter_boost.dart';
import 'package:flutter_module/main.dart';

class TestDemoPage extends StatefulWidget {
  TestDemoPage({Key key, this.params}) : super(key: key);

  @required
  final Map params;

  _TestDemoPageState createState() => _TestDemoPageState();
}

class _TestDemoPageState extends State {

void _receiveMessage() {
    messageChannel.setMessageHandler((message) async {
      print('message: $message, current page is ${widget.pageName}');
      return '返回Native端的数据';
    });
  }

@override
  void initState() { 
    super.initState();
  // 初始化后开始监听通过BasicMessageChannel从Native传递过来的数据
    _receiveMessage();
  }
// 通过调用方法关闭当前页面,back按钮可调用此函数
void _closeCurrentPage() {
    FlutterBoost.singleton.closePageForContext(context);
}

// 以下三个函数是通过MethodChannel实现Flutter调用Native的方法
 void _showLoading() async {
    await platform.invokeMethod('showLoading');
  }

  void _dismissLoading() async {
    await platform.invokeMethod('dismissLoading');
  }

  void _showTips() async {
    await platform.invokeMethod('showTips', {'tips': '请求失败,请稍后重试'});
  }

// 此方法需要绑定到具体的事件上去
void _openNativePage(dynamic obj) async {
      // 如果参数obj是model,需要调用model对应的类名.toJson()方法转为json对象
      Map jsonObj;
      // jsonObj = (obj as News.Result).toJson();
      
      // 因为我要跳转native的页面故加一个type字段
      // 每个Flutter的页面都是从native调用进行实例化FlutterViewContainer的
      // native通过解析此处的type字段决定跳转Native还是Flutter页面
      jsonObj["type"] = "App";
      FlutterBoost.singleton.openPage("news_detail", jsonObj);
}

@override
  Widget build(BuildContext context) {
    return new CupertinoPageScaffold(
      navigationBar: new CupertinoNavigationBar(
        backgroundColor: Color(0xffDB2C30),
        middle: Text(
          widget.params['title'],
          style: new TextStyle(color: CupertinoColors.white),
        ),
        leading: CupertinoButton(
            padding: EdgeInsets.only(top: 0, bottom: 0, left: 0),
            child: Icon(
              Icons.arrow_back,
              color: CupertinoColors.white,
            ),
            onPressed: () {
              _closeCurrentPage();
            }),
      ),

      child: new Container(),
    );
  } 
}
iOS端代码(swift):

主要实现一个类FlutterRouter.swift

import Foundation
import UIKit
import flutter_boost
import EasyNavigationbar

class FlutterRouter: NSObject, FLBPlatform {
    
    lazy var navigationController: UINavigationController? = {
        let nav = UIViewController.easy_currentViewController()?.navigationController
        return nav
    }()
    
    var _fvc: FlutterViewController?
    
    var fvc: FlutterViewController? {
        didSet {
            _fvc = fvc
            setupFlutterCallNative()
        }
    }
    
    private static var share: FlutterRouter?
    class func sharedRouter() -> FlutterRouter {
        guard let instance = share else {
            share = FlutterRouter.init()
            FlutterBoostPlugin.sharedInstance()?.startFlutter(with: share!, onStart: { (fvc) in
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.001, execute: {
                    FlutterRouter.sharedRouter().fvc = fvc
                })
            })
            return share!
        }
        return instance
    }

    // Flutter调用此函数的方式: 
    // FlutterBoost.singleton.openPage("news_detail", jsonObj);
    // Native可直接调用
    func openPage(_ name: String, params: [AnyHashable : Any], animated: Bool, completion: @escaping (Bool) -> Void) {
        print("打开页面传递的参数 = \(params)")
        
        // ["type": "Flutter", "session": session, "title": "title"]
        guard let value = params["type"], let type = value as? String else {
            return
        }
        
        // type为调转目标为App or Flutter
        // params的所有键值对可以自己定义,我的格式是["type": "Flutter", "session": session, "title": "title"]
        switch type {
        case "App":
            // 跳转原生以及传递参数
            openNativeController(with: name, params: params, animated: animated)
        default:
            // 跳转Flutter页面以及传参
            if let isPresent = params["present"], (isPresent as? Bool) == true{
                let vc = CFLBFlutterViewContainer.init();
                vc.setName(name, params: params)
                navigationController?.present(vc, animated: animated, completion: {})
            } else {
                let vc = CFLBFlutterViewContainer.init();
                vc.setName(name, params: params)
                vc.hidesBottomBarWhenPushed = true
                navigationController?.easy_pushViewController(vc, animated: animated)
            }
        }
    }

     // Flutter调用此函数的方式: 
    //  FlutterBoost.singleton.closePageForContext(context);
    func closePage(_ uid: String, animated: Bool, params: [AnyHashable : Any], completion: @escaping (Bool) -> Void) {
        print("关闭页面传递的参数 = \(params)")
        if let vc = navigationController?.presentedViewController,
            vc.isKind(of: CFLBFlutterViewContainer.self),
            (vc as! CFLBFlutterViewContainer).uniqueIDString == uid{
            vc.dismiss(animated: animated, completion: {})
        } else {
            navigationController?.popViewController(animated: animated)
        }
    }
    
    func accessibilityEnable() -> Bool {
        return true
    }
    
    // 判断跳转原生各Native页面处理
    private func openNativeController(with pageName: String, params: [AnyHashable : Any], animated: Bool) {
        
        switch pageName {
        case "news_detail":
            let vc = UIViewController.init()
            navigationController?.easy_pushViewController(vc, animated: true)
        default:
            let vc = NativeViewController.init()
            vc.navBar.title = params["title"] as? String
            vc.hidesBottomBarWhenPushed = true
            navigationController?.easy_pushViewController(vc, animated: true)
        }
    }
    
    // MARK: FlutterCallNative Flutter调用Native在此处回调,处理完成还可以通过result(params)回调params数据给flutter使用
    private func setupFlutterCallNative() {
        // 用于Flutter 调用 Native
        // 这个channelname必须与Native里接收的一致
        guard let vc = _fvc else {
            return
        }
        let flutterCallNativeChannel = FlutterMethodChannel(name: "infosearch.flutter.io/flutterCallNative", binaryMessenger: vc)
        //FlutterMethodCall call, FlutterResult result
        flutterCallNativeChannel.setMethodCallHandler { (call, result) in
            print("method: \(call.method)")
            
            print("arguments: \(String(describing: call.arguments))")
            switch call.method {
            case "showLoading":
                YZTProgressHUD.show()
            case "dismissLoading":
                YZTProgressHUD.dismiss()
            case "showTips":
                if let arg = call.arguments as? [String: String], let tips = arg["tips"] {
                    YZTProgressHUD.showText(tips)
                }
            default:
                result(FlutterMethodNotImplemented)
            }
        }
    }
    
    // BasicMessageChannel在native的实现代码,需要发送消息给Flutter就调用此处函数:
    // FlutterRouter.sharedRouter().setupBasicMessageChannel(pageName: "collect")
    // 入参可以自定义,在Flutter端各页面可用此参数来区分是从哪里传递过来的数据
    func setupBasicMessageChannel(pageName: String) {
        if let vc = _fvc {
            let messageChannel = FlutterBasicMessageChannel.init(name: "infosearch.flutter.io/basic", binaryMessenger: vc)
            messageChannel.sendMessage(pageName)
        }
    }
}

你可能感兴趣的:(flutter_boost在iOS端的简单使用)