美文网首页FlutterAndroid拾萃Flutter学习
Android项目中集成Flutter,实现秒开Flutter模

Android项目中集成Flutter,实现秒开Flutter模

作者: 信仰年輕 | 来源:发表于2021-06-07 10:31 被阅读0次

    源代码
    Flutter版本2.0.3
    GitHub源代码

    本文目标

    成功在Android原生项目中集成Flutter

    Warning

    • 从Flutter v1.1.7版本开始,Flutter module仅支持AndroidX应用
    • 在release模式下Flutter仅支持以下架构:x86_64,armeabi-v7a,arm64-v8a,不支持mips和x86,所以引入Flutter前需要选取Flutter支持的架构
    android{
      //...
      defaultConfig {
            //配置支持的动态库类型
            ndk {
                abiFilters 'x86_64','armeabi-v7a', 'arm64-v8a'
            }
        }
    }
    
    

    混合开发的一些适用场景

    • 在原有项目中加入Flutter页面
    • 原生页面中嵌入Flutter模块
    • 在Flutter项目中嵌入原生模块

    主要步骤

    • 创建Flutter module
    • 为已存在的Android项目添加Flutter module依赖
    • 早Kotlin/Java中调用Flutter module
    • 编写Dart代码
    • 运行项目
    • 热重启/重新加载
    • 调试Dart代码
    • 发布应用

    请把所有的项目都放在同一个文件夹内

    - WorkProject
        -  AndroidProject
        -  iOSProject
        -  flutrter_module
    

    WorkProject下面分别是原生Android模块,原生iOS模块,flutter模块,并且这三个模块是并列结构

    创建Flutter module

    在做混合开发之前我们需要创建一个Flutter module
    这个时候需要

      cd xxx/WorkProject /
    

    创建flutter_module

    flutter create -t module flutter_module
    

    如果要指定包名

    flutter create -t module --org com.example flutter_module
    

    然后就会创建成功

    • .android - flutter_module的Android宿主工程
    • .ios - flutter_module的iOS宿主工程
    • lib - flutter_module的Dart部分代码
    • pubspec.yaml - flutter_module的项目依赖配置文件
      因为宿主工程的存在,我们这个flutter_module在布甲额外的配置的情况下是可以独立运行的,通过安装了Flutter和Dart插件的AndroidStudio打开这个flutter_module项目,通过运行按钮可以直接运行

    构建flutter aar(非必须)

    可以通过如下命令构建aar

    cd .android/
    ./gradlew flutter:assembleRelease
    

    这会在.android/Flutter/build/outputs/aar/中生成一个flutter-release.aar归档文件

    为已存在的Android用意添加Flutter module依赖

    打开我们的Android项目的 settings.gradle添加如下代码

    setBinding(new Binding([gradle: this]))                              
    evaluate(new File(                                                 
            settingsDir.parentFile,                                      
            'flutter_module/.android/include_flutter.groovy'                     
    ))
    
    //可选,主要作用是可以在当前AS的Project下显示flutter_module以方便查看和编写Dart代码
    include ':flutter_module'
    project(':flutter_module').projectDir = new File('../flutter_module')
    

    setBinding与evaluate允许Flutter模块包括它自己在内的任何Flutter插件,在setting.gradle中以类似:flutter package_info :video_player的方式存在

    添加:flutter依赖

    dependencies {
      implementation project(':flutter')
    }
    

    添加Java8编译选项

    因为Flutter的Android engine使用了Java8的特性,所有在引入Flutter时需要配置你的项目的Java8编译选项

    //在app的build.gradle文件的android{}节点下添加
    android {
        compileOptions {
            sourceCompatibility = 1.8
            targetCompatibility = 1.8
        }
    }
    

    在Kotlin中调用Flutter module

    支持,我们已经为我们的Android项目添加了Flutter所必须的依赖,接下来我们来看如何在项目中以Kotlin的方式在Fragment中调用Flutter模块,在这里我们能做到让Flutter优化提升加载速度,实现秒开Flutter模块

    原生Kotlin端代码

    /**
     * flutter抽象的基类fragment,具体的业务类fragment可以继承
     **/
    abstract class FlutterFragment(moduleName: String) : IBaseFragment() {
    
        private val flutterEngine: FlutterEngine?
        private lateinit var flutterView: FlutterView
    
        init {
            flutterEngine =FlutterCacheManager.instance!!.getCachedFlutterEngine(AppGlobals.get(), moduleName)
        }
    
        override fun getLayoutId(): Int {
            return R.layout.fragment_flutter
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            (mLayoutView as ViewGroup).addView(createFlutterView(activity!!))
        }
    
        private fun createFlutterView(context: Context): FlutterView {
            val flutterTextureView = FlutterTextureView(activity!!)
            flutterView = FlutterView(context, flutterTextureView)
            return flutterView
        }
    
        /**
         * 设置标题
         */
        fun setTitle(titleStr: String) {
            rl_title.visibility = View.VISIBLE
            title_line.visibility = View.VISIBLE
            title.text = titleStr
            title.setOnClickListener {
    
            }
        }
    
        /**
         * 生命周期告知flutter
         */
        override fun onStart() {
            flutterView.attachToFlutterEngine(flutterEngine!!)
            super.onStart()
        }
    
        override fun onResume() {
            super.onResume()
            //for flutter >= v1.17
            flutterEngine!!.lifecycleChannel.appIsResumed()
        }
    
        override fun onPause() {
            super.onPause()
            flutterEngine!!.lifecycleChannel.appIsInactive()
        }
    
        override fun onStop() {
            super.onStop()
            flutterEngine!!.lifecycleChannel.appIsPaused()
        }
    
        override fun onDetach() {
            super.onDetach()
            flutterEngine!!.lifecycleChannel.appIsDetached()
        }
    
        override fun onDestroy() {
            super.onDestroy()
            flutterView.detachFromFlutterEngine()
        }
    }
    

    R.layout.fragment_flutter的布局

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <RelativeLayout
            android:id="@+id/rl_title"
            android:visibility="gone"
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_45"
            android:background="@color/color_white"
            android:gravity="center_vertical"
            android:orientation="horizontal">
    
            <TextView
                android:id="@+id/title"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_centerInParent="true"
                android:layout_gravity="center"
                android:gravity="center"
                android:textColor="@color/color_000"
                android:textSize="16sp" />
        </RelativeLayout>
    
        <View
            android:id="@+id/title_line"
            android:visibility="gone"
            android:layout_width="match_parent"
            android:layout_height="2px"
            android:background="@color/color_eee" />
    </LinearLayout>
    
    
    /**
     * flutter缓存管理,主要是管理多个flutter引擎
     **/
    class FlutterCacheManager private constructor() {
    
        /**
         * 伴生对象,保持单例
         */
        companion object {
    
            //喜欢页面,默认是flutter启动的主入口
            const val MODULE_NAME_FAVORITE = "main"
            //推荐页面
            const val MODULE_NAME_RECOMMEND = "recommend"
    
            @JvmStatic
            @get:Synchronized
            var instance: FlutterCacheManager? = null
                get() {
                    if (field == null) {
                        field = FlutterCacheManager()
                    }
                    return field
                }
                private set
        }
    
        /**
         * 空闲时候预加载Flutter
         */
        fun preLoad(context: Context){
            //在线程空闲时执行预加载任务
            Looper.myQueue().addIdleHandler {
                initFlutterEngine(context, MODULE_NAME_FAVORITE)
                initFlutterEngine(context, MODULE_NAME_RECOMMEND)
                false
            }
        }
    
        /**
         * 初始化Flutter
         */
        private fun initFlutterEngine(context: Context, moduleName: String): FlutterEngine {
            //flutter 引擎
            val flutterLoader: FlutterLoader = FlutterInjector.instance().flutterLoader()
            val flutterEngine = FlutterEngine(context,flutterLoader, FlutterJNI())
            flutterEngine.dartExecutor.executeDartEntrypoint(
                DartExecutor.DartEntrypoint(
                    flutterLoader.findAppBundlePath(),
                    moduleName
                )
            )
            //存到引擎缓存中
            FlutterEngineCache.getInstance().put(moduleName,flutterEngine)
            return flutterEngine
        }
    
        /**
         * 获取缓存的flutterEngine
         */
        fun getCachedFlutterEngine(context: Context?, moduleName: String):FlutterEngine{
            var flutterEngine = FlutterEngineCache.getInstance()[moduleName]
            if(flutterEngine==null && context!=null){
                flutterEngine=initFlutterEngine(context,moduleName)
            }
            return flutterEngine!!
        }
    
    }
    

    具体业务类使用

    //在app初始化中初始一下
    public class MyApplication extends Application {
    
        @Override
        public void onCreate() {
            super.onCreate();
            FlutterCacheManager.getInstance().preLoad(this);
        }
    }
    

    收藏页面

    class FavoriteFragment : FlutterFragment(FlutterCacheManager.MODULE_NAME_FAVORITE) {
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            setTitle(getString(R.string.title_favorite))
        }
    }
    

    推荐页面

    class RecommendFragment : FlutterFragment(FlutterCacheManager.MODULE_NAME_RECOMMEND) {
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            setTitle(getString(R.string.title_recommend))
        }
    }
    

    Dart端代码

    import 'package:flutter/material.dart';
    import 'package:flutter_module/favorite_page.dart';
    import 'package:flutter_module/recommend_page.dart';
    
    
    //至少要有一个入口,而且这下面的man() 和 recommend()函数名字 要和FlutterCacheManager中定义的对应上
    void main() => runApp(MyApp(FavoritePage()));
    
    //必须加注解
    @pragma('vm:entry-point')
    void recommend() => runApp(MyApp(RecommendPage()));
    
    class MyApp extends StatelessWidget {
      final Widget page;
      const MyApp(this.page);
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: Scaffold(
            body: page,
          ),
        );
      }
    }
    

    Dart侧收藏页面

    import 'package:flutter/material.dart';
    
    class FavoritePage extends StatefulWidget {
      @override
      _FavoritePageState createState() => _FavoritePageState();
    }
    
    class _FavoritePageState extends State<FavoritePage> {
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Text("收藏"),
        );
      }
    }
    

    Dart侧推荐页面

    import 'package:flutter/material.dart';
    
    class RecommendPage extends StatefulWidget {
      @override
      _RecommendPageState createState() => _RecommendPageState();
    }
    
    class _RecommendPageState extends State<RecommendPage> {
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Text("推荐"),
        );
      }
    }
    
    

    最终效果

    相关文章

      网友评论

        本文标题:Android项目中集成Flutter,实现秒开Flutter模

        本文链接:https://www.haomeiwen.com/subject/vjvosltx.html