在Android中整合Flutter的學習筆記
Flutter可能是未來跨平臺開發的又一技術框架,那麼對於一個app,我們不可能完全用flutter來開發,那麼就意味著我們需要在已有的Android和iOS程式碼中去整合flutter。目前這一技術還處於預覽狀態,並且還要切換flutter的channel為mater分支。如下,官方原話:

那麼我們在整合之前需要檢視現在flutter處於什麼渠道:

我的是處於master分支,如果你以前沒改過的話,應該是beta分支,那麼可以執行:
flutter channel master
進行切換。
下面正式開始整合Android和iOS。
Android
首先用Android studio建立一個Android工程,步驟不做介紹了。然後在Android工程的根目錄執行一下命令:
flutter create -t module my_flutter
來建立一個flutter的module,成功之後,目錄結構如下:

接著我們來修改一下Android功能裡的gradle檔案:
首先是app的setting.gradle檔案,新增如下:
include ':app' setBinding(new Binding([gradle: this])) evaluate(new File( settingsDir.parentFile, 'my_flutter/.android/include_flutter.groovy' ))
目的就是去載入指定目錄的include_flutter.groovy檔案,那麼我們檢視一下這個檔案:
// Generated file. Do not edit. def scriptFile = getClass().protectionDomain.codeSource.location.path def flutterProjectRoot = new File(scriptFile).parentFile.parentFile gradle.include ':flutter' gradle.project(':flutter').projectDir = new File(flutterProjectRoot, '.android/Flutter') def plugins = new Properties() def pluginsFile = new File(flutterProjectRoot, '.flutter-plugins') if (pluginsFile.exists()) { pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } } plugins.each { name, path -> def pluginDirectory = flutterProjectRoot.toPath().resolve(path).resolve('android').toFile() gradle.include ":$name" gradle.project(":$name").projectDir = pluginDirectory } gradle.getGradle().projectsLoaded { g -> g.rootProject.afterEvaluate { p -> p.subprojects { sp -> if (sp.name != 'flutter') { sp.evaluationDependsOn(':flutter') } } } }
其中最重要的一段程式碼,就是include ':flutter',意思就是flutter這個module要參與編譯。
接著在app層級(不是project層)的build.gradle檔案中新增依賴:
dependencies { implementation project(':flutter') : }
OK配置階段結束,我們開始先寫Android程式碼,在activity中新增一個button,當我們點選它時,將載入flutter佈局,程式碼如下:
public class MainActivity extends AppCompatActivity { private TextView button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { FragmentTransaction tx = getSupportFragmentManager().beginTransaction(); tx.replace(R.id.container, Flutter.createFragment("route1")); tx.commit(); // View flutterView = Flutter.createView(MainActivity.this,getLifecycle(),"route1"); // FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(100,100); // params.leftMargin = 100; // params.topMargin = 200; // addContentView(flutterView,params); } }); } }
這裡有兩種實現方式,一種是使用fragment,一種是使用FlutterView。程式碼中的route1字串則是flutter程式碼中定義的,接下來就開始寫flutter程式碼:
import 'dart:ui'; import 'package:flutter/material.dart'; void main() => runApp(_widgetForRoute(window.defaultRouteName)); Widget _widgetForRoute(String route) { switch (route) { case 'route1': return SomeWidget(); case 'route2': return SomeWidget(); default: return Center( child: Text('Unknown route: $route', textDirection: TextDirection.ltr), ); } } class SomeWidget extends StatelessWidget{ @override Widget build(BuildContext context) { // TODO: implement build return Container( width: 100, height: 100, color: Color(0xFF00FF00), child: Center( child: Text("hello",textDirection: TextDirection.ltr,), ), ); } }
這裡可以看到對rout1的定義。
寫到這裡程式碼部分就完成了,然後執行android專案,就可以看到效果了。
【附】相關資料

有些大家需要的資料知識我都分享在群裡了,還有些錄製成視訊供大家免費下載,希望可以幫助在這個行業發展的朋友,在論壇部落格等地方少花些時間找資料,把有限的時間,真正花在學習上,所以我把這些資料,分享出來。相信對於已經工作和遇到技術瓶頸或者寫部落格碼友,在這份資料中一定都有你需要的內容。
進群【940780115】免費領取,歡迎各位一起來探討在Android開發上面所遇見的問題。