版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/qq_26936889/article/details/90768742
一.Android已有項目接入Flutter module(官方提供的module方式)
官方文檔:https://github.com/flutter/flutter/wiki/Add-Flutter-to-existing-apps
1.創建Flutter module
(1)在已有的flutter項目中 輸入命令:flutter create -t module moduleName,將生成的module復制到原生項目中
(2)或者在已有Android項目中輸入上面命令,同樣會生成一個module
2.在Android項目工程的settings.gradle增加以下配置
setBinding(new Binding([gradle: this]))
evaluate(new File(
? ? ? ? settingsDir.parentFile,
? ? ? ? 'AndroidFlutterProject/flutter_module/.android/include_flutter.groovy'
))
1
2
3
4
5
flutter_module和app是同一級
AndroidFlutterProject:是Android項目的工程名
flutter_module:是剛才通過命令生成的module
3.在app的build.gradle增加以下依賴
implementation project(':flutter')
1
注意:原生項目中minSdkVersion 至少為16,否則編譯不過
通過以上三步就將Flutter集成到原生項目中了。
二:Android原生調Flutter代碼
Flutter提供兩種引入方法:一個是View,會默認生成一個View,一個是FlutterFragment方式。
View方式:可以自己設置新View的大小,位置
FlutterView flutterView = Flutter.createView(this, getLifecycle(), "路由信息,自己自定義");
FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(100, 100);
layout.leftMargin = 0;
layout.topMargin = 0;
addContentView(flutterView, layout);
1
2
3
4
5
FlutterFragment方式:
setContentView(R.layout.activity_main);
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fl_flutter_view, Flutter.createFragment("路由信息,自己自定義"));
fragmentTransaction.commit();
1
2
3
4
通過以上任意一種方式,都會調用fluttermodule中lib包下main.dart這個文件,我們可以在這個文件下面配置路由信息,控制頁面跳轉展示。
void main() => runApp(widgetForRoute(window.defaultRouteName));
Widget widgetForRoute(String route) {
? switch (route) {
? ? case '路由信息,自己自定義':
? ? ? return Center(
? ? ? ? child: Text('route: $route', textDirection: TextDirection.ltr),
? ? ? );
? ? ? return Center(
? ? ? ? child: Text('Unknown route: $route', textDirection: TextDirection.ltr),
? ? ? );
? }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
三:Flutter調用Android原生代碼
Flutter調用原生主要使用插件方式,通過MethodChannel的方式。
1.在Application onCreate方法中進行初始化,關鍵
FlutterMain.startInitialization(this);
1
2.實現插件,創建一個類實現MethodChannel.MethodCallHandler,在onMethodCall回調方法中對Flutter指令分發處理。
public class FlutterPluginJumpToAct implements MethodChannel.MethodCallHandler {
? ? //channel信息,可以自己隨便定義
? ? public static String CHANNEL = "com.qyh.jump/plugin";
? ? static MethodChannel channel;
? ? private Activity activity;
? ? private FlutterPluginJumpToAct(Activity activity) {
? ? ? ? this.activity = activity;
? ? }
? ? // 此方法需要外界進行調用注冊
? ? public static void registerWith(PluginRegistry.Registrar registrar) {
? ? ? ? channel = new MethodChannel(registrar.messenger(), CHANNEL);
? ? ? ? FlutterPluginJumpToAct instance = new FlutterPluginJumpToAct(registrar.activity());
? ? ? ? //setMethodCallHandler在此通道上接收方法調用的回調
? ? ? ? channel.setMethodCallHandler(instance);
? ? }
? ? @Override
? ? public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
? ? ? ? //通過methodCall可以獲得參數和方法名,原生這面做對應業務
? ? ? ? //result可以給Flutter設置回調
? ? ? ? // "test1":是Flutter代碼設置的調用指令
? ? ? ? if (methodCall.method.equals("test1")) {
? ? ? ? ? ? // do something
? ? ? ? ? ? result.success("suc");
? ? ? ? }
? ? }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
3.在Activity中注冊,此Activity需要繼承FlutterActivity
public class MainActivity extends FlutterActivity? {
? ? @Override
? ? protected void onCreate(Bundle savedInstanceState) {
? ? ? ? super.onCreate(savedInstanceState);
? ? ? ? GeneratedPluginRegistrant.registerWith(this);
? ? ? ? registerCustomPlugin(this);
? ? }
? ? private static void registerCustomPlugin(PluginRegistry registrar) {
? ? ? ? FlutterPluginJumpToAct.registerWith(registrar.registrarFor(FlutterPluginJumpToAct.CHANNEL));
? ? }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
FlutterActivity繼承的是Activity,如果想用其他Activity,比如AppCompatActivity,我們可以創建抽象Base類,繼承AppCompatActivity實現FlutterView.Provider, PluginRegistry, FlutterActivityDelegate.ViewFactory一系列方法。然后讓我們的Activity直接繼承這個基類就可以了。
4.在Flutter代碼中實現跳轉邏輯編寫
void main() => runApp(widgetForRoute(window.defaultRouteName));
Widget widgetForRoute(String route) {
? ? // com.qyh.jump/plugin是原生代碼中定義好的,要對應起來
? const jumpPlugin = const MethodChannel('com.qyh.jump/plugin');
? //test1 就是我們Flutter代碼回調原生的指令名字
? jumpPlugin.invokeMethod('test1');
}
1
2
3
4
5
6
7
8
當Flutter代碼執行到widgetForRoute(),會回調到插件FlutterPluginJumpToAct類的onMethodCall回調方法中,我們就可以通過methodCall.method獲取到指令(test1)名,進行原生邏輯編寫了,以上步驟就是Flutter調用原生代碼的方法。
4.1.在Flutter代碼中給原生傳遞參數
Flutter代碼中通過Map的方式對數據進行拼接,然后回傳給原生
void main() => runApp(widgetForRoute(window.defaultRouteName));
Widget widgetForRoute(String route) {
? // com.qyh.jump/plugin是原生代碼中定義好的,要對應起來
? const jumpPlugin = const MethodChannel('com.qyh.jump/plugin');
? Map<String, String> mapData = {"flutterKey1": "flutterValue1","flutterKey2": "flutterValue2"};
? jumpPlugin.invokeMethod('test1',mapData);
}
1
2
3
4
5
6
7
8
原生代碼中通過methodCall.arguments獲取,解析
@Override
public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
? ? //通過methodCall可以獲得參數和方法名,原生這面做對應業務
? ? if (methodCall.method.equals("test1")) {
? ? ? ? if (methodCall.arguments != null) {
? ? ? ? ? ? Map<String, String> arguments = (Map<String, String>) methodCall.arguments;
? ? ? ? }
? ? }
}
1
2
3
4
5
6
7
8
9
以上就是Android原生跟Flutter交互方式,在實際項目中我遇到一個實際問題,原生、Flutter混合開發會遇到棧混亂的情況,之后引入阿里的[flutter_boost] (https://github.com/alibaba/flutter_boost),詳細接入可以參考開源庫,下面總結一下我接入這個庫遇到一些問題:
1.Android appcation中不能引用FlutterBoostPlugin
在原生項目 app下面gradle引入flutter_boost
implementation project(':flutter_boost')
1
2.v4 v7庫版本沖突
將xservice_kit 、flutter_boost、 flutter_module、 app下gradle里版本統一。
3.Android接收Flutter中傳參中文字符串亂碼
String decodeValue = URLDecoder.decode(value, "UTF-8");
1
四、接入Flutter后調試問題
1.Android原生代碼不能快速debug
解決方法:將Android Studio升級到最新版本,目前最新版本3.4.1
2.Flutter熱加載
在flutter_module目錄下 輸入命令 flutter attach,這個時候會提示等待連接設備,然后 Run一次項目,當項目重新運行起來后,就可以在Terminal 中輸入r(熱加載)、R(熱重啟)命令進行愉快的開發了。
————————————————
版權聲明:本文為CSDN博主「Android小工」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_26936889/article/details/90768742