• 【Flutter 混合开发】添加 Flutter 到 Android Activity


    Flutter 混合开发系列 包含如下:

    • 嵌入原生View-Android
    • 嵌入原生View-iOS
    • 与原生通信-MethodChannel
    • 与原生通信-BasicMessageChannel
    • 与原生通信-EventChannel
    • 添加 Flutter 到 Android Activity
    • 添加 Flutter 到 Android Fragment
    • 添加 Flutter 到 iOS

    每个工作日分享一篇,欢迎关注、点赞及转发。

    创建 Flutter Module

    Flutter可以以源代码或AAR的方法嵌入到Android原生项目,集成流程可以使用 Android Studio 完成,也可以手动完成。强烈建议使用 Android Studio。

    首先创建一个 Android 项目,创建一个空的 Activity:

    Android 项目创建成功后,使用Android Studio 添加Flutter模块,在Android原生项目中点击“File > New > New Module...”,创建 Flutter Module

    注意:Android Studio 的版本3.5及以上,Flutter IntelliJ plugin版本42及以上。

    在弹出的选择Module类型的对话框中选中Flutter Module,然后点击Next,

    设置Flutter module的Project name、Flutter SDK等,点击Next:

    设置Flutter module的包名,点击Finish:

    编译完成后将在当前App目录下生成Flutter模块的代码,目录结构如下:

    启动页加载 Flutter

    将 Flutter 页面加载到 MainActivity(默认启动页) 中,修改 MainActivity :

    package com.flutter.androidflutter
    
    import io.flutter.embedding.android.FlutterActivity
    
    class MainActivity : FlutterActivity()
    

    你没有看错,只需让 MainActivity 继承 FlutterActivity 即可。

    注意:FlutterActivity的包名是io.flutter.embedding.android.FlutterActivity

    跳转到 Flutter 页面

    MainActivity(默认启动页)添加一个按钮,点击后跳转到新的页面,此页面加载 Flutter ,MainActivity代码如下:

    package com.flutter.androidflutter
    
    import android.content.Intent
    import androidx.appcompat.app.AppCompatActivity
    import android.os.Bundle
    import io.flutter.embedding.android.FlutterActivity
    import kotlinx.android.synthetic.main.activity_main.*
    
    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            button.setOnClickListener {
                startActivity(Intent(this,SecondFlutterActivity::class.java))
            }
        }
    }
    

    SecondFlutterActivity 代码如下:

    package com.flutter.androidflutter
    
    import io.flutter.embedding.android.FlutterActivity
    
    class SecondFlutterActivity:FlutterActivity() 
    

    AndroidManifest.xml 中注册此 Activity:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.flutter.androidflutter">
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            ...
            <activity android:name=".SecondFlutterActivity"/>
        </application>
    
    </manifest>
    

    flutter_android_1

    SecondFlutterActivity 只是继承了 FlutterActivity,这种情况下,也可以直接使用 FlutterActivity

    startActivity(Intent(this, FlutterActivity::class.java))
    

    或者:

    startActivity(FlutterActivity.createDefaultIntent(this))
    

    AndroidManifest.xml 中注册 FlutterActivity:

    <activity android:name="io.flutter.embedding.android.FlutterActivity"/>
    

    效果与上面是一样的。

    FlutterActivity 会加载 Flutter Module 中 lib/main.dart 中 main 方法,如果有多个Flutter页面,如何指定跳转,比如现在有 OnePage Flutter 页面,OnePage 代码如下:

    class OnePage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(),
          body: Center(
            child: Text('这是 One 页面'),
          ),
        );
      }
    }
    

    FlutterActivity 指定加载页面需要使用命名路由,MyApp 修改如下:

    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
    
            primarySwatch: Colors.blue,
          ),
          routes: {
            'one_page':(context){
              return OnePage();
            },
            'two_page':(context){
              return TwoPage();
            }
          },
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    

    MainActivity 页面点击到 Flutter 页面,加载 OnePage 页面:

    class MainActivity : AppCompatActivity() {
    
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            button.setOnClickListener {
                startActivity(
                    FlutterActivity
                        .withNewEngine()
                        .initialRoute("one_page")
                        .build(this)
                )
            }
        }
    }
    

    引擎缓存

    加载 FlutterActivity 页面时明显看到一段时间的黑屏,这段时间主要是启动 Flutter 引擎(FlutterEngine),Flutter 引擎启动的时间在不同手机上不同,性能越好的手机越短。同时每一个 FlutterActivity 页面都会启动一个引擎,所以强烈建议不要在一个项目中创建多个 FlutterActivity(或者启动多个 FlutterActivity 实例),否则内存会越来越大,下面是每隔3秒创建一个 FlutterActivity 实例内存变化图:

    为了减少 FlutterActivity 页面的延迟时间和多个 FlutterActivity 实例内存一直增长问题,我们可以使用 Flutter 引擎(FlutterEngine)缓存,在启动 FlutterActivity 前先启动 Flutter 引擎,然后使用缓存的引擎加载页面,通常将其放在 Application 中:

    class MyApplication : Application() {
        lateinit var flutterEngine: FlutterEngine
    
        override fun onCreate() {
            super.onCreate()
            flutterEngine = FlutterEngine(this)
            flutterEngine.dartExecutor.executeDartEntrypoint(
                DartExecutor.DartEntrypoint.createDefault()
            )
            FlutterEngineCache
                .getInstance()
                .put("engine_id", flutterEngine)
        }
    
    }
    

    使用缓存的引擎:

    startActivity(
        FlutterActivity
            .withCachedEngine("engine_id")
            .build(this)
    )
    

    在同一台手机上效果非常明显,黑屏时间大大减少,不过还是有一个短暂的黑屏。

    这里要注意,使用缓存引擎时,其生命周期不在是 FlutterActivity(或者 FlutterFragment)的生命周期,而是整个 App 的生命周期(在Application 中的创建和销毁)。当然也可以提前销毁:

    flutterEngine.destroy()
    

    另外项目的 debug 和 release 版本对性能的影响非常大,如果要测试其性能一定在要 release 下测试

    上面使用新的引擎可以指定 FlutterActivity(或者 FlutterFragment)配置初始路由,但使用缓存引擎时无法在 FlutterActivity(或者 FlutterFragment)配置初始路由,因为缓存引擎已经启动并运行,不过可以在启动缓存引擎时指定其初始路由:

    flutterEngine = FlutterEngine(this)
    
    flutterEngine.navigationChannel.setInitialRoute("one_page")
    
    flutterEngine.dartExecutor.executeDartEntrypoint(
        DartExecutor.DartEntrypoint.createDefault()
    )
    FlutterEngineCache
        .getInstance()
        .put("engine_id", flutterEngine)
    

    如果使用缓存引擎在FlutterActivity(或 FlutterFragment)指定不同路由,如何处理?这时需要创建一个 method channel,flutter 接收具体消息从而切换不同的路由。

    交流

    老孟Flutter博客(330个控件用法+实战入门系列文章):http://laomengit.com

    欢迎加入Flutter交流群(微信:laomengit)、关注公众号【老孟Flutter】:

  • 相关阅读:
    python学习笔记(29)-操作excel
    python学习笔记(28)-unittest单元测试-执行用例
    python学习笔记(27)-unittest单元测试-测试用例
    python学习笔记(26)-request模块
    python学习笔记(25)-继承
    c++ 流基本概念
    友元函数、类和运算符重载
    c++中的引用
    c++重点知识点
    指针和结构体
  • 原文地址:https://www.cnblogs.com/mengqd/p/13887892.html
Copyright © 2020-2023  润新知