老闆喜歡的,Flutter實現多平臺開發

一.Flutter簡介

跨平臺

Flutter的目標是使同一套代碼同時運行在Android和iOS系統上,而且擁有媲美原生應用的性能。java

flutter所支持的平臺:react

  1. 移動端
  2. 網頁
  3. Windows、Linux和macOS

高性能

技術類型 渲染方式 性能 開發效率 動態 表明框架
H5+原生 封裝原生(相機,聯繫人,設備等)+webview 支持 ionic,cordova
js+原生渲染 原生的控件渲染 支持 weex,react native
原生+自繪引擎 Skia 2D渲染引擎 flutter

學習資源

  1. flutter中文網:flutterchina.club/
  2. flutter插件:pub.flutter-io.cn/
  3. flutter控件介紹:toly1994328.gitee.io/flutter_web…
  4. dart語言:www.dartcn.com/
  5. 開源項目:github

二.Flutter原理

框架結構

Flutter Frameworkandroid

這是一個純 Dart實現的 SDK,它實現了一套基礎庫,自底向上,咱們來簡單介紹一下:c++

  • 底下兩層(Foundation和Animation、Painting、Gestures)是dart UI層,對應的是Flutter中的dart:ui包,它是Flutter引擎暴露的底層UI庫,提供動畫、手勢及繪製能力。
  • Rendering層,這一層是一個抽象的佈局層,它依賴於dart UI層,Rendering層會構建一個UI樹,當UI樹有變化時,會計算出有變化的部分,而後更新UI樹,最終將UI樹繪製到屏幕上。Rendering層能夠說是Flutter UI框架最核心的部分,它除了肯定每一個UI元素的位置、大小以外還要進行座標變換、繪製(調用底層dart:ui)。
  • Widgets層是Flutter提供的的一套基礎組件庫,在基礎組件庫之上,Flutter還提供了 Material 和Cupertino兩種視覺風格的組件庫。而咱們Flutter開發的大多數場景,只是和這兩層打交道

Flutter enginegit

這是一個純 C++實現的 SDK,其中包括了 Skia引擎、Dart運行時、文字排版引擎等。在代碼調用 dart:ui庫時,調用最終會走到Engine層,而後實現真正的繪製邏輯。github

如何繪製

  1. RenderObject:渲染樹中全部節點的基類,定義了佈局、繪製和合成相關的接口web

  2. RendererBinding:是渲染樹和Flutter引擎的膠水層,負責管理幀重繪、窗口尺寸和渲染相關參數變化的監聽。windows

  3. 控件樹中的每一個控件經過實現RenderObjectWidget#createRenderObject(BuildContext context) → RenderObject方法來建立對應的不一樣類型的RenderObject對象,組成渲染對象樹安全

三.混合開發

github地址:

github.com/alibaba/flu…markdown

介紹:阿里出品

新一代Flutter-Native混合解決方案。 FlutterBoost是一個Flutter插件,它能夠輕鬆地爲現有原生應用程序提供Flutter混合集成方案。FlutterBoost的理念是將Flutter像Webview那樣來使用。在現有應用程序中同時管理Native頁面和Flutter頁面並不是易事。 FlutterBoost幫你處理頁面的映射和跳轉,你只需關心頁面的名字和參數便可(一般能夠是URL)

如何混合開發

1.新建flutterModule
2.pubspec.yaml添加插件
dependencies:
  flutter:
    sdk: flutter
  flutter_boost:
      git:
        url: 'https://github.com/alibaba/flutter_boost.git'
        ref: '1.17.1'
複製代碼
3.原生添加依賴

build.gradle

implementation project(':flutter')
implementation project(':flutter_boost')
複製代碼

settings.gradle

setBinding(new Binding([gradle: this]))
evaluate(new File(
        settingsDir,
        'flutter_module\\.android\\include_flutter.groovy'
))


include ':flutter_module'

複製代碼
4.application初始化
private fun initFlutter() {
        val router =
            INativeRouter { context, url, urlParams, requestCode, exts ->
                val assembleUrl =
                    Utils.assembleUrl(url, urlParams)
                PageRouter.openPageByUrl(context, assembleUrl, urlParams)
            }

        val boostLifecycleListener: BoostLifecycleListener = object : BoostLifecycleListener {
            override fun beforeCreateEngine() {}
            override fun onEngineCreated() {

                // 註冊MethodChannel,監聽flutter側的getPlatformVersion調用
                val methodChannel = MethodChannel(
                    FlutterBoost.instance().engineProvider().dartExecutor,
                    "flutter_native_channel"
                )
                methodChannel.setMethodCallHandler { call: MethodCall, result: MethodChannel.Result ->
                    when (call.method) {
                        "getPlatformVersion" -> {
                            result.success(Build.VERSION.RELEASE)
                        }
                        "getPlatformChannel" -> {
                            result.success(BuildConfig.FLAVOR)
                        }
                        "getToken" -> {
                            result.success(SPUtils.getInstance().getString(Constants.Access_Token))
                        }
                        else -> {
                            result.notImplemented()
                        }
                    }
                }

                // 註冊PlatformView viewTypeId要和flutter中的viewType對應
// FlutterBoost
// .instance()
// .engineProvider()
// .platformViewsController
// .registry
// .registerViewFactory(
// "plugins.test/view",
// TextPlatformViewFactory(StandardMessageCodec.INSTANCE)
// )
            }

            override fun onPluginsRegistered() {}
            override fun onEngineDestroy() {}
        }


        //
        // AndroidManifest.xml 中必需要添加 flutterEmbedding 版本設置
        //
        // <meta-data android:name="flutterEmbedding"
        // android:value="2">
        // </meta-data>
        // GeneratedPluginRegistrant 會自動生成 新的插件方式 
        //
        // 插件註冊方式請使用
        // FlutterBoost.instance().engineProvider().getPlugins().add(new FlutterPlugin());
        // GeneratedPluginRegistrant.registerWith(),是在engine 建立後立刻執行,放射形式調用
        //
        val platform = FlutterBoost.ConfigBuilder(this, router)
            .isDebug(true)
            .whenEngineStart(FlutterBoost.ConfigBuilder.ANY_ACTIVITY_CREATED)
            .renderMode(FlutterView.RenderMode.texture)
            .lifecycleListener(boostLifecycleListener)
            .build()
        FlutterBoost.instance().init(platform)
    }
複製代碼
<meta-data android:name="flutterEmbedding"
    android:value="2">
</meta-data>

<activity
	android:name="com.idlefish.flutterboost.containers.BoostFlutterActivity"
                			     android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
            android:hardwareAccelerated="true"
            android:theme="@style/Theme.AppCompat"
            android:windowSoftInputMode="adjustResize"/>
複製代碼
5.配置路由
class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();

    FlutterBoost.singleton.registerPageBuilders(<String, PageBuilder>{


      ///能夠在native層經過 getContainerParams 來傳遞參數
      'flutterPage': (String pageName, Map<String, dynamic> params, String _) {
        print('flutterPage params:$params');

        return FlutterRouteWidget(params: params);
      },
    });
    FlutterBoost.singleton.addBoostNavigatorObserver(TestBoostNavigatorObserver());
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Boost example',
        builder: FlutterBoost.init(postPush: _onRoutePushed),
        home: Container(color: Colors.white));
  }

  void _onRoutePushed(
    String pageName,
    String uniqueId,
    Map<String, dynamic> params,
    Route<dynamic> route,
    Future<dynamic> _,
  ) {}
}
複製代碼

native配置路由

public class PageRouter {

    public final static Map<String, String> pageName = new HashMap<String, String>() {{
        put("sample://flutterPage", "flutterPage");
    }};

    public static final String NATIVE_PAGE_URL = "sample://nativePage";
    public static final String FLUTTER_PAGE_URL = "sample://flutterPage";

    public static boolean openPageByUrl(Context context, String url, Map params) {
        return openPageByUrl(context, url, params, 0);
    }

    public static boolean openPageByUrl(Context context, String url, Map params, int requestCode) {

        String path = url.split("\\?")[0];

        Log.i("openPageByUrl",path);

        try {
            if (pageName.containsKey(path)) {
                Intent intent = BoostFlutterActivity.withNewEngine().url(pageName.get(path)).params(params)
                        .backgroundMode(BoostFlutterActivity.BackgroundMode.opaque).build(context);
                if(context instanceof Activity){
                    Activity activity=(Activity)context;
                    activity.startActivityForResult(intent,requestCode);
                }else{
                    context.startActivity(intent);
                }
                return true;
            }else if (url.startsWith(NATIVE_PAGE_URL)) {
                String aNative = (String) params.get("native");
                Timber.e("回傳:"+aNative);
                NavigationUtils.INSTANCE.goWorkStateActivity();
                return true;
            }
            return false;

        } catch (Throwable t) {
            return false;
        }
    }
}
複製代碼
6.路由跳轉
//原生
  val params= mutableMapOf<String,String>()
                params["test1"] = "v_test1"
                params["test2"] = "v_test2"
  //Add some params if needed.
  PageRouter.openPageByUrl(this, PageRouter.FLUTTER_PAGE_URL, params)
複製代碼
onTap: () => FlutterBoost.singleton.open(
                  'sample://nativePage',
// urlParams: <String, dynamic>{
// 'query': <String, dynamic>{'native': 'bbb'}
// },
                  urlParams: {"native": "我是參數乙"},
                ),
複製代碼

四.Web開發

1.flutter SDK配置

sdk文件夾中找到flutter_console.bat

flutter channel
flutter channel beta
flutter upgrade
flutter config --enable-web
flutter devices
複製代碼

2.安裝web編譯工具

flutter pub global activate webdev
複製代碼

配置環境變量:path中添加 D:\flutter\fluttersssssss.pub-cache\bin

3.發佈

若是你想查看release版本,能夠運行

flutter build web
複製代碼

會在項目的D:\flutter\flutter_web_app\build\web 生成打包文件

五.Windows開發

1.flutter SDK配置

sdk文件夾中找到flutter_console.bat

flutter channel
flutter channel master
flutter upgrade
flutter config --enable-windows-desktop
複製代碼

2.若是你的電腦沒有在開發者模式,使用插件會出錯。 你能夠在設置-->更新和安全-->開發者選項裏設置

Building with plugins requires symlink support. Please enable Developer Mode in your system settings
複製代碼

3.安裝VisualStudio

選擇c++開發版

Exception: Unable to find suitable Visual Studio toolchain. Please run flutter doctor for more details.

flutter doctor 查看錯誤

4.打包exe

flutter build windows
複製代碼

會在該目錄下生成exe D:\flutter\flutter_windows\build\windows\runner\Release

Advanced Installer 這個工具能夠構建windows安裝程序

桌面開發插件地址:github.com/google/flut…

個人demo地址:gitee.com/hhyq520/flu…

六.移動端mvvm+provider搭建環境

盡請期待。。。下期更精彩

七.總結

1.除了移動端,其餘平臺不成熟

2.依靠原生

3.潛力大

4.須要插件

5.一套代碼多個平臺

6.背靠谷歌爸爸

相關文章
相關標籤/搜索