因為筆者本身主要從事是Android開發(fā)咒林,所以很多角度都是作為一個Android開發(fā)者學習Flutter的角度出發(fā)徒仓,IOS或者H5的開發(fā)同學可以選擇性閱讀
目錄
前言
如果我們目前的項目是Android的悲伶,但是接下來我們希望部分頁面可以使用Flutter進行開發(fā),甚至我們希望在Native頁面中嵌入FlutterUI組件醉者,那么我們該如何實現(xiàn)呢啼器?
創(chuàng)建Flutter Module
假設你現(xiàn)在Android項目的目錄的結構是這樣的
xxx/flutter_hybrid/FlutterHybridAndroid
這時候如果你想創(chuàng)建一個Flutter模塊玛追,使得Android模塊和Flutter模塊之間可以進行交互舔痕,我們可以通過Android Studio新建一個Flutter Module,具體過程是:File —> New —> New Module 豹缀,之后選擇Flutter Module,指定Project Location的路徑為
xxx/flutter_hybrid
也就是說慨代,最終你的項目結構會是這樣的
- flutter_hybrid
- flutter_module
- FlutterHybridAndroid
接下來在Android Module的build.gradle
文件中添加flutter依賴
//FlutterHybridAndroid/app/build.gradle
...
dependencies {
implementation project(':flutter')
...
}
Android啟動Flutter頁面的兩種方式
先創(chuàng)建一個Flutter頁面
這里比較重要的是window.defaultRouteName
這個字段邢笙,這個字段可以接收從Native傳遞過來的參數(shù)(下文我們會介紹原生傳遞參數(shù)的方法),也就是說通過這個字段我們就可以進行Flutter頁面的路由的分發(fā)
import 'dart:ui';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'FlutterHybird',
theme: ThemeData(
primarySwatch: Colors.blue,
),
//window.defaultRouteName可以接收從Native傳過來的參數(shù)
home: _widgetForRoute(window.defaultRouteName),
);
}
}
Widget _widgetForRoute(String route) {
switch (route) {
case 'route1':
return Center(
child: Text("route1"),
);
case 'route2':
return Center(
child: Text("route2"),
);
default:
return Center(
child: Text('Unknown route: $route', textDirection: TextDirection.ltr),
);
}
}
- 直接啟動一個FlutterActivity
我們可以直接在Android的MainActivity
中啟動一個FlutterActivity
侍匙,這里的initialRoute
方法中傳遞的參數(shù)就對應Flutter層的window.defaultRouteName
findViewById(R.id.jump).setOnClickListener(v -> {
startActivity(FlutterActivity.withNewEngine()
.initialRoute("route2")
.build(MainActivity.this));
});
注意:需要在AndroidManifest.xml
注冊FlutterActivity
<activity
android:name="io.flutter.embedding.android.FlutterActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize" />
- 啟動復寫后的FlutterActivity(推薦)
自己創(chuàng)建一個FlutterAppActivity
繼承自FlutterActivity
public class FlutterAppActivity extends FlutterActivity {
public final static String INIT_PARAMS = "initParams";
private String initParams;
public static void start(Context context, String initParams) {
Intent intent = new Intent(context, FlutterAppActivity.class);
intent.putExtra(INIT_PARAMS, initParams);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initParams = getIntent().getStringExtra(INIT_PARAMS);
}
/**
* 重載該方法來傳遞初始化參數(shù)
*
* @return
*/
@NonNull
@Override
public String getInitialRoute() {
return initParams == null ? super.getInitialRoute() : initParams;
}
}
在MainActivity
中啟動FlutterAppActivity
(另外別忘了在AndroidManifest.xml
中注冊FlutterAppActivity
)
findViewById(R.id.jump).setOnClickListener(v -> {
FlutterAppActivity.start(MainActivity.this,"route2");
});
兩種啟動方式的區(qū)別
如果單純只是想打開一個Flutter頁面氮惯,兩種方式實際上基本沒有太大區(qū)別,第一種方式也許還會更簡單一點想暗。但是妇汗,在Flutter開發(fā)中,我們往往還需要開發(fā)一些Native插件供Flutter調用说莫,如果使用復寫FlutterActivity
的方式更有利于我們在FlutterActivity
中注冊我們的Native插件杨箭,所以實際開發(fā)中一般推薦使用第二種方式
擴展思考
initialRoute
從名稱上看起來是Flutter提供給我們進行Native與Flutter交互的路由跳轉的,但是實際上他就是一個字符串储狭,我們不僅僅可以傳遞一個路由名稱互婿,有時候我們也可以通過這個參數(shù)傳遞一串JSON數(shù)據(jù),然后在Flutter端進行解析辽狈,這樣我們就可以通過這個參數(shù)做更多的事情
在Android原生頁面中嵌入FlutterUI組件
activity_main.xml
FrameLayout
用于承載Flutter組件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/colorAccent"
android:gravity="center"
android:text="Hello World!" />
<FrameLayout
android:id="@+id/container"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1">
</FrameLayout>
</LinearLayout>
MainActivity.java
使用FragmentManager
將FlutterFragment
添加到FrameLayout
容器中
FlutterFragment fragment = FlutterFragment.withNewEngine().initialRoute("route1").build();
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.container, fragment)
.commit();
運行結果
上半部分是原生的TextView慈参,下半部分是Flutter的Text組件
總結
本節(jié)主要介紹了Native和Flutter之間的頁面跳轉,以及同一個頁面中Native與Flutter組件的組合刮萌。接下來會介紹如何編寫Android插件與Flutter進行數(shù)據(jù)交互