Flutter混合項目搭建之Flutter_Boot的使用

 

一、概念

1、Flutterr_Boot

這是一個由鹹魚技術出品,幫助你在已有原生應用的情況下,搭建flutter混合開發環境的工具。 它提供了標準的混合工程結構,同時支持混合棧(一套原生和flutter之前頁面通信和過渡的方案)的快速接入。

https://github.com/alibaba-flutter/flutter-boot

2、Flutter_Boost

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

https://github.com/alibaba/flutter_boost

二、準備工作

  1. npm安裝以及環境配置
  2. flutter 的v1.9.1-hotfixes分支安裝以及環境配置,對應flutter_boost版本是0.1.60---0.1.64
  3. JDK,Android SDK 等環境配置正確

三、開始混合項目搭建

項目地址:https://github.com/jingzhanwu/FlutterHybrid-FlutterBoot

1、安裝flutter_boot,命令行執行:npm install flutter_boot

npm install flutter_boot

2、初始化flutter_boot項目,進入要存放工程的目錄執行:

flutter-boot init

接着會提示你輸入工程名稱

輸完工程名會一次提示你輸入flutter 倉庫地址、是否有android項目,是否有IOS項目、關聯本地項目等,根據自己項目需求選擇即可,如果你已經有了android原生項目,則最好在關聯android項目哪一步輸入本地native項目的路勁進行關聯,如果選擇不關聯也可以,後面後說道如果關聯,因爲我是第二次創建,所以就默認執行了之前選擇的。

上面都執行完畢後在本地就會生成一個項目,名稱就是剛輸入的flutter_lib

3、編譯flutter_lib項目,下載配置gradle,如果是android studio 直接打開項目也可以

依次執行下面命令,第一個命令是進入到項目根目錄

>>>cd flutter_lib

>>>flutter build apk

4、如果初始化的時候沒有關聯native項目,則在原生項目根目錄下運行下面命令進行關聯、如果初始化時已經關聯則跳過此步驟。
進入native項目根目錄執行:flutter-boot link "flutter項目的本地目錄",link後面爲flutter項目本地目錄

重新關聯:flutter-boot link -f "flutter項目的本地目錄"

這一步是將原生項目與flutter項目進行軟關聯,這一步執行完畢已經就可以進行正常的混合開發了

5、使用flutter_boost,添加混合棧

執行:flutter-boot use

flutter-boot use

這一步執行完畢,會在原生項目的app下build.gradle、settings.gradle和gradle.properties文件中生成一些配置信息,具體如下

gradle.properties文件

settings.gradle文件

 

app下build.gradle文件

除了以上增加的內容外,還會多出來兩個gradle文件,分別是flutter的build.gradle和flutter-boost的build.gradle文件;他們分別對應flutter_lib(flutter側)和flutter_boost庫的gradle配置,一般情況下不要去修改這兩個文件中的內容,否則會引起一些編譯錯誤。

6、初始化flutter-boost

執行完flutter-boot use 命令後分別會在native側和flutter側的項目根目錄下生成一些初始化使用的事例代碼,可以參考;native側的在 fb目錄下,flutter的在main.dart和my_flutter_boost_app.dart文件中。

Native側我把生成的事例代碼進行了整理,首先是Application中的初始化部分:FlutterInitializer.init(this);

public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        FlutterInitializer.init(this);
    }
}

FlutterInitializer.java的部分

public class FlutterInitializer {
    private final static String TAG = FlutterInitializer.class.getSimpleName();


    public static void init(Application app) {
        if (!(app instanceof FlutterApplication)) {
            FlutterMain.startInitialization(app);
        }

        //路由,Flutter 啓動Native頁面的時候回調這裏
        INativeRouter router = (context, url, urlParams, requestCode, exts) -> {
            String assembleUrl = Utils.assembleUrl(url, urlParams);
            PageRouter.openPageByUrl(context, assembleUrl, urlParams);
        };
        //插件註冊
        FlutterBoost.BoostPluginsRegister pluginsRegister = mRegistry -> {
            GeneratedPluginRegistrant.registerWith(mRegistry);
            //註冊native的TextView插件,插件名稱:TextPlatformViewPlugin
            TextPlatformViewPlugin.register(mRegistry.registrarFor("TextPlatformViewPlugin"));
        };
        //配置
        Platform platform = new FlutterBoost.ConfigBuilder(app, router)
                .isDebug(true)
                .whenEngineStart(FlutterBoost.ConfigBuilder.ANY_ACTIVITY_CREATED)
                .renderMode(FlutterView.RenderMode.texture)
                .pluginsRegister(pluginsRegister)
                .build();

        //初始化flutter_boost
        FlutterBoost.instance().init(platform);
    }
}

PageRouter.java:是一個自定義的路由控制輔助類,方便管理頁面跳轉

public class PageRouter {

    public final static Map<String, String> pageName = new HashMap<String, String>() {{

        put("first", "first");
        put("second", "second");
        put("tab", "tab");
        put("sample://flutterPage", "flutterPage");
        put("sample://demoFlutterPage", "flutterDemoPage");
    }};

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

    public static final String FLUTTER_DEMO_PAGE_URL = "sample://demoFlutterPage";
    public static final String FLUTTER_PAGE_URL = "sample://flutterPage";
    public static final String FLUTTER_FRAGMENT_PAGE_URL = "sample://flutterFragmentPage";

    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)) {
                //打開指定url的flutter頁面
                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(FLUTTER_FRAGMENT_PAGE_URL)) {
                //打開flutter創建的fragment
                context.startActivity(new Intent(context, FlutterFragmentPageActivity.class));
                return true;
            } else if (url.startsWith(NATIVE_PAGE_URL)) {
                //打開原生Activity
                context.startActivity(new Intent(context, NativePageActivity.class));
                return true;
            }
            return false;
        } catch (Throwable t) {
            return false;
        }
    }
}

 

flutter側的代碼我整理到lib下了,具體如下

main.dart文件,我自己在生成的事例代碼上添加了自己的一些邏輯

void main() => runApp(MyFlutterBoostApp({
      'embeded': (pageName, params, String id) => EmbededFirstRouteWidget(),
      'first': (pageName, params, String id) => FirstRouteWidget(),
      'second': (pageName, params, String id) => SecondRouteWidget(),
      'tab': (pageName, params, String id) => TabRouteWidget(),
      'platformView': (pageName, params, String id) => PlatformRouteWidget(),
      'flutterDemoPage': (String url, Map params, String id) =>
          MyHomePage(title: '$url $id'),
      'flutterPage': (String pageName, Map params, String id) =>
          FlutterRouteWidget(params: params),
      'flutterFragment': (String url, Map params, String id) =>
          FragmentRouteWidget(params),
    }));

my_flutter_boost_app.dart文件

class MyFlutterBoostApp extends StatefulWidget {
  final Map<String, PageBuilder> builders;

  MyFlutterBoostApp(this.builders);

  @override
  _MyFlutterBoostAppState createState() => _MyFlutterBoostAppState();
}

class _MyFlutterBoostAppState extends State<MyFlutterBoostApp> {
  @override
  void initState() {
    super.initState();
    FlutterBoost.singleton.registerPageBuilders(widget.builders);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      builder: FlutterBoost.init(postPush: _onRoutePushed),
      home: Container(),
    );
  }

  void _onRoutePushed(
    String pageName,
    String uniqueId,
    Map params,
    Route route,
    Future _,
  ) {
    print("flutter端路由:pageName:$pageName\n params:$params\n route:$route");
  }
}

核心代碼爲: FlutterBoost.singleton.registerPageBuilders(widget.builders)這句,flutter-boost註冊一個flutter 的widget供native側通過url來調用。

7、manifest文件的配置

必須註冊這個activity,否則無法打開flutter頁面

 <!--        這個必須註冊,不然無法打開flutter的頁面-->
        <activity
            android:name="com.idlefish.flutterboost.containers.BoostFlutterActivity"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
            android:hardwareAccelerated="true"
            android:screenOrientation="portrait"
            android:theme="@style/Theme.AppCompat"
            android:windowSoftInputMode="adjustResize">
            <meta-data
                android:name="io.flutter.embedding.android.SplashScreenDrawable"
                android:resource="@drawable/page_loading" />

        </activity>

在每個需要使用flutter頁面的activity中都要加入android:hardwareAccelerated="true"這個屬性的配置

8、如果native項目出現support庫重複的情況,可以在項目的build.gradle文件中加入以下代碼來排除重複包

def addRepos(RepositoryHandler handler) {
    handler.google()
    handler.jcenter()
    handler.maven { url "https://jitpack.io" }
}

allprojects {
    //循環所有依賴,指定support的版本爲28.0.0,解決重複包問題
    //此方法在編譯的時候會循環依賴,所以會增加編譯時間。建議在
    //依賴的時候使用exclude 方法排除可能重複的包
    addRepos(repositories)
    subprojects {
        project.configurations.all {
            resolutionStrategy.eachDependency { details ->
                if (details.requested.group == 'com.android.support'
                        && !details.requested.name.contains('multidex')) {
                    details.useVersion "28.0.0"
                }
            }
        }
    }
}

以上就是flutter-boot混合項目腳手架的使用以及flutter-boost的配置了,每一步都是本人自己通過動手實踐驗證過的,如過程中有錯誤,首頁確認以下flutter版本和使用的flutter-boost的版本,版本對應關係以flutter-boost官網介紹爲準https://github.com/alibaba/flutter_boost

簡易MVP,支持Jetpack:https://blog.csdn.net/qq_19979101/article/details/103691091

 

Flutter中Sqlite使用:https://blog.csdn.net/qq_19979101/article/details/93030803

Flutter的Stomp-websocket插件:https://blog.csdn.net/qq_19979101/article/details/93873731

 

發佈了15 篇原創文章 · 獲贊 21 · 訪問量 6078
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章