Flutter混合開發(一):Android項目集成Flutter模塊詳細指南

本文首發於微信公衆號「Android開發之旅」,歡迎關注 ,獲取更多技術乾貨java

混合開發應用場景

目前在國內開發純Flutter的應用仍是比較少的,絕大部分使用Flutter來開發的公司也都是使用混合開發。那麼混合開發的主要使用場景有哪些呢?android

  • 做爲獨立的頁面進行加入,能夠從原生頁面跳轉到Flutter頁面,也能夠從Flutter頁面跳轉到原生頁面。

  • 做爲頁面的一部分嵌入。

建立Flutter module

既然是作混合開發,那麼咱們確定是由Android原生項目的。假如native項目的路徑是這樣的:flutter/flutter_hybrid/native,那麼咱們須要在native上一層目錄flutter_hybrid中建立Flutter module。git

cd flutter/flutter_hybrid/
//建立支持AndroidX的flutter_module
flutter create --androidx -t module flutter_module 
//建立不支持AndroidX的flutter_module
flutter create -t module flutter_module
複製代碼

因此咱們在建立模塊的時候首先要肯定native項目是否是已經支持AndroidX,若是支持就須要加上 --androidx 參數。json

輸入後控制檯打印以下:bash

$ flutter create -t module flutter_module
Creating project flutter_module...
  flutter_module/test/widget_test.dart (created)
  flutter_module/flutter_module.iml (created)
  flutter_module/.gitignore (created)
  flutter_module/.metadata (created)
  flutter_module/pubspec.yaml (created)
  flutter_module/README.md (created)
  flutter_module/lib/main.dart (created)
  flutter_module/flutter_module_android.iml (created)
  flutter_module/.idea/libraries/Flutter_for_Android.xml (created)
  flutter_module/.idea/libraries/Dart_SDK.xml (created)
  flutter_module/.idea/modules.xml (created)
  flutter_module/.idea/workspace.xml (created)
Running "flutter pub get" in flutter_module...                      1.2s
Wrote 12 files.

All done!
Your module code is in flutter_module/lib/main.dart.
複製代碼

看到All done就表示咱們項目建立好了。整個module目錄和原生Flutter基本同樣,主要就是Android、iOS的宿主工程和lib目錄以及pubspec.yaml文件。微信

添加Flutter module依賴

module項目建立好後就須要添加到Android項目中了。咱們打開Android項目的setting.gradle文件,添加以下代碼:app

setBinding(new Binding([gradle: this]))
evaluate(new File(
        settingsDir.parentFile,
        //flutter_module即爲建立的模塊名稱
        'flutter_module/.android/include_flutter.groovy'
))
複製代碼

setBinding與evaluate容許Flutter模塊包括它本身在內的任何Flutter插件,在settings.gradle中以相似 :flutter、package_info、:video_player的方式存在。less

而後打開app/build.gradle在dependencies標籤中添加依賴:ide

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

這樣兩步就完成了依賴的添加,這裏爲何添加的叫「flutter」 而不是 「flutter_module」呢?由於項目編譯完成後會在Android項目的目錄下生成叫Flutter的目錄,這就是須要咱們依賴的。還有個須要注意是gradle中的minSdkVersion必需要大於等於16,由於這個flutter支持的最低版本。同時添加使用java8來編譯。在app/build.gradle中的android標籤中添加:工具

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}
複製代碼

調用Flutter module

依賴完成後咱們就能夠調用flutter模塊來建立UI了。Flutter爲咱們提供了兩種方式調用,一種是createView,以view的形式加載。另外一種是createFragment,以Android中的fragment的形式加載。

createView方式:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_main);

        FlutterView flutterView = Flutter.createView(this, getLifecycle(), "initialRoute");
        setContentView(flutterView);

    }
}
複製代碼

createFragment方式:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        //container爲activity_main佈局中的佔位符FrameLayout
        transaction.replace(R.id.container, Flutter.createFragment("initialRoute"));
        transaction.commit();

    }
}
複製代碼

這樣就將Flutter默認的首頁加載到應用上了。

從上面兩部分代碼中咱們能夠看到都有一個 「initialRoute」 參數,這個參數是用來告訴Dart代碼在Flutter視圖中顯示哪一個小部件。下面咱們就來修改module中的main.dart代碼來加載咱們本身的頁面。

咱們設置兩個route,分別展現route1Widget,和route2Widget,當沒有匹配的時候展現提醒文字。

import 'package:flutter/material.dart';
import 'dart:ui';

void main() => runApp(MyApp(
      //經過window.defaultRouteName獲取從native傳遞過來的參數,須要導入dart:ui包
      initParams: window.defaultRouteName,
    ));

class MyApp extends StatelessWidget {
  final String initParams;

  MyApp({Key key, this.initParams}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter_Android混合開發',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(initParams: initParams),
    );
  }
}

class HomePage extends StatefulWidget {
  final String initParams;

  const HomePage({Key key, this.initParams}) : super(key: key);

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

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: _widgetRoute(widget.initParams),
      ),
    );
  }
}

///路由轉發
Widget _widgetRoute(String route) {
  switch (route) {
    case "route1":
      return route1Widget();
    case "route2":
      return route2Widget();
    default:
      return notFoundWidget();
  }
}

Widget route1Widget() {
  return Center(
    child: Text(
      "this is route1Widget",
      style: TextStyle(color: Colors.red, fontSize: 20),
    ),
  );
}

Widget route2Widget() {
  return Center(
    child: Text(
      "this is route2Widget",
      style: TextStyle(color: Colors.blue, fontSize: 20),
    ),
  );
}

Widget notFoundWidget() {
  return Center(
    child: Text(
      "未匹配到路由111",
      style: TextStyle(fontSize: 40),
    ),
  );
}

複製代碼

咱們如今將加載Flutter時的initialRoute參數替換爲 「route1」,那頁面將加載route1Widget,替換爲 「route2」,將加載route2Widget。不然將展現notFoundWidget。固然咱們能夠直接傳路由參數,可是由於這個參數自己是一個字符串,因此咱們能夠來搞事情。好比傳遞一個json串,那麼是否是能夠作不少事呢?這裏我就不貼demo了,由於和上面的邏輯基本同樣,你們能夠去試試看。

熱重啓/從新加載

你們在寫純Flutter應用的時候,知道是有熱重啓/從新加載功能的,可是在作混合開發的過程當中,你會發現熱重啓/從新加載功能失效了。那麼如何在混合開發中開啓熱重啓/從新加載功能呢?

  • 首先接入咱們的設備或者模擬器
  • 將咱們的App關閉,退出後臺,在terminal中運行 flutter attach命令
$ flutter attach
Waiting for a connection from Flutter on Android SDK built for x86...

複製代碼

此時就在等待設備的鏈接。這裏要注意的是,若是電腦鏈接了多臺設備須要使用 -d 命令來指定一臺設備,參數爲設備的id。

flutter attach -d '你的設備id'
複製代碼
  • 而後啓動咱們的應用會看到控制檯輸出:
Done.
Syncing files to device Android SDK built for x86...             1,393ms

🔥  To hot reload changes while running, press "r". To hot restart (and rebuild state), press "R".
An Observatory debugger and profiler on Android SDK built for x86 is available at: http://127.0.0.1:59354/zRsDBfpesrk=/
For a more detailed help message, press "h". To detach, press "d"; to quit, press "q".
複製代碼

這樣就表示咱們鏈接成功了。在輸出的日誌中也告訴了咱們如何使用熱重啓/從新加載功能。

在Terminal中輸入如下命令​:​

r : 熱加載;
R : 熱重啓;
h : 獲取幫助;
d : 斷開鏈接;
q : 退出;
複製代碼

這裏的的 d 和 q 的命令都有退出調試,區別在於 d 命令只是單純的斷開而 q 命令會將應用退到後臺。

調試Dart代碼

一樣在混合開發過程當中咱們如何調試dart代碼呢?

  • 關閉咱們的應用
  • 點擊Android Studio工具欄上的Flutter Attach按鈕(須要安裝Flutter與Dart插件)

  • 啓動咱們的應用

接下來就能夠像調試普通Flutter項目同樣來調試混合開發模式下的Dart代碼了。

總結

以上就是如何在Android原生項目中接入Flutter模塊的基礎講解,主要就是模塊的建立、依賴、調用以及調試等等。其它的像iOS接入Flutter模塊,Android項目和Flutter項目之間的通訊以及iOS項目和Flutter之間的通訊都將在以後的文章中進行講解。由於寫在一篇中篇幅太長,朋友們讀起來也累。因此後續還會有至少三篇相關的文章和你們見面。動動手關注公衆號,即時獲取相關文章的推送。

所有Demo源碼已經上傳到後臺,關注公衆號回覆「Android混合開發」便可得到下載連接。

若是你以爲文章還不錯,請你們點贊分享下,你的確定是對我最大的鼓勵和支持。

推薦閱讀

Flutter開發必備Dart基礎:Dart快速入門

掃描下方二維碼關注公衆號,獲取更多技術乾貨。

相關文章
相關標籤/搜索