Flutter(Android 混合開發(fā))

前言


Flutter 支持作為 android Moudle 出現(xiàn)在項(xiàng)目中.這樣就可以在 已有的項(xiàng)目中 使用.
雖然現(xiàn)在Flutter 比較受關(guān)注,但是和weex 一樣 ,大部分都只是在觀望 不是真正的進(jìn)行使用.所以 如果用還是混合開發(fā) 原生+Flutter 方式比較合適(自我感覺(jué)).
寫一個(gè)demo 進(jìn)行Android及Flutter 交互.(IOS 方法基本一致).

Flutter 調(diào)用 android 硬件的插件還比較匱乏 比如 各種傳感器, 自定義相機(jī) 所以就會(huì)用到 Flutter 調(diào)用android 及android 原生調(diào)用 Flutter的方法.

本例子中會(huì)實(shí)現(xiàn).

(1) 原有的android 應(yīng)用程序嵌入 FlutterView
(2) Flutter 代碼調(diào)用Android 原生方法進(jìn)行頁(yè)面跳轉(zhuǎn)及傳值
(3) Android原生 調(diào)用 Flutter 方法 進(jìn)行傳值

步驟
新建一個(gè) android 項(xiàng)目

然后在 同級(jí)目錄創(chuàng)建一個(gè)Flutter Moudle

圖片.png

然后 導(dǎo)入 Flutter Moudle


Flutter Moudle

Moudle 導(dǎo)入成功后 項(xiàng)目結(jié)構(gòu)


項(xiàng)目結(jié)構(gòu)

app 目錄下的
build.gradle 中 新增了

    implementation project(':flutter')

項(xiàng)目目錄下的
settings.gradle 增加

setBinding(new Binding([gradle: this]))
evaluate(new File(
  settingsDir.parentFile,
  'flutter_test_module\\.android\\include_flutter.groovy'
))

基礎(chǔ)框架就搭建成功了

Demo 實(shí)現(xiàn)

實(shí)現(xiàn)效果

最上層放置了一個(gè) Android原生 TextView 下方使用的FlutterView

        flutterView = Flutter.createView(this, getLifecycle(), "route2");
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
        frameLayout.addView(flutterView, layoutParams);

其中 flutterView = Flutter.createView(this, getLifecycle(), "route2"); route2 與flutter_test_module lib 文件夾下 main.dart 中 所對(duì)應(yīng) 希望加載 哪個(gè)頁(yè)面 就填寫相應(yīng)的 route 名稱.

Widget _widgetForRoute(String route) {
  switch (route) {
    case 'route1':
      return  MyHomePage(title: 'Flutter Demo Home Page1');
    case 'route2':
      return  MyHomePage(title: 'Flutter Demo Home Page2');
    default:
        return  MyHomePage(title: 'Flutter Demo Home Page2');
  
  }
}

Flutter 調(diào)用Android

java

        new MethodChannel(flutterView, FlutterToAndroidCHANNEL).setMethodCallHandler(new MethodChannel.MethodCallHandler() {
            @Override
            public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {

                //接收來(lái)自flutter的指令withoutParams
                if (methodCall.method.equals("withoutParams")) {

                    //跳轉(zhuǎn)到指定Activity
                    Intent intent = new Intent(NativeActivity.this, NativeActivity.class);
                    startActivity(intent);

                    //返回給flutter的參數(shù)
                    result.success("success");
                }
                //接收來(lái)自flutter的指令withParams
                else if (methodCall.method.equals("withParams")) {

                    //解析參數(shù)
                    String text = methodCall.argument("flutter");

                    //帶參數(shù)跳轉(zhuǎn)到指定Activity
                    Intent intent = new Intent(NativeActivity.this, NativeActivity.class);
                    intent.putExtra("test", text);
                    startActivity(intent);

                    //返回給flutter的參數(shù)
                    result.success("success");
                } else {
                    result.notImplemented();
                }
            }
        });

dart


  Future<Null> _jumpToNative() async {
    String result = await toAndroidPlugin.invokeMethod('withoutParams');

    print(result);
  }


  Future<Null> _jumpToNativeWithParams() async {

    Map<String, String> map = { "flutter": "這是一條來(lái)自flutter的參數(shù)" };

    String result = await toAndroidPlugin.invokeMethod('withParams', map);

    print(result);
  }

Android 向 Flutter 傳參

java

  new EventChannel(flutterView, AndroidToFlutterCHANNEL)
                .setStreamHandler(new EventChannel.StreamHandler() {
                    @Override
                    public void onListen(Object o, EventChannel.EventSink eventSink) {
                        String androidParmas = "來(lái)自android原生的參數(shù)";
                        eventSink.success(androidParmas);
                    }

                    @Override
                    public void onCancel(Object o) {

                    }
                });

dart


  void _startfromAndroiPlugin(){
    if(_fromAndroiSub == null){
      _fromAndroiSub =  fromAndroiPlugin.receiveBroadcastStream()
      .listen(_onfromAndroiEvent,onError: _onfromAndroiError);
    }
  }


void _onfromAndroiEvent(Object event) {
    setState(() {
      _nativeParams = event;
    });
  }

  void _onfromAndroiError(Object error) {
    setState(() {
      _nativeParams = "error";
      print(error);
    });
  }

有幾處 要注意一一對(duì)應(yīng)
new EventChannel(flutterView, AndroidToFlutterCHANNEL)

        new MethodChannel(flutterView, FlutterToAndroidCHANNEL).setMethodCallHandler(new MethodChannel.MethodCallHandler() {
            @Override
            public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {

                //接收來(lái)自flutter的指令withoutParams
                if (methodCall.method.equals("withoutParams")) {

                    //跳轉(zhuǎn)到指定Activity
                    Intent intent = new Intent(NativeActivity.this, NativeActivity.class);
                    startActivity(intent);

                    //返回給flutter的參數(shù)
                    result.success("success");
                }
                //接收來(lái)自flutter的指令withParams
                else if (methodCall.method.equals("withParams")) {

                    //解析參數(shù)
                    String text = methodCall.argument("flutter");

                    //帶參數(shù)跳轉(zhuǎn)到指定Activity
                    Intent intent = new Intent(NativeActivity.this, NativeActivity.class);
                    intent.putExtra("test", text);
                    startActivity(intent);

                    //返回給flutter的參數(shù)
                    result.success("success");
                } else {
                    result.notImplemented();
                }
            }
        });

dart


  Future<Null> _jumpToNative() async {
    String result = await toAndroidPlugin.invokeMethod('withoutParams');

    print(result);
  }

  Future<Null> _jumpToNativeWithParams() async {

    Map<String, String> map = { "flutter": "這是一條來(lái)自flutter的參數(shù)" };

    String result = await toAndroidPlugin.invokeMethod('withParams', map);

    print(result);
  }

Android 向 Flutter 傳參

java

  new EventChannel(flutterView, AndroidToFlutterCHANNEL)
                .setStreamHandler(new EventChannel.StreamHandler() {
                    @Override
                    public void onListen(Object o, EventChannel.EventSink eventSink) {
                        String androidParmas = "來(lái)自android原生的參數(shù)";
                        eventSink.success(androidParmas);
                    }

                    @Override
                    public void onCancel(Object o) {

                    }
                });

dart


  void _startfromAndroiPlugin(){
    if(_fromAndroiSub == null){
      _fromAndroiSub =  fromAndroiPlugin.receiveBroadcastStream()
      .listen(_onfromAndroiEvent,onError: _onfromAndroiError);
    }
  }

void _onfromAndroiEvent(Object event) {
    setState(() {
      _nativeParams = event;
    });
  }

  void _onfromAndroiError(Object error) {
    setState(() {
      _nativeParams = "error";
      print(error);
    });
  }

有幾處 要注意一一對(duì)應(yīng)
public static final String FlutterToAndroidCHANNEL = "com.litngzhe.toandroid/plugin";
public static final String AndroidToFlutterCHANNEL= "com.litngzhe.toflutter/plugin";

new EventChannel(flutterView, AndroidToFlutterCHANNEL)
new MethodChannel(flutterView, FlutterToAndroidCHANNEL)

dart中
//獲取到插件與原生的交互通道
static const toAndroidPlugin = const MethodChannel('com.litngzhe.toandroid/plugin');

static const fromAndroiPlugin = const EventChannel('com.litngzhe.toflutter/plugin');
MethodChannel 中 涉及到的方法名要要統(tǒng)一

Flutter 布局及路由導(dǎo)航
可以看 胖哥視頻
http://jspang.com/post/flutter4.html

本文中 知識(shí)點(diǎn) 從下方文章學(xué)習(xí)
http://www.reibang.com/p/c5263a3d7aac

本文demo 傳至 Github
下載地址

github 上有反饋說(shuō) demo 無(wú)法運(yùn)行.兩個(gè)項(xiàng)目 要分開打開. 先把 moudle 打開,
解決 庫(kù)依賴問(wèn)題 運(yùn)行編譯.


圖片

flutter_test_module 先運(yùn)行


圖片

或者 在終端 輸入 flutter packages get

程序不報(bào)錯(cuò)后

圖片

目錄中出現(xiàn) android 及IOS環(huán)境
點(diǎn)擊運(yùn)行 .

打開 FlutterTest

點(diǎn)擊運(yùn)行.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末晚树,一起剝皮案震驚了整個(gè)濱河市送讲,隨后出現(xiàn)的幾起案子厦凤,更是在濱河造成了極大的恐慌胖缤,老刑警劉巖眷蚓,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件澳骤,死亡現(xiàn)場(chǎng)離奇詭異歧强,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)为肮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門摊册,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人颊艳,你說(shuō)我怎么就攤上這事茅特。” “怎么了棋枕?”我有些...
    開封第一講書人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵白修,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我重斑,道長(zhǎng)兵睛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任绸狐,我火速辦了婚禮卤恳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘寒矿。我一直安慰自己突琳,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開白布符相。 她就那樣靜靜地躺著拆融,像睡著了一般。 火紅的嫁衣襯著肌膚如雪啊终。 梳的紋絲不亂的頭發(fā)上镜豹,一...
    開封第一講書人閱讀 52,255評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音蓝牲,去河邊找鬼趟脂。 笑死,一個(gè)胖子當(dāng)著我的面吹牛例衍,可吹牛的內(nèi)容都是我干的昔期。 我是一名探鬼主播已卸,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼硼一!你這毒婦竟也來(lái)了累澡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤般贼,失蹤者是張志新(化名)和其女友劉穎愧哟,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哼蛆,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蕊梧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了人芽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片望几。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖萤厅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情靴迫,我是刑警寧澤惕味,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站玉锌,受9級(jí)特大地震影響名挥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜主守,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一禀倔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧参淫,春花似錦救湖、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至耍铜,卻和暖如春邑闺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背棕兼。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工陡舅, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人伴挚。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓靶衍,卻偏偏與公主長(zhǎng)得像臂寝,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子摊灭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • Flutter - Dart代碼調(diào)用Kotlin原生代碼 背景 開發(fā)中咆贬,我們常常需要調(diào)用原生Android的代碼,...
    Cosecant閱讀 23,756評(píng)論 21 28
  • 安裝教程https://www.cnblogs.com/wdh1995/p/7496688.html 激活可用ht...
    xinhua224閱讀 598評(píng)論 0 0
  • 時(shí)維九月帚呼,序?qū)偃锾投小G镪?yáng)行至中天,晴暖如往昔煤杀,熏醉了身心眷蜈。只愿暖陽(yáng)下長(zhǎng)坐,一任魂靈神游沈自,慵慵懶懶昏昏迷迷酌儒,神思行至...
    弱德之美閱讀 431評(píng)論 0 0
  • 時(shí)光讓我們漸漸老去酪夷, 塵世間的濁酒在歲月里過(guò)濾榴啸, 或許是我的思緒過(guò)于癡愚, 只在這一隅執(zhí)著里陋室而居晚岭。 生活如麻總...
    古城蒼狼閱讀 353評(píng)論 2 10