千家信息网

如何在Flutter中嵌套Android布局

发表于:2025-11-08 作者:千家信息网编辑
千家信息网最后更新 2025年11月08日,这篇文章主要介绍了如何在Flutter中嵌套Android布局的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇如何在Flutter中嵌套Android布局文章都会有所收获,
千家信息网最后更新 2025年11月08日如何在Flutter中嵌套Android布局

这篇文章主要介绍了如何在Flutter中嵌套Android布局的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇如何在Flutter中嵌套Android布局文章都会有所收获,下面我们一起来看看吧。

效果

本文具体demo效果如下

开发

1.首先创建flutter项目,在项目中定义好flutter需要展示布局:

  @override  Widget build(BuildContext context) {    return Scaffold(      body: Column(        crossAxisAlignment: CrossAxisAlignment.start,        children: [          Expanded(            child: Center(              child: Text(                'Android按钮点击了 $_counter 次',                style: const TextStyle(fontSize: 17.0)),            ),          ),          Container(            padding: const EdgeInsets.only(bottom: 15.0, left: 5.0),            child: Row(              children: [                Image.asset('assets/flutter-mark-square-64.png', scale: 1.5),                const Text('Flutter', style: TextStyle(fontSize: 30.0)),              ],            ),          ),        ],      ),      floatingActionButton: FloatingActionButton(        onPressed: _sendFlutterIncrement,        child: const Icon(Icons.add),      ),    );  }

上述代码所呈现的布局就是效果图中Flutter那一部分(上半部分),设置FloatingActionButton是为了呈现Flutter与Android的交互过程, "Android按钮点击了 $_counter 次"呈现的是交互结果,Image.asset()则显示的是Flutter的logo(标记这是flutter中的布局)。之所以这样做是因为Flutter与Android页面相互嵌套通产伴随着数据交互。

2.创建Android中的布局:

                              

io.flutter.embedding.android.FlutterView就是需要展示的flutter布局也就是第一步中编写的布局,剩下的部分和第一步的逻辑是一样的,有用来展示交互结果的TextView(@+id/button_tap),标记Android页面的TextView(@string/android),用来交互的按钮FloatingActionButton。

3.定义通信渠道

Flutter:

  static const String _channel = 'increment';  static const String _pong = 'pong';  static const String _emptyMessage = '';  static const BasicMessageChannel platform =      BasicMessageChannel(_channel, StringCodec());  int _counter = 0;    @override  void initState() {    super.initState();    platform.setMessageHandler(_handlePlatformIncrement);  }   Future _handlePlatformIncrement(String message) async {    setState(() {      _counter++;    });    return _emptyMessage;  }  void _sendFlutterIncrement() {    platform.send(_pong);  }

代码中通信渠道使用的是BasicMessageChannel,没有用MethodChannel和EventChannel是因为BasicMessageChannel可以随时随地进行任何通信,而另外两种则各自有各自的局限性,这里就不做解释了,稍后会有文章专门介绍这三种通信渠道。_channel 是通信渠道的名称,这个是唯一且固定的,一旦定义好,Android端也要使用相同的名称,否则两者无法对接,导致通信失败。_pong是Flutter向Android传递的消息内容,Android每次接收的内容为"pong",相应的Flutter按钮点击次数就+1,消息内容和类型用户都可以自定义,只要定义好BasicMessageChannel的泛型和消息编码机制(文中使用的是StringCodec)即可。如果消息的内容比较多,开发者可以使用Json进行消息传递。_counter是flutter接收Android按钮的点击次数,Android按钮每点击一次_counter就+1。相关变量或常量定义完后,开发者需要在initState()中进行消息接收处理,因为BasicMessageChannel是双向通信,platform.setMessageHandler(_handlePlatformIncrement)就是对接收到的消息进行处理,_handlePlatformIncrement方法说明了消息的类型是String,消息是异步,_counter+1后调用setState()刷新布局后相应展示的Android按钮点击次数就+1了。platform.send(_pong)就是Flutter按钮点击完后调用这个方法,然后BasicMessageChannel将消息发送到Android。

Android:

private static FlutterEngine flutterEngine;    private FlutterView flutterView;    private int counter;    private static final String CHANNEL = "increment";    private static final String EMPTY_MESSAGE = "";    private static final String PING = "ping";    private BasicMessageChannel messageChannel;    ...    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);            if (flutterEngine == null) {            flutterEngine = new FlutterEngine(this, args);            flutterEngine.getDartExecutor().executeDartEntrypoint(                DartEntrypoint.createDefault()            );        }        ...        flutterView = findViewById(R.id.flutter_view);        flutterView.attachToFlutterEngine(flutterEngine);        messageChannel = new BasicMessageChannel<>(flutterEngine.getDartExecutor(), CHANNEL, StringCodec.INSTANCE);        messageChannel.            setMessageHandler(new MessageHandler() {                @Override                public void onMessage(String s, Reply reply) {                    onFlutterIncrement();                    reply.reply(EMPTY_MESSAGE);                }            });        FloatingActionButton fab = findViewById(R.id.button);        fab.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                sendAndroidIncrement();            }        });        ...

CHANNEL 是通信渠道的名称也是渠道的标识符,一定要和flutter统一,否则无法通信。BasicMessageChannel是通信渠道,如果使用了和flutter端不一样的,也是无法通信的。EMPTY_MESSAGE是Android端收到Flutter消息后给Flutter的回复,表示让Flutter知道Android收到消息了。Android端收到消息后在setMessageHandler中进行消息处理:将flutter点击按钮次数+1( onFlutterIncrement()),同时回复确认收到的消息(reply.reply(EMPTY_MESSAGE))。FloatingActionButton发生点击事件后调用sendAndroidIncrement方法就会向Flutter发送消息说自己点击了一次按钮:

private void sendAndroidIncrement() {        messageChannel.send(PING);    }

PING就是Android向Flutter发送的消息内容,Flutter收到消息后就对Android点击按钮次数+1。如果传递的消息比较多,还需要对具体的消息进行判断来确认需要做哪些处理,本文中只传递一种内容的消息,所以对消息的参数和方法没有做判断。代码中flutterView即是需要展示的Flutter布局,flutterEngine则是flutter引擎(说法不统一), flutterView.attachToFlutterEngine(flutterEngine)则是为flutterView注入生命和能量,否则flutterView就是空空没有生命和内容的控件。flutterEngine和AppCompatActivity的生命周期是绑定在一起:

  @Override    protected void onResume() {        super.onResume();        flutterEngine.getLifecycleChannel().appIsResumed();    }    @Override    protected void onPause() {        super.onPause();        flutterEngine.getLifecycleChannel().appIsInactive();    }    @Override    protected void onStop() {        super.onStop();        flutterEngine.getLifecycleChannel().appIsPaused();    }    @Override    protected void onDestroy() {        flutterView.detachFromFlutterEngine();        super.onDestroy();    }

Android中一旦出现了对生命周期的绑定,就是说只要按要求来,就不会出现乱七八糟的问题,即使有问题也不是它的问题。

关于"如何在Flutter中嵌套Android布局"这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对"如何在Flutter中嵌套Android布局"知识都有一定的了解,大家如果还想学习更多知识,欢迎关注行业资讯频道。

0