怎么提高自己网站的知名度,WordPress5更改logo,前端seo搜索引擎优化,无经验做网站前言
实际开发混合项目时#xff0c;常常会有页面跳转的需求 如果是原生界面和flutter界面需要互相跳转 这种情况应该怎么处理呢#xff1f; 今天这篇博客主要就来介绍下这个情况 其实想一下#xff0c;这个问题可以拆成四个小的问题来分析#xff1a; 1#xff1a;原生界…前言
实际开发混合项目时常常会有页面跳转的需求 如果是原生界面和flutter界面需要互相跳转 这种情况应该怎么处理呢 今天这篇博客主要就来介绍下这个情况 其实想一下这个问题可以拆成四个小的问题来分析 1原生界面自己怎么跳转 2Flutter界面互相跳转 2原生界面跳转Flutter 3Flutter跳转原生界面 第一点很好理解 拿android来说 就是startActivity 本篇博客主要讲一下后面三点的办法 当然本篇博客主要讲我知道的方法 如果有更好的方法欢迎评论区留言
Flutter界面互相跳转
Navigator跳转
Flutter界面互相跳转一般使用Navigator类 比如我们要跳转到另外一个页面我们可以这样写
final result await Navigator.push(context, MaterialPageRoute(builder: (context) SecondPage(params: firstpage,)));使用Navigator.push进行跳转参数放在目标页面的构造方法内 result 为页面返回后传递的值 而SecondPage退出的时候则可以这样写
Navigator.pop(context, hi good);第二个参数是返回给上一个页面的数据
getx跳转
除了使用自带的Navigator我们还可以借助第三方库 先引入getx get: 4.6.0跳转的时候
final result await Get.to(GetxSecondPage(params: firstpage,));返回的时候
Get.back(result: hi good);当然这是最基础的用法 我们还可以自定义路由 首先我们要使用GetMaterialApp
class GetxJump extends StatelessWidget {const GetxJump({super.key});// This widget is the root of your application.overrideWidget build(BuildContext context) {return GetMaterialApp(title: Flutter Demo,theme: ThemeData(primarySwatch: Colors.blue,),initialRoute: /,getPages: [GetPage(name: /, page: () GetxFirstPage()),GetPage(name: /GetxSecondPage, page: () GetxSecondPage()),],// home: GetxFirstPage(),);}
}在getPages里定义我们的路由/为默认的第一个页面 这时候就不用配置home属性了 然后GetxFirstPage跳转到GetxSecondPage的时候
final result await Get.toNamed(/GetxSecondPage,arguments: firstpage--arguments);返回的逻辑还是一样的用Get.back即可
原生界面跳转Flutter
fragment显示Flutter页面
Flutter的页面其实都是存在于一个叫做FlutterActivity的安卓页面上的 我们可以打开我们的任意一个Flutter项目可以看到MainActivity是继承的FlutterActivity 其实我们也可以把Flutter的页面理解为一个webview 在讲跳转之前我们先尝试用一个fragment来显示Flutter页面 我们在Flutter项目中创建一个Activity布局如下
LinearLayout xmlns:androidhttp://schemas.android.com/apk/res/androidandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentandroid:orientationverticalandroid:gravitycenterFrameLayoutandroid:idid/flutterframelayoutandroid:layout_widthmatch_parentandroid:layout_height500dp//LinearLayout然后我们在Activity的onCreate方法中写如下代码 var flutterFragment FlutterFragment.createDefault()supportFragmentManager.beginTransaction().add(R.id.flutterframelayout, flutterFragment).commit()注意我们的Activity并没有继承FlutterActivity 而是直接继承最基础的AppCompatActivity 这时候我们运行代码会发现我们也显示出了Flutter的Hello world界面 这时候flutter的页面大小就是我们fragment的大小所以看起来有点怪 其实我们还可以让这个flutter页面和我们的Activity通信 这样一个页面就又有原生又有flutter界面了 具体通信可以查看这篇博客 Flutter与Native通信的方式MethodChannel 讲这个主要是为了帮助大家更好的认识Flutter 讲完这点再来介绍一个东西 FlutterEngine 我们刚刚用FlutterFragment.createDefault()来创建了一个FlutterFragment 其实FlutterFragment还有两种创建方式 这边都列出来
FlutterFragment.withNewEngine().buildFlutterFragment() 重新创建一个Engine指定main方法作为Flutter程序入口
FlutterFragment.createDefault() 使用默认的指定main方法作为Flutter程序入口
FlutterFragment.withCachedEngine(engine_id) 根据engine_id找到Engine然后Engine可以配置自己指定的程序入口可以看到这里面有一个Engine那么Engine是什么呢 这里的Engine其实指的是FlutterEngine 下面就介绍下它
认识Engine
Engine翻译过来有引擎发动机的意思 说明它的确是Flutter中很重要的一部分 Engine有一个很重要的作用就是负责配置Flutter页面的方法入口 比如我们在写最简单的Flutter项目时会发现Flutter的代码都是以main方法作为入口 就像这样
void main() runApp(const MyApp());加上前面说的Flutter的页面是类似以webview的形式放在安卓的Activity上面的 那么他们是怎么关联起来的呢 下面就会一一讲到 这部分内容有点多如果想直接看用法 可以点到“跳转到一个FlutterActivity”目录查看怎么使用就好了
FlutterFragment如何被创建
我们先看下一个FlutterFragmentActivity是怎么处理的 在FlutterFragmentActivity的onCreate方法里我们找到了一个ensureFlutterFragmentCreated方法 这个方法的代码我贴出来 private void ensureFlutterFragmentCreated() {if (flutterFragment null) {// If both activity and fragment have been destroyed, the activity restore may have// already recreated a new instance of the fragment again via the FragmentActivity.onCreate// and the FragmentManager.flutterFragment retrieveExistingFlutterFragmentIfPossible();}if (flutterFragment null) {// No FlutterFragment exists yet. This must be the initial Activity creation. We will create// and add a new FlutterFragment to this Activity.flutterFragment createFlutterFragment();FragmentManager fragmentManager getSupportFragmentManager();fragmentManager.beginTransaction().add(FRAGMENT_CONTAINER_ID, flutterFragment, TAG_FLUTTER_FRAGMENT).commit();}}可以看到就是调用createFlutterFragment去创建了一个Fragment 其实这个Fragment就是显示我们Flutter页面的Fragment 不信再来看下createFlutterFragment方法 NonNullprotected FlutterFragment createFlutterFragment() {final BackgroundMode backgroundMode getBackgroundMode();final RenderMode renderMode getRenderMode();final TransparencyMode transparencyMode backgroundMode BackgroundMode.opaque? TransparencyMode.opaque: TransparencyMode.transparent;final boolean shouldDelayFirstAndroidViewDraw renderMode RenderMode.surface;if (getCachedEngineId() ! null) {Log.v(TAG,Creating FlutterFragment with cached engine:\n Cached engine ID: getCachedEngineId() \n Will destroy engine when Activity is destroyed: shouldDestroyEngineWithHost() \n Background transparency mode: backgroundMode \n Will attach FlutterEngine to Activity: shouldAttachEngineToActivity());return FlutterFragment.withCachedEngine(getCachedEngineId()).renderMode(renderMode).transparencyMode(transparencyMode).handleDeeplinking(shouldHandleDeeplinking()).shouldAttachEngineToActivity(shouldAttachEngineToActivity()).destroyEngineWithFragment(shouldDestroyEngineWithHost()).shouldDelayFirstAndroidViewDraw(shouldDelayFirstAndroidViewDraw).build();} else {Log.v(TAG,Creating FlutterFragment with new engine:\n Background transparency mode: backgroundMode \n Dart entrypoint: getDartEntrypointFunctionName() \n Dart entrypoint library uri: (getDartEntrypointLibraryUri() ! null ? getDartEntrypointLibraryUri() : \\) \n Initial route: getInitialRoute() \n App bundle path: getAppBundlePath() \n Will attach FlutterEngine to Activity: shouldAttachEngineToActivity());return FlutterFragment.withNewEngine().dartEntrypoint(getDartEntrypointFunctionName()).dartLibraryUri(getDartEntrypointLibraryUri()).dartEntrypointArgs(getDartEntrypointArgs()).initialRoute(getInitialRoute()).appBundlePath(getAppBundlePath()).flutterShellArgs(FlutterShellArgs.fromIntent(getIntent())).handleDeeplinking(shouldHandleDeeplinking()).renderMode(renderMode).transparencyMode(transparencyMode).shouldAttachEngineToActivity(shouldAttachEngineToActivity()).shouldDelayFirstAndroidViewDraw(shouldDelayFirstAndroidViewDraw).build();}}太长不想看的话直接看结论 其实就是通过判断getCachedEngineId缓存的id是否有缓存的id 然后来创建Fragment 如果有idwithCachedEngine方法会创建一个CachedEngineFragmentBuilder 否则就是withNewEngine创建一个NewEngineFragmentBuilder 两个FragmentBuilder的build方法其实都是利用反射去创建了FlutterFragment 并且在createArgs方法内进行了传参 如下 NonNullpublic T extends FlutterFragment T build() {try {SuppressWarnings(unchecked)T frag (T) fragmentClass.getDeclaredConstructor().newInstance();if (frag null) {throw new RuntimeException(The FlutterFragment subclass sent in the constructor ( fragmentClass.getCanonicalName() ) does not match the expected return type.);}Bundle args createArgs();frag.setArguments(args);return frag;} catch (Exception e) {throw new RuntimeException(Could not instantiate FlutterFragment subclass ( fragmentClass.getName() ), e);}}等下这种创建Fragment的方式和我们上面写的fragment显示Flutter页面的例子不是一样吗 对 我们上面其实就是自己写了个简单的FlutterFragmentActivity 我们自己创建了FlutterFragment然后显示了出来 而FlutterFragmentActivity默认帮我们创建了并且默认入口是main()方法 查看上面代码 发现如果找不到getCachedEngineId 走的是
FlutterFragment.withNewEngine()所以我们再来看FlutterFragment创建的三种方式
FlutterFragment.withNewEngine().buildFlutterFragment() 重新创建一个Engine指定main方法作为Flutter程序入口
FlutterFragment.createDefault() 使用默认的指定main方法作为Flutter程序入口
FlutterFragment.withCachedEngine(engine_id) 根据engine_id找到Engine然后Engine可以配置自己指定的程序入口其实第二种内部调用的就是第一种二者是一样的 NonNullpublic static CachedEngineFragmentBuilder withCachedEngine(NonNull String engineId) {return new CachedEngineFragmentBuilder(engineId);}NonNullpublic static FlutterFragment createDefault() {return new NewEngineFragmentBuilder().build();}//可以看到是一样的NonNullpublic static NewEngineFragmentBuilder withNewEngine() {return new NewEngineFragmentBuilder();}那么NewEngineFragmentBuilder和CachedEngineFragmentBuilder有什么区别呢
FragmentBuilder
刚刚已经分析了通过判断getCachedEngineId缓存的id是否有缓存的id 有就通过CachedEngineFragmentBuilder创建Fragment 否则通过NewEngineFragmentBuilder创建Fragment 先看CachedEngineFragmentBuilder 它拿到缓存的engineId后通过Bundle 传给了创建的FlutterFragment
Bundle args new Bundle();
args.putString(ARG_CACHED_ENGINE_ID, engineId);FlutterFragment通过getCachedEngineId方法得到了engineId NullableOverridepublic String getCachedEngineId() {return getArguments().getString(ARG_CACHED_ENGINE_ID, null);}那么getCachedEngineId是什么时候调用的呢? 会发现这个方法是来自于FlutterActivityAndFragmentDelegate.Host接口 FlutterFragment刚好实现了这个接口 然后FlutterActivityAndFragmentDelegate的setupFlutterEngine方法中会调用getCachedEngineId 先得到缓存的cachedEngineId 然后用单例类FlutterEngineCache根据cachedEngineId就得到了FlutterEngine String cachedEngineId host.getCachedEngineId();if (cachedEngineId ! null) {flutterEngine FlutterEngineCache.getInstance().get(cachedEngineId);isFlutterEngineFromHost true;if (flutterEngine null) {throw new IllegalStateException(The requested cached FlutterEngine did not exist in the FlutterEngineCache: cachedEngineId );}return;}而setupFlutterEngine方法是被FlutterActivityAndFragmentDelegate的onAttach调用 FlutterActivityAndFragmentDelegate的onAttach方法最终又被FlutterFragment的onAttach方法调用 如下代码 Overridepublic void onAttach(NonNull Context context) {super.onAttach(context);delegate delegateFactory.createDelegate(this);delegate.onAttach(context);if (getArguments().getBoolean(ARG_SHOULD_AUTOMATICALLY_HANDLE_ON_BACK_PRESSED, false)) {requireActivity().getOnBackPressedDispatcher().addCallback(this, onBackPressedCallback);}context.registerComponentCallbacks(this);}这时候我们就清楚了在FlutterFragment调用onAttach生命周期方法的时候 就根据传递的cachedEngineId得到了缓存的FlutterEngine 那么如果用的是NewEngineFragmentBuilder 这时候没有cachedEngineId会怎么办呢其实就会直接创建一个FlutterEngine 所以我们大概了解了 两个FragmentBuilder的区别主要在于创建FlutterFragment是否有缓存的Engineid 然后根据这种不同来决定是否使用缓存的FlutterEngine还是直接创建新的 那么FlutterEngine又有什么作用呢
FlutterEngine
顾名思义FlutterEngine是Flutter的引擎和发动机 我们还是看两个NewEngineFragmentBuilder 发现FlutterFragment.withNewEngine()创建了NewEngineFragmentBuilder之后 马上调用了dartEntrypoint(getDartEntrypointFunctionName())方法 里面调用的getDartEntrypointFunctionName方法源码如下 NonNullpublic String getDartEntrypointFunctionName() {try {Bundle metaData getMetaData();String desiredDartEntrypoint metaData ! null ? metaData.getString(DART_ENTRYPOINT_META_DATA_KEY) : null;return desiredDartEntrypoint ! null ? desiredDartEntrypoint : DEFAULT_DART_ENTRYPOINT;} catch (PackageManager.NameNotFoundException e) {return DEFAULT_DART_ENTRYPOINT;}}可以看到是根据key来取一个字符串 取不到这返回默认的DEFAULT_DART_ENTRYPOINT 而这个默认的值为
static final String DEFAULT_DART_ENTRYPOINT main;这下我们终于看到了就是main方法 getDartEntrypointFunctionName得到的字符串 会赋值给NewEngineFragmentBuilder的dartEntrypoint 并最终通过Bundle传递给FlutterFragment
args.putString(ARG_DART_ENTRYPOINT, dartEntrypoint);FlutterFragment在getDartEntrypointFunctionName方法中得到这个参数 可以看到得不到的时候默认取main OverrideNonNullpublic String getDartEntrypointFunctionName() {return getArguments().getString(ARG_DART_ENTRYPOINT, main);}现在我们可以做一个初步的总结 FlutterFragmentActivity创建了Fragment用于显示Flutter页面 然后通过创建NewEngineFragmentBuilder并调用NewEngineFragmentBuilder的dartEntrypoint方法 从而设置了Flutter的程序入口 那么具体是怎么设置的呢 其实getDartEntrypointFunctionName方法也是来自于FlutterActivityAndFragmentDelegate.Host接口 并且被FlutterActivityAndFragmentDelegate的doInitialFlutterViewRun方法调用 doInitialFlutterViewRun方法又在FlutterActivityAndFragmentDelegate的onStart方法中被调用 FlutterActivityAndFragmentDelegate的onStart方法被FlutterFragment的onStart方法调用 这时候我们就知道了归根结底还是FlutterFragment的生命周期 然后我们继续看doInitialFlutterViewRun方法在得到这个字符串后会做什么 重点来了 DartExecutor.DartEntrypoint entrypoint libraryUri null? new DartExecutor.DartEntrypoint(appBundlePathOverride, host.getDartEntrypointFunctionName()): new DartExecutor.DartEntrypoint(appBundlePathOverride, libraryUri, host.getDartEntrypointFunctionName());flutterEngine.getDartExecutor().executeDartEntrypoint(entrypoint, host.getDartEntrypointArgs());可以看到根据getDartEntrypointFunctionName返回的程序入口 从而创建了DartExecutor.DartEntrypoint类 并且调用flutterEngine.getDartExecutor().executeDartEntrypoint(entrypoint, host.getDartEntrypointArgs()); 从而完成了入口的设置 这时候我们就清楚了 在FlutterFragment调用onAttach生命周期方法的时候 就根据传递的cachedEngineId得到了缓存的FlutterEngine 没有缓存则创建新的FlutterEngine 然后FlutterFragment调用onStart生命周期方法的时候 会触发FlutterActivityAndFragmentDelegate的onStart方法里面的doInitialFlutterViewRun方法 方法内部调用getDartEntrypointFunctionName从而得到程序入口 并且把这个入口配置给到了FlutterEngine 那么下一个问题 NewEngineFragmentBuilder配置的入口可以改吗 当然 我们也可以通过调用flutterEngine.getDartExecutor().executeDartEntrypoint(entrypoint, host.getDartEntrypointArgs()); 完成入口的设置 文章后面就会讲具体怎么设置 回到上面两个FragmentBuilder 我们也可以知道 不管是缓存的还是新创建的FragmentBuilder 归根结底都要得到一个FlutterEngine 而FlutterEngine才是真正设置入口的类 他的executeDartEntrypoint方法需要传入一个DartEntrypoint类 DartEntrypoint类的dartEntrypointFunctionName属性用来配置入口方法的名称 最后看下executeDartEntrypoint方法吧 内部利用flutterJNI去寻找入口这块我们就不继续看下去了 public void executeDartEntrypoint(NonNull DartEntrypoint dartEntrypoint, Nullable ListString dartEntrypointArgs) {if (isApplicationRunning) {Log.w(TAG, Attempted to run a DartExecutor that is already running.);return;}TraceSection.begin(DartExecutor#executeDartEntrypoint);try {Log.v(TAG, Executing Dart entrypoint: dartEntrypoint);flutterJNI.runBundleAndSnapshotFromLibrary(dartEntrypoint.pathToBundle,dartEntrypoint.dartEntrypointFunctionName,dartEntrypoint.dartEntrypointLibrary,assetManager,dartEntrypointArgs);isApplicationRunning true;} finally {TraceSection.end();}}知道了这一块我们做个最终总结 1FlutterFragmentActivity根据Intent是否传递过来缓存的engineid决定采用不同方式创建FlutterFragment 有缓存则用CachedEngineFragmentBuilder 无缓存则用NewEngineFragmentBuilder 二者都是利用反射创建了FlutterFragment 并且将engineid传递给了FlutterFragment 2:FlutterFragment根据是否有engineid来得到一个FlutterEngine 有engineid通过单例类FlutterEngineCache的Map得到缓存的FlutterEngine 无engineid创建新的FlutterEngine 这一步在FlutterFragment的onAttach方法执行 3FlutterFragment的onStart方法判断是否有ARG_DART_ENTRYPOINT参数 没有就默认返回main作为程序入口 ARG_DART_ENTRYPOINT参数的值赋值给了创建的DartExecutor.DartEntrypoint类 并最终被FlutterEngine的executeDartEntrypoint使用了这个类 从而完成入口的配置
这是关于FlutterFragmentActivity的整体逻辑 继承的是FragmentActivity 其实还有另外一个FlutterActivity类 继承的是Activity 并实现FlutterActivityAndFragmentDelegate.Host接口 FlutterActivity类也是可以显示Flutter页面的Activity 和FlutterFragmentActivity有一些区别 这块我没有细看了 貌似他是用FlutterActivityAndFragmentDelegate创建不同的flutterView来显示Flutter页面的 这块感兴趣的可以看下目前我基本都是用FlutterFragmentActivity 了解了这么多我们跳转到一个FlutterActivity其实就很简单了
跳转到一个FlutterActivity
和上面讲的NewEngineFragmentBuilder、CachedEngineFragmentBuilder一样 Flutter提供了两个IntentBuilder方便我们跳转 NewEngineIntentBuilder和CachedEngineIntentBuilder 区别其实就是是否有缓存的engineid 下面介绍具体跳转方式
NewEngineIntentBuilder
这个就比较简单了首先在我们的目标Activity里面创建NewEngineIntentBuilder 注意目标Activity要继承FlutterFragmentActivity companion object {fun NewEngineIntentBuilder(): NewEngineIntentBuilder {return NewEngineIntentBuilder(MainActivity3::class.java)}}然后跳转代码为 startActivity(MainActivity3.NewEngineIntentBuilder().build(thisMainActivity))可以看到创建了NewEngineIntentBuilder并调用它的build方法即可 build方法其实就是返回了一个intent NonNullpublic Intent build(NonNull Context context) {Intent intent new Intent(context, activityClass).putExtra(EXTRA_INITIAL_ROUTE, initialRoute).putExtra(EXTRA_BACKGROUND_MODE, backgroundMode).putExtra(EXTRA_DESTROY_ENGINE_WITH_ACTIVITY, true);if (dartEntrypointArgs ! null) {intent.putExtra(EXTRA_DART_ENTRYPOINT_ARGS, new ArrayList(dartEntrypointArgs));}return intent;}通过这种方式最终目标Activity创建Fragment的时候 用的将会是NewEngineFragmentBuilder 从而创建新的FlutterEngine 而这种跳转页面的方式只能跳转到Flutter的main方法 也就是不能决定Flutter的程序入口 要改变入口还是需要FlutterEngine
CachedEngineIntentBuilder
使用CachedEngineIntentBuilder跳转 一样在目标Activity里创建CachedEngineIntentBuilder companion object {fun withCachedEngine(cachedEngineId: String): CachedEngineIntentBuilder {return CachedEngineIntentBuilder(MainActivity3::class.java, cachedEngineId)}}跳转的代码这样写 startActivity(MainActivity3.withCachedEngine(App.your_engine_id).build(thisMainActivity).apply {putExtra(method, showtestpage)putExtra(params, 参数params)})其实也是创建了CachedEngineIntentBuilder并调用它的build方法即可 build方法其实也是返回了一个intent NonNullpublic Intent build(NonNull Context context) {return new Intent(context, activityClass).putExtra(EXTRA_CACHED_ENGINE_ID, cachedEngineId).putExtra(EXTRA_DESTROY_ENGINE_WITH_ACTIVITY, destroyEngineWithActivity).putExtra(EXTRA_BACKGROUND_MODE, backgroundMode);}那么区别在哪呢 就在于withCachedEngine方法内传递的cachedEngineId 这个cachedEngineId需要我们定义好 我这里是定义在Application里 定义好之后我们再去创建FlutterEngine private val flutterEngine by lazy {//显示默认的页面会找flutter的main方法FlutterEngine(this).apply {dartExecutor.executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault())}}然后把创建的FlutterEngine存入到单例类FlutterEngineCache中
FlutterEngineCache.getInstance().put(your_engine_id, flutterEngine)这里your_engine_id就是key 要和withCachedEngine方法内传递的cachedEngineId保持一致才可以找到对应的FlutterEngine 通过这种方式最终目标Activity创建Fragment的时候 用的将会是CachedEngineFragmentBuilder 从而找到缓存的FlutterEngine 而这种跳转页面的方式 可以通过创建DartExecutor.DartEntrypoint类 并且调用flutterEngine.getDartExecutor().executeDartEntrypoint(entrypoint, host.getDartEntrypointArgs()); 便完成了入口的设置
入口和传参
那么具体怎么设置呢 其实就在于我们创建FlutterEngine的方式 其实创建FlutterEngine的方式和创建FlutterFragment创建的方式差不多 FlutterFragment提供这三种方式创建第一种和第二种其实一样
FlutterFragment.withNewEngine().buildFlutterFragment() 重新创建一个Engine指定main方法作为Flutter程序入口
FlutterFragment.createDefault() 使用默认的指定main方法作为Flutter程序入口
FlutterFragment.withCachedEngine(engine_id) 根据engine_id找到Engine然后Engine可以配置自己指定的程序入口FlutterEngine则是提供三种方式创建第一种和第二种其实一样
FlutterEngine(this).apply {dartExecutor.executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault())
}//createDefault内部其实就是这样写的
FlutterEngine(this).apply {var entrypointDartEntrypoint(FlutterMain.findAppBundlePath(), main)dartExecutor.executeDartEntrypoint(entrypoint)
}FlutterEngine(this).apply {var entrypoint DartExecutor.DartEntrypoint(FlutterMain.findAppBundlePath(), testMethod)dartExecutor.executeDartEntrypoint(entrypoint)
}这里testMethod就是我们定义的程序入口了 这样在跳转到我们目标Activity后 Flutter就会加载main.dart文件里的testMethod()方法作为程序入口了 注意 testMethod()必须写在main.dart文件里 这块我暂时也没找到其他方法 页面跳转有了那么传参呢 可以看到我刚刚跳转的时候传递了两个参数给Intent putExtra(method, showtestpage)putExtra(params, 参数params)那么在目标Activity的configureFlutterEngine方法里我们可以这样处理 override fun configureFlutterEngine(flutterEngine: FlutterEngine) {super.configureFlutterEngine(flutterEngine)var channel MethodChannel(flutterEngine.dartExecutor.binaryMessenger, paramsChannel)intent?.apply {val path getStringExtra(method) ?: val params getStringExtra(params) ?: Log.d(MainActivity3, path是:path)Log.d(MainActivity3, params是:params)channel.invokeMethod(path, params)}}会发现其实还是用MethodChannel进行通信 然后来到Flutter端的代码 定义MethodChannel var commonNativeChannel MethodChannel(paramsChannel);在initState里面 overridevoid initState() {commonNativeChannel.setMethodCallHandler((MethodCall call) async {print(拿到参数 ${call.method});switch (call.method) {case showtestpage:print(拿到参数 ${call.arguments});//这里可以根据参数设置跳转不同page我这里刷新一下显示不做跳转处理setState(() {params call.arguments.toString();});break;default:print(Unknowm method ${call.method});//触发Android端的notImplemented方法throw MissingPluginException();}});super.initState();}这样指定跳转Flutter页面和传参就完成了
Flutter跳转原生界面
Flutter跳转指定原生页面需要用到MethodChannel进行通信 对MethodChannel不了解的可以看我的这篇博客 Flutter与Native通信的方式MethodChannel 下面展示具体的用法 首先是在Flutter端定义好MethodChannel的字段和方法 这里用两个按钮的点击事件来触发跳转 分别调用安卓端的jumpActivity和finish方法 当然也可以传参具体传参可以看上面的MethodChannel博客
class _MyjumpAndroidPageState extends StateMyjumpAndroidPage {var commonNativeChannel MethodChannel(ForNativePlugin);overridevoid initState() {super.initState();}overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(widget.title),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: Widget[ElevatedButton(onPressed: () {commonNativeChannel.invokeMethod(jumpActivity);}, child: Text(点击跳转到android页面)),ElevatedButton(onPressed: () {commonNativeChannel.invokeMethod(finish);}, child: Text(点击关闭当前Flutter页面))],),),);}
}然后来到我们安卓端 继承FlutterFragmentActivity类 照样创建MethodChannel 在configureFlutterEngine方法中 对这些被调用的方法进行处理即可 我这边只是打印了下日志 正常情况下StartActivity即可
class MainActivity4 : FlutterFragmentActivity() {private lateinit var flutterMethodChannel: MethodChannelcompanion object {fun withCachedEngine(cachedEngineId: String): CachedEngineIntentBuilder {return CachedEngineIntentBuilder(MainActivity4::class.java, cachedEngineId)}}override fun configureFlutterEngine(flutterEngine: FlutterEngine) {super.configureFlutterEngine(flutterEngine)flutterMethodChannel MethodChannel(flutterEngine.dartExecutor, ForNativePlugin)flutterMethodChannel.setMethodCallHandler { methodCall, result -when (methodCall.method) {finish - {Toast.makeText(thisMainActivity4, 关闭页面, Toast.LENGTH_SHORT).show()finish()}jumpActivity - {Toast.makeText(thisMainActivity4, 跳转页面, Toast.LENGTH_SHORT).show()}else - {// 表明没有对应实现result.notImplemented()}}}}
}源码
关于Flutter与Native页面互相跳转大体上就是这么多内容了 下面分享下这篇文章涉及到的源码地址 new_gradlesetting_native_jump_flutter