赞
踩
前面我们学习了Dart端页面的跳转是通过Navigator控制的,而在android原生开发中,采用的是Intent。那混合开发中,两者间的页面跳转又是如何实现的呢?
<activity
android:name="io.flutter.embedding.android.FlutterActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:theme="@style/Theme.AppCompat"
android:windowSoftInputMode="adjustResize" />
import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class MyBasicMessageChannel extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: BasicMessageChannelHome(), ); } } class BasicMessageChannelHome extends StatefulWidget { @override State<BasicMessageChannelHome> createState() => BasicMessageChannelHomeState(); } class BasicMessageChannelHomeState extends State<BasicMessageChannelHome> { var _basicMessage = BasicMessageChannel("BasicChannel", StringCodec()); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: Center( child: GestureDetector( child: Text('发送BasicMessageChannel'), onTap: () { _basicMessage.send('JumpNativeActivity').then((value) { print(value); }); }, ), ), ), ); }
import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class FlutterMethodChannel extends StatelessWidget { MethodChannel methodChannel = MethodChannel('nativeCall'); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: GestureDetector( onTap: () { _callNativeMethod(); }, child: Center( child: Text('调用Native方法'), ), ), ), ); } void _callNativeMethod() async { try { methodChannel.invokeMethod('JumpNativeActivity'); } catch (e) { print(e); } } }
package com.example.flutter_hello import android.content.Context import android.os.Bundle import android.util.Log import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.BasicMessageChannel import io.flutter.plugin.common.StringCodec const val TAG:String="MainActivity" class MainActivity : FlutterActivity() { override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) var channel = BasicMessageChannel( flutterEngine.dartExecutor.binaryMessenger, "BasicChannel", StringCodec.INSTANCE ) channel.setMessageHandler { message, reply -> startActivity( Intent( this, SecondActivity::class.java ) ) reply.reply("成功跳转") } } }
package com.example.flutter_hello import android.content.Context import android.content.Intent import android.os.Bundle import android.util.Log import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.StringCodec const val TAG:String="MainActivity" class MainActivity : FlutterActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Log.e(TAG,"onCreate") MethodChannel( flutterEngine!!.dartExecutor.binaryMessenger, "nativeCall" ).setMethodCallHandler { call, result -> run { if (call.method.equals("JumpNativeActivity")) { result.success("success") startActivity( Intent( this, SecondActivity::class.java ) ) } } } }
该方式是基于Navigator和routes的,所以,对于Dart端一定要配置好routes。
import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class DartPages extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( routes: <String, WidgetBuilder>{ 'home': (BuildContext context) => DartHomePage(), 'second': (BuildContext context) => DartSecondPage(), }, initialRoute: 'home', ); } } class DartHomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('HomePage'), centerTitle: true, ), body: const Center( child: Text('欢迎来到Dart主页'), ), floatingActionButton: FloatingActionButton( onPressed: () { MethodChannel methodChannel=const MethodChannel("nativeCall"); methodChannel.invokeMethod("toSecondActivity"); }, child: const Text('跳转'), ), ); } } class DartSecondPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('HomePage'), centerTitle: true, ), body: const Center( child: Text('欢迎来到Dart第二页'), ), ); } }
MainActivity
package com.example.flutter_hello import android.content.Context import android.content.Intent import android.os.Bundle import android.util.Log import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.StringCodec const val TAG:String="MainActivity" class MainActivity : FlutterActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Log.e(TAG,"onCreate") MethodChannel( flutterEngine!!.dartExecutor.binaryMessenger, "nativeCall" ).setMethodCallHandler { call, result -> run { if (call.method.equals("nativeMethod")) { result.success("success") Log.e(TAG, "Get Dart call method") }else if(call.method.equals("toSecondActivity")){ startActivity( Intent( this, SecondActivity::class.java ) ) } } } } }
该方法使用的是withNewEngine,页面跳转会出现卡顿感
SecondActivity
package com.example.flutter_hello import android.content.Context import android.content.Intent import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.databinding.DataBindingUtil import com.example.flutter_hello.databinding.ActivitySecondBinding import io.flutter.embedding.android.FlutterActivity class SecondActivity : AppCompatActivity() { lateinit var mContext: Context override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mContext = this val binding: ActivitySecondBinding = DataBindingUtil.setContentView(this, R.layout.activity_second) binding.jumpToDartSecond.setOnClickListener { //方式1:跳转到已经在flutter的routers声明的命名路由页面(会卡顿) startActivity(FlutterActivity.withNewEngine().initialRoute("second").build(mContext)) } } }
2、在Application里面先设置好FlutterEngine,使用的时候直接取缓存过得FlutterEngine
自定义MyApplication
package com.example.flutter_hello import android.app.Application import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.FlutterEngineCache import io.flutter.embedding.engine.dart.DartExecutor class MyApplication : Application() { lateinit var flutterEngineInit: FlutterEngine override fun onCreate() { super.onCreate() flutterEngineInit = FlutterEngine(this) // 开始执行Dart代码以预热FlutterEngine flutterEngineInit.navigationChannel.setInitialRoute("second") flutterEngineInit.getDartExecutor() .executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault()) // 缓存FlutterActivity要使用的FlutterEngine FlutterEngineCache.getInstance().put("second", flutterEngineInit) } override fun onTerminate() { flutterEngineInit.destroy() super.onTerminate() } }
在Manifest文件里面注册该自定义的Application
package com.example.flutter_hello import android.content.Context import android.content.Intent import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.databinding.DataBindingUtil import com.example.flutter_hello.databinding.ActivitySecondBinding import io.flutter.embedding.android.FlutterActivity class SecondActivity : AppCompatActivity() { lateinit var mContext: Context override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mContext = this val binding: ActivitySecondBinding = DataBindingUtil.setContentView(this, R.layout.activity_second) binding.jumpToDartSecond.setOnClickListener { //方式2:跳转到initialRoute指定的页面(不卡顿) startActivity( FlutterActivity .withCachedEngine("second") .build(mContext) ) } } }
PS:如果要使用window属性,必须导入 'dart:ui’的包
import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class DartPages extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( routes: <String, WidgetBuilder>{ 'home': (BuildContext context) => DartHomePage(), 'second': (BuildContext context) => DartSecondPage(), }, home: _widgetForRoute(window.defaultRouteName), ); } } class DartHomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('HomePage'), centerTitle: true, ), body: const Center( child: Text('欢迎来到Dart主页'), ), floatingActionButton: FloatingActionButton( onPressed: () { MethodChannel methodChannel=const MethodChannel("nativeCall"); methodChannel.invokeMethod("toSecondActivity"); }, child: const Text('跳转'), ), ); } } class DartSecondPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('HomePage'), centerTitle: true, ), body: const Center( child: Text('欢迎来到Dart第二页'), ), ); } } Widget? _widgetForRoute(String route){ switch(route){ case "home": return DartHomePage(); case "second": return DartSecondPage(); default: return DartHomePage(); } }
package com.example.flutter_hello import android.content.Context import android.content.Intent import android.os.Bundle import android.util.Log import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine var INIT_PARAMS = "initParams" const val TAG:String="MainActivity" class MainActivity : FlutterActivity() { private var initParams: String? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Log.e(TAG,"onCreate") initParams = getIntent().getStringExtra(INIT_PARAMS) } override fun getInitialRoute(): String? { return if (initParams == null) super.getInitialRoute() else initParams } companion object { fun start(context: Context, initParams: String) { val intent = Intent(context, MainActivity::class.java) intent.putExtra(INIT_PARAMS, initParams) context.startActivity(intent) } } }
1、在继承FlutterActivity的类重写getInitialRoute方法
package com.example.flutter_hello import android.content.Context import android.content.Intent import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.databinding.DataBindingUtil import com.example.flutter_hello.databinding.ActivitySecondBinding import io.flutter.embedding.android.FlutterActivity class SecondActivity : AppCompatActivity() { lateinit var mContext: Context override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mContext = this val binding: ActivitySecondBinding = DataBindingUtil.setContentView(this, R.layout.activity_second) binding.jumpToDartSecond.setOnClickListener { MainActivity.start(mContext,"second") } } }
import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class DartPages extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( routes: <String, WidgetBuilder>{ 'home': (BuildContext context) => DartHomePage(), 'second': (BuildContext context) => DartSecondPage(), }, home: _widgetForRoute(window.defaultRouteName), ); } } class DartHomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('HomePage'), centerTitle: true, ), body: const Center( child: Text('欢迎来到Dart主页'), ), floatingActionButton: FloatingActionButton( onPressed: () { MethodChannel methodChannel=const MethodChannel("nativeCall"); methodChannel.invokeMethod("toSecondActivity"); }, child: const Text('跳转'), ), ); } } class DartSecondPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('HomePage'), centerTitle: true, ), body: const Center( child: Text('欢迎来到Dart第二页'), ), ); } } Widget? _widgetForRoute(String route){ switch(route){ case "home": return DartHomePage(); case "second": return DartSecondPage(); default: return DartHomePage(); } }
package com.example.flutter_hello import android.content.Context import android.content.Intent import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.databinding.DataBindingUtil import com.example.flutter_hello.databinding.ActivitySecondBinding import io.flutter.embedding.android.FlutterActivity class SecondActivity : AppCompatActivity() { lateinit var mContext: Context override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mContext = this val binding: ActivitySecondBinding = DataBindingUtil.setContentView(this, R.layout.activity_second) binding.jumpToDartSecond.setOnClickListener { startActivity(Intent(mContext,ThreeActivity::class.java)) } } }
package com.example.flutter_hello import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.fragment.app.FragmentTransaction import io.flutter.embedding.android.FlutterFragment //原生页面采用FlutterFragment引入Flutter的widgets class ThreeActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_three) var ft:FragmentTransaction=supportFragmentManager.beginTransaction() val dartView:FlutterFragment=FlutterFragment.withNewEngine().initialRoute("second").build() ft.replace(R.id.dartPageContain,dartView).commit() } }
总结:虽然混合开发中页面跳转能够实现,但是总体的页面切换的效果还是很差,估计用户体验不是很高,混合开发中跨平台页面渲染还有很大提升空间。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。