Flutter- Android项目集成flutter模块

Flutter- Android项目集成flutter模块,第1张

Android项目集成flutter模块 创建Flutter module添加Flutter module依赖Native跳转Flutter页面 -Activityflutter路由配置Android中跳转指定路由单例FlutterEngine缓存管理在Application中初始化使用 Flutter跳转到NativeNative创建抽象BridgeFlutter创建Bridge使用 Native端发送消息到Flutter端构建flutter aar

创建Flutter module

在做混合开发之前我们首先需要创建一个Flutter module

假如Native项目是:xxx/flutter_hybrid/native项目

$ cd xxx/flutter_hybrid

//create flutter module
$ flutter create -t module flutter_module

//指定报名
$ flutter create -t module --org cn.xxstudy flutter_module

也可以使用Androidstudio创建

添加Flutter module依赖

settings.gradle添加如下代码

include  ':app'
...
setBinding(new Binding([gradle: this]))
evaluate(new File(
        settingsDir.parentFile,
        'flutter_module/.android/include_flutter.groovy'
))

//可选,主要作用是可以在当前projec中显示flutter_module方便查看和编写代码
include ':flutter_module'
project(':flutter_module').projectDir = new File('../flutter_module')


setBindingevaluate允许Flutter模块包括它自己在内的任何flutter插件,在settings.gradle中以类似::flutterpackage_info:vidoe_palyer的方式存在

添加依赖:app/build.gradle

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

必须添加Java8的编译选项

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}
Native跳转Flutter页面 -Activity 最简单的方式(不推荐)

AndroidManifest.xml中注册

<activity
  android:name="io.flutter.embedding.android.FlutterActivity"
  android:theme="@style/MyTheme"
  android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
  android:hardwareAccelerated="true"
  android:windowSoftInputMode="adjustResize"
  />

startActivitystartActivity(new Intent(context, FlutterActivity.class

这个时候target flutter page 就是Flutter module中的默认页面,如果flutter 中有多个页面,需要跳转时指定路由名称,flutter 中也需要进行路由配置

flutter路由配置
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      initialRoute: '/',
      routes: {
        'login': (context) => const ConnectLogin(),
        '/': (context) => const RefreshListViewDemo()
      },
    );
  }
}
Android中跳转指定路由
 Intent intent = FlutterActivity.withNewEngine()
         .initialRoute("login").build(this);
 startActivity(intent);
推荐方式
由于上述的方式每次都需要创建一个FlutterEngine,创建FlutterEngine代价是比较大的,一些低端手机在跳转时会出现短暂的黑屏问题,因此可以先提前缓存好FlutterEngine 单例FlutterEngine缓存管理
public class FlutterCacheManager {
    public static final String LIST = "list";
    public static final String LOGIN = "login";

    private FlutterCacheManager() {
    }

    public static FlutterCacheManager getInstance() {
        return FlutterCacheManagerHolder.INSTANCE;
    }

    private static class FlutterCacheManagerHolder {
        private static final FlutterCacheManager INSTANCE = new FlutterCacheManager();
    }

    public void preLoad(Context context) {
        Looper.myQueue().addIdleHandler(() -> {
            initFlutterEngine(context, LIST);
            initFlutterEngine(context, LOGIN);
            return false;
        });
    }

    @NonNull
    public FlutterEngine getCacheFlutterEngine(Context context, String moduleName) {
        FlutterEngine flutterEngine = FlutterEngineCache.getInstance().get(moduleName);
        if (flutterEngine == null) {
            flutterEngine = initFlutterEngine(context, moduleName);
        }
        return flutterEngine;
    }

    private FlutterEngine initFlutterEngine(Context context, String moduleName) {
        FlutterEngine flutterEngine = new FlutterEngine(context);
        //set route name
        flutterEngine.getNavigationChannel().setInitialRoute(moduleName);
        //init bridge
        FlutterBridge.getInstance().init(flutterEngine);
        flutterEngine.getDartExecutor().executeDartEntrypoint(
                DartExecutor.DartEntrypoint.createDefault()
        );
        FlutterEngineCache.getInstance().put(moduleName, flutterEngine);

    }
}
在Application中初始化
@Override
public void onCreate() {
    context = this;
    super.onCreate();
    FlutterCacheManager.getInstance().preLoad(this);
    ...
 }
使用
FlutterCacheManager.getInstance().getCacheFlutterEngine(this, FlutterCacheManager.LOGIN);
Intent intent=FlutterActivity.withCachedEngine(FlutterCacheManager.LOGIN).build(this);
Flutter跳转到Native Native创建抽象Bridge
public interface IBridge<P, Callback> {

    void sendMessage(String method, Object arguments);

    void sendMessage(String method, Object arguments, MethodChannel.Result callback);

    void onBack(P p);

    void goToNative(P p);
}
public class FlutterBridge implements IBridge<Object, MethodChannel.Result>, MethodChannel.MethodCallHandler {

    private List<MethodChannel> methodChannels = new ArrayList<>();

    private FlutterBridge() {
    }

    public static FlutterBridge getInstance() {
        return FlutterBridgeHolder.INSTANCE;
    }

    private static class FlutterBridgeHolder {
        private static final FlutterBridge INSTANCE = new FlutterBridge();
    }

    //需要在FlutterCacheManager 创建FlutterEngine时初始化
    public void init(FlutterEngine engine) {
        //name need to be the same as flutter
        MethodChannel methodChannel = new MethodChannel(engine.getDartExecutor(), "FlutterBridge");
        //set handler
        methodChannel.setMethodCallHandler(this);
        methodChannels.add(methodChannel);
    }

    @Override
    public void sendMessage(String method, Object arguments) {
        for (MethodChannel methodChannel : methodChannels) {
            methodChannel.invokeMethod(method, arguments);
        }
    }

    @Override
    public void sendMessage(String method, Object arguments, MethodChannel.Result callback) {
        for (MethodChannel methodChannel : methodChannels) {
            methodChannel.invokeMethod(method, arguments, callback);
        }
    }

    @Override
    public void onBack(Object o) {
        Activity currentActivity = ActivityManager.getInstance().getCurrentActivity();
        if (currentActivity != null && !currentActivity.isDestroyed()) {
            currentActivity.onBackPressed();
        }
    }

    @Override
    public void goToNative(Object o) {
        //start HomeActivity
        Activity currentActivity = ActivityManager.getInstance().getCurrentActivity();
        currentActivity.startActivity(new Intent(currentActivity, HomeActivity.class));
        currentActivity.finish();
    }

    @Override
    public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
        switch (call.method) {
            case "onBack":
                onBack(call.arguments);
                break;
            case "goToNative":
                goToNative(call.arguments);
                break;
            default:
                break;
        }
    }
}
Flutter创建Bridge
class FlutterBridge {
  static final FlutterBridge _instance = FlutterBridge._();
  final MethodChannel _bridge = const MethodChannel('FlutterBridge');
  final _listener = {};

  FlutterBridge._() {
    _bridge.setMethodCallHandler((call) {
      String method = call.method;
      if (_listener[method] != null) {
        return _listener[method](call);
      }
      return Future.value();
    });
  }

  static FlutterBridge getInstance() {
    return _instance;
  }

  register(String method, Function(MethodCall) callback) {
    _listener[method] = callback;
  }

  unRegister(String method) {
    _listener.remove(method);
  }

  MethodChannel get bridge => _bridge;

  goToNative([Map? params]) {
    _bridge.invokeMethod("goToNative", params);
  }

  onBack() {
    _bridge.invokeMethod('onBack');
  }
}
使用
child: ElevatedButton(
    onPressed: () {
      FlutterBridge.getInstance().goToNative();
    },
    style: ButtonStyle(
        elevation: MaterialStateProperty.all(0),
        backgroundColor:
            MaterialStateProperty.all<Color>(Colors.transparent)
    child: Text("LOGIN",
        style: TextStyle(
            fontFamily: 'QuicksandMedium', fontSize: 19.sp)))),
Native端发送消息到Flutter端
sendMessage.setOnClickListener((view) -> {
    FlutterBridge.getInstance().sendMessage("listener", "by Native message", new MethodChannel.Result() {
        @Override
        public void success(@Nullable Object result) {
            LogUtils.Sensi("LoginHomeActivity.java",
                    "success(LoginHomeActivity.java:156)" + result);
        }
        @Override
        public void error(String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails) {
            LogUtils.Sensi("LoginHomeActivity.java",
                    "error(LoginHomeActivity.java:163)errorCode=" + errorCode + ",errorMessage=" + errorMessage);
        }
        @Override
        public void notImplemented() {
        }
    });
});
 @override
 void initState() {
   FlutterBridge.getInstance().register('listener', (MethodCall call) {
     print(
         'receive Native message arguments=${call.arguments}  method=${call.method}');
     return Future.value(
         'by flutter message ${DateTime.now().toIso8601String()}');
   });
   super.initState();
 }
 
 @override
void dispose() {
  FlutterBridge.getInstance().unRegister('listener');
  super.dispose();
}
构建flutter aar
$ cd .android/
$ ./gradlew flutter:assembleRelease

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/992519.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存