美文网首页
Flutter混合开发实战

Flutter混合开发实战

作者: 刘景昌 | 来源:发表于2020-09-21 14:47 被阅读0次

之前开发了一个纯Flutter的项目,结果接到个新的需求需要使用Flutter单独开一个模块集成到原有的android项目中
下面分享一下如何集成现有的项目和如何继承以及碰到的问题
1.首先第一步 修改gradle
因为 Flutter 当前仅支持为 x86_64,armeabi-v7a 和 arm64-v8a 构建预编(AOT)的库 所以我们需要修改gradle的文件限制 APK 中支持的架构,从而避免 libflutter.so找不到引起的崩溃

android {
  //...
  defaultConfig {
    ndk {
      // Filter for architectures supported by Flutter.
      abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64'
    }
  }
}

2.新建一个FlutterModel的工程

image.png
3.在android中添加Flutter的依赖
在添加Flutter依赖的时候一共有两种方式
1.使用本地文件(建议自己本地调试的时候使用) 因为方便修改和调试
(1)修改 settings.gradle
image.png
(2)修改gradle引入Flutter
dependencies {
  implementation project(':flutter')
}

2.使用aar文件 因为所有工程统一使用jenkins打包所以我们放在本地肯定是不合适的
说以我们需要 打包aar并上传服务器

@echo off   
::start cmd /C

flutter clean
flutter build aar --build-number version

# 定义用于aar、pom文件目录存放的数组
aars=()
poms=()
# 指定打包后本地仓库的目录,由于这里将此脚本放在flutter module根目录,因此直接配置了flutter module根目录下相对目录
targetPath="build/host/outputs/repo"

# 定义遍历找到所有pom文件和aar文件的函数
# 参数$1:当前查找的目录名
function findAarPom(){
    echo "查找此目录是否有aar及pom:$1"
    targetDir=`ls $1`
    for fileName in $targetDir
    do
        if [[ -d  $1"/"$fileName ]]; then
            # 还是目录,则递归找下一级
            findAarPom $1"/"$fileName
        else
          # 如果是文件,判断后缀,如果符合期望,则将文件路径拼接好放于对应数组最后一位
            if [[ ${fileName:0-4} == '.aar' ]]; then
                aars[${#aars[@]}]=$1"/"$fileName
            elif [[ ${fileName:0-4} == '.pom' ]]; then
                poms[${#poms[@]}]=$1"/"$fileName
            fi
        fi
    done
}

findAarPom $targetPath
echo "============"
echo "aar有:《共${#aars[@]}个》"
echo "${aars[@]}"
echo "pom有:《共${#poms[@]}个》"
echo "${poms[@]}"
echo "============"

# 一个aar文件必然对应会有一个pom文件,如果数量不对,一定是打包出错
if [[ ${#aars[@]} -ne ${#poms[@]} ]]; then
    echo "-- !!! pom文件与aar不对称,请检查aar打包配置,上传任务 退出 !!! --"
    exit 1
fi
if [[ ${#aars[@]} == 0 ]]; then
    echo "-- !!! 未找到aar文件,请检查aar打包配置,上传任务 退出 !!! --"
    exit 1
fi

# 定义将目标pom及aar上传到maven指定仓库的函数
# 参数$1:为pom文件
# 参数$2:为aar文件
function upload(){
    echo "开始上传:"
    echo $1
    echo $2
    # mvn上传命令,这里由于将上传用户名密码配置于全局maven settings.xml,则无需再指定用户名密码
    mvn deploy:deploy-file \
    -DpomFile="$1" \
    -DgeneratePom=false \
    -Dfile="$2" \
    -Durl="你自己的maven服务器地址" \
    -DrepositoryId="deploymentRepo" \
    -Dpackaging=aar
}

# 循环上传
for (( i=0;i<${#aars[@]};i++ )); do
    echo "正在处理第$[$i+1]个,共${#aars[@]}个"
    upload "${poms[$i]}" "${aars[$i]}"
done

上传完成后在android中引用

    debugImplementation 'com.xyy.saas_flutter:flutter_debug:1.1.7-SNAPSHOT'

    releaseImplementation 'com.xyy.saas_flutter:flutter_release:1.1.7-SNAPSHOT'

在开发中遇到的问题
1.关于android和Ios中的跳转传参问题
这个问题在android端还是比较方便的 但是的在Ios端并不怎么好实现
最终决定使用flutter_boost来完成android和Ios与Flutter的通信操作
flutter_boost github地址:https://github.com/alibaba/flutter_boost
集成文档:https://github.com/alibaba/flutter_boost/blob/master/INTEGRATION.md
集成文档给出了 但是没有android的 尴尬
下满分享下android的集成
(1)在flutter的 pubspec.yaml工程中添加

  flutter_boost:
    git:
      url: 'https://github.com/alibaba/flutter_boost.git'
      ref: 'v1.17.1-hotfixes'

(2)修改android工程
使用本地工程的时候需要在工程共添加

 implementation project(':flutter_boost')

使用aar的时候不需要添加
(3)在android工程中添加对应的条状路由配置

public class PageRouter {

//在map中添加对应路由的key和value
 public final static Map<String, String> pageName = new HashMap<String, String>() {{
     put(NAME, "name");
 }};


 public static void openPageByUrl(Context context, String url, Map<String, Object> params) {
     openPageByUrl(context, url, params, 0);
 }

 public static void openPageByUrl(Context context, String url, Map<String, Object> params, int requestCode) {
     String path = url.split("\\?")[0];
     LogUtils.i("openPageByUrl", path);
     try {
         if (pageName.containsKey(path)) {
             Intent intent = MyFlutterActivity.withNewEngine().url(Objects.requireNonNull(pageName.get(path))).params(params)
                     .backgroundMode(MyFlutterActivity.BackgroundMode.opaque).build(context);
             if (context instanceof Activity) {
                 Activity activity = (Activity) context;
                 activity.startActivityForResult(intent, requestCode);
             } else {
                 context.startActivity(intent);
             }

         }

     } catch (Throwable t) {
         LogUtils.e(t.getMessage());
     }
 }
}

(4)在使用默认的flutter_boost启动界面的时候可能碰到状态栏丢失的情况
所以最好集成BoostFlutterActivity写一个新的activity方便处理状态栏和activity进出动画

public class MyFlutterActivity extends BoostFlutterActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       //重写设置状态栏
        StatusBarUtil.setColor(this, ContextCompat.getColor(this, R.color.colorWhite), 0);
        StatusBarUtil.StatusBarLightMode(this);
    }
    //这个必须要写 否则不生效
    public static NewEngineIntentBuilder withNewEngine() {
        return new NewEngineIntentBuilder(MyFlutterActivity.class);
    }


    @Override
    public void finish() {
        super.finish();
       //动画
        overridePendingTransition(R.anim.activity_trans_right_in, R.anim.activity_trans_right_out);
    }
}

(5)跳转并传参
//params 传多个参数可以使用json的形式

    PageRouter.openPageByUrl(this, key, params);

2.在flutter中的网络框架使用的dio结果在ios的弹出loading的时候出现卡顿现象
解决方式:1.服务换证书 (但是后台太忙暂时没有支持的人员)
2.ios使用原生的loading解决
3.在使用dio的时候出现ios部分手机 网络请求缓慢问题
解决方法:请求的时候使用http 2.0协议
插件地址:https://github.com/flutterchina/dio/tree/master/plugins/http2_adapter

相关文章

网友评论

      本文标题:Flutter混合开发实战

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