Android與Flutter數(shù)據(jù)交互

  • 先看一下效果圖吧(圖一):上面是android原生攒读,下面是flutter頁面

    圖一

  • 好 讓我們一步一步來

- 1.創(chuàng)建flutter module

在android項(xiàng)目同級的目錄里按住shift+右鍵遮斥,然后選擇在此處打開 Powershell窗口(s)怠噪。
//或者在dos里cd到指定目錄也行

然后輸入flutter create -t module my_flutter

創(chuàng)建好后目錄如下(圖二):

圖二

- 2.配置android工程(將Flutter模塊作為依賴添加到主項(xiàng)目)

settings.gradle文件里添加:

setBinding(new Binding([gradle: this]))
//我們的flutter目錄
evaluate(new File(
        settingsDir.parentFile,
        'my_flutter/.android/include_flutter.groovy'
))

app目錄的build.gradle下添加:

dependencies {
    ...
    implementation project(':flutter')
}

添加之后同步下代碼,然后我們就可以在android項(xiàng)目里調(diào)用flutter頁面了

- 3.android添加flutter布局

改一下android:MainActivity.java里代碼

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
//        setContentView(R.layout.activity_main)
        
        //獲取flutterView
        val flutterView = Flutter.createView(this, lifecycle, "route1")
        setContentView(flutterView)
    }
}

Flutter.createView方法里前兩個參數(shù)是不變的,后面的"route1"可以獲取指定的flutter頁面鞠绰,后面講
現(xiàn)在我們先運(yùn)行一下看一下效果厢洞。。西饵。

  • 運(yùn)行的時候報了個錯誤(圖三):


    圖三

需要在app目錄的build.gradle下指定下jdk版本:

android {
    ...
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

再同步下酝掩,就可以運(yùn)行了,運(yùn)行效果(圖四):


圖四

獲取flutterView還有一種方法:

//獲取flutterView 第二種方法
val tx = supportFragmentManager.beginTransaction()
//第一個參數(shù)填入flutterView要存放的布局id
tx.replace(R.id.---, Flutter.createFragment("route1"))
tx.commit()

這兩種方法都設(shè)置了"route1"這個參數(shù)眷柔,我們來看一下這個參數(shù)在flutter里怎么用吧:
修改flutter main.dart里代碼:

import 'dart:ui';

import 'package:flutter/material.dart';

void main() => runApp(_widgetForRoute(window.defaultRouteName));

Widget _widgetForRoute(String route) {
  switch (route) {
    case 'route1':
      return MyApp1();
      break;
    default:
      return MyApp();
      break;
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('MyApp'),
        ),
      ),
    );
  }
}

class MyApp1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('MyApp1'),
        ),
      ),
    );
  }
}

這里的window需要導(dǎo)包期虾,現(xiàn)在知道那個參數(shù)的作用了吧,我們可以根據(jù)那個參數(shù)跳轉(zhuǎn)不同的flutter頁面

  • 到這里android和flutter的基礎(chǔ)配置就結(jié)束了驯嘱,接下來我們進(jìn)行數(shù)據(jù)傳遞
- 4.數(shù)據(jù)傳遞

寫之前我們先修改下android activity_main.xml的布局(圖五):

圖五

MainActivity.java

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //獲取flutterView
        val flutterView = Flutter.createView(this, lifecycle, "route1")
        llMainBottom.addView(flutterView)
    }
}

flutter頁面的布局也修改下:

import 'dart:ui';

import 'package:flutter/material.dart';

void main() => runApp(_widgetForRoute(window.defaultRouteName));

Widget _widgetForRoute(String route) {
  switch (route) {
    case 'route1':
      return MyApp1();
      break;
    default:
      return MyApp();
      break;
  }
}

//App
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('MyApp'),
        ),
      ),
    );
  }
}

//App1
class MyApp1 extends StatefulWidget {
  @override
  _MyApp1State createState() => _MyApp1State();
}

class _MyApp1State extends State<MyApp1> {
  String _text = '你好 世界镶苞!';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Stack(
          alignment: FractionalOffset(0.5, 0.95),
          children: <Widget>[
            Center(
              child: Text(_text),
            ),
            RaisedButton(
              child: Text('修改android'),
              onPressed: () {
                
              },
            ),
          ],
        ),
      ),
    );
  }
}
  • 運(yùn)行效果就和我們最上面的一樣了,這里就不貼了鞠评,傳輸數(shù)據(jù)Flutter向我們提供了3個方法:
    -MethodChannel
    - EventChannel
    - BasicMessageChannel
    我這邊示例一下MethodChannel的使用茂蚓,其他兩種方法有點(diǎn)類似

  • 我們點(diǎn)擊android按鈕,然后傳輸數(shù)據(jù)到flutter那邊

android發(fā)送:

//發(fā)送msg給flutters
MethodChannel(flutterView, "com.yang.test001").invokeMethod("android","Hello World!")

  • "com.yang.test001"相當(dāng)于唯一標(biāo)識剃幌,flutter那邊接受用
  • invokeMethod方法里傳的是鍵值對聋涨,flutter接受時可根據(jù)key取值

flutter 接收:

  @override
  void initState() {
    super.initState();
    MethodChannel('com.yang.test001').setMethodCallHandler((handler) {
      //根據(jù)key判斷android傳過來的值
      switch (handler.method) {
        case 'android':
          setState(() {});
          var msg = handler.arguments;
          _text = msg.toString();
          break;
      }
    });
  }

initState方法里進(jìn)行監(jiān)聽,然后根據(jù)key進(jìn)行判斷负乡,再setState(() {});改變下值就ok了
android接受flutter的值同理...

  • 當(dāng)我們android項(xiàng)目混合了flutter后牍白,可以進(jìn)行熱重載(我這邊測試只能更改flutter代碼才有效果)
    :進(jìn)入我們創(chuàng)建的my_flutter目錄里,再shift+右鍵抖棘,然后選擇在此處打開 Powershell窗口(s)茂腥,然后輸入:
flutter attach

會看到如下界面(圖六):


圖六

然后在android工程里啟動我們的app(圖七):


圖七

啟動后在shell窗口會看到如下信息(圖八):


圖八

之后修改flutter代碼,在終端輸入r就可以熱重載了切省,R是熱重啟最岗。沒用的話先輸入一遍R,再輸入r朝捆,應(yīng)該就可以看到效果了仑性,再沒用就反復(fù)多試試,感覺有點(diǎn)延遲,還有只能重載flutter代碼诊杆,所以用處嘛,就一丟丟而已了歼捐。。

  • 所有的代碼也貼一下吧:

android

class MainActivity : AppCompatActivity() {
    private lateinit var mMethodChannel: MethodChannel   //flutter連接
    private val METHOD_CHANNER = "com.yang.test001"      //與flutter連接的標(biāo)識
    private var mIsSendFlutter = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initView()
        initListener()
    }

    private fun initView() {
        //綁定flutterView 第一種方法
        val flutterView = Flutter.createView(this, lifecycle, "route1")
        llMainBottom.addView(flutterView)

//        //第二種方法
//        val tx = supportFragmentManager.beginTransaction()
//        tx.replace(R.id.llMainBottom, Flutter.createFragment("route1"))
//        tx.commit()

        //初始化MethodChannel
        mMethodChannel = MethodChannel(flutterView, METHOD_CHANNER)
    }

    private fun initListener() {
        //接受flutter消息監(jiān)聽
        mMethodChannel.setMethodCallHandler(object : MethodChannel.MethodCallHandler {
            override fun onMethodCall(p0: MethodCall, p1: MethodChannel.Result) {
                //根據(jù)收到的消息key進(jìn)行接收
                when (p0.method) {
                    "flutter" -> {
                        val msg = p0.arguments
                        tvMain.text = msg.toString()
                    }
                    else -> {

                    }
                }
            }
        })

        btnMain.setOnClickListener {
            //發(fā)送msg給flutter
            mMethodChannel.invokeMethod("android", if (mIsSendFlutter) {
                "你好 世界晨汹!"
            } else {
                "Hello World!"
            })
            mIsSendFlutter = !mIsSendFlutter
        }
    }
}

flutter

import 'dart:ui';

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

void main() => runApp(_widgetForRoute(window.defaultRouteName));

Widget _widgetForRoute(String route) {
  switch (route) {
    case 'route1':
      return MyApp1();
      break;
    default:
      return MyApp();
      break;
  }
}

//App1
class MyApp1 extends StatefulWidget {
  @override
  _MyApp1State createState() => _MyApp1State();
}

class _MyApp1State extends State<MyApp1> {
  MethodChannel _methodChannel = MethodChannel('com.yang.test001'); //與android連接
  String _text = '你好 世界豹储!';
  bool _isSendAndroid = false;

  @override
  void initState() {
    super.initState();
    _methodChannel.setMethodCallHandler(_handler);
  }

  //接收android監(jiān)聽
  Future<dynamic> _handler(MethodCall call) {
    switch (call.method) {
      case 'android':
        setState(() {});
        var msg = call.arguments;
        _text = msg.toString();
        break;
    }
  }

  //發(fā)送消息給android
  void _sendMessage() {
    //flutter 相當(dāng)于key 后面是內(nèi)容
    _methodChannel.invokeListMethod(
        'flutter', _isSendAndroid ? 'Hello World!' : '你好 世界!');
    _isSendAndroid = !_isSendAndroid;
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Stack(
          alignment: FractionalOffset(0.5, 0.95),
          children: <Widget>[
            Center(
              child: Text(_text),
            ),
            RaisedButton(
              child: Text('修改android'),
              onPressed: () {
                _sendMessage();
              },
            ),
          ],
        ),
      ),
    );
  }
}

//默認(rèn)App
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Text('myApp'),
        ),
      ),
    );
  }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末淘这,一起剝皮案震驚了整個濱河市剥扣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌铝穷,老刑警劉巖钠怯,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異曙聂,居然都是意外死亡晦炊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門宁脊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來断国,“玉大人,你說我怎么就攤上這事榆苞∥瘸模” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵坐漏,是天一觀的道長薄疚。 經(jīng)常有香客問我,道長赊琳,這世上最難降的妖魔是什么街夭? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮慨畸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘衣式。我一直安慰自己寸士,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布碴卧。 她就那樣靜靜地躺著弱卡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪住册。 梳的紋絲不亂的頭發(fā)上婶博,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機(jī)與錄音荧飞,去河邊找鬼凡人。 笑死名党,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的挠轴。 我是一名探鬼主播传睹,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼岸晦!你這毒婦竟也來了欧啤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤启上,失蹤者是張志新(化名)和其女友劉穎邢隧,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體冈在,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡倒慧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了讥邻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片迫靖。...
    茶點(diǎn)故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖兴使,靈堂內(nèi)的尸體忽然破棺而出系宜,到底是詐尸還是另有隱情,我是刑警寧澤发魄,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布盹牧,位于F島的核電站,受9級特大地震影響励幼,放射性物質(zhì)發(fā)生泄漏汰寓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一苹粟、第九天 我趴在偏房一處隱蔽的房頂上張望有滑。 院中可真熱鬧,春花似錦嵌削、人聲如沸毛好。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽肌访。三九已至,卻和暖如春艇劫,著一層夾襖步出監(jiān)牢的瞬間吼驶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蟹演,地道東北人风钻。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像轨帜,于是被迫代替她去往敵國和親魄咕。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評論 2 355