Flutter - 处理页面路由跳转(Dart -> Native[Java/Kotlin])

背景

最近一直在考虑Flutter如何处理由原生页面处理后返回的结果,比如:startActivityForResult,需要处理的结果必须在onActivityResult方法处理,但是Dart代码中又要接收到该值。经过多番查看资料,终于找到了相应的办法。

相关代码

  1. 创建一个插件库,编写一个叫RouterPlugin的项目。注意代码中的几个重要的接口:PluginRegistry.ActivityResultListener,该类需要实现onActivityResult方法,用于处理相应的返回处理。

  2. 插件类中保存MethodCallResult的实例,用于处理相关的结果。

    class RouterPlugin private constructor(private val registrar: Registrar) : MethodCallHandler, PluginRegistry.ActivityResultListener {
    
        companion object {
    
            @JvmStatic
            private val TAG = RouterPlugin::class.java.simpleName
    
            @JvmStatic
            fun registerWith(registrar: Registrar): Unit {
                val instance = RouterPlugin(registrar)
                val channel = MethodChannel(registrar.messenger(), "router_plugin")
                registrar.addActivityResultListener(instance)
                channel.setMethodCallHandler(instance)
            }
    
        }
    
        private var methodCall: MethodCall? = null
        private var pendingResult: Result? = null
        private var requestCode: Int = 0
    
        override fun onMethodCall(call: MethodCall, result: Result): Unit {
            if (this.pendingResult != null) {
                Log.e(TAG, "RouterPlugin is already active.")
                return
            }
            val activity = registrar.activity()
            if (activity == null) {
                Log.e(TAG, "RouterPlugin requires a foreground activity.")
                return
            }
            this.methodCall = call
            this.pendingResult = result
            val activityClassName = if (!call.hasArgument("activity")) null else call.argument<String>("activity")
            if (activityClassName.isNullOrEmpty()) {
                Log.e(TAG, "RouterPlugin requires a activity class name.")
                return
            }
            val arguments = if (!call.hasArgument("arguments")) null else call.argument<Map<String, Any>?>("arguments")
            when (call.method) {
                "startActivity" -> {
                    activity.startActivity(getActivityIntent(activity, activityClassName!!, arguments))
                    result.success(null)
                    this.methodCall = null
                    this.pendingResult = null
                }
                "startActivityForResult" -> {
                    val requestCode = if (!call.hasArgument("requestCode")) -1 else call.argument("requestCode")
                    if (requestCode == -1) {
                        Log.e(TAG, "RequestCode cannot be null")
                        return
                    }
                    this.requestCode = requestCode
                    activity.startActivityForResult(getActivityIntent(activity, activityClassName!!, arguments), requestCode)
                }
            }
        }
    
        override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
            if (requestCode == this.requestCode) {
                if (resultCode == Activity.RESULT_OK) {
                    val ret: MutableMap<String, Any> = mutableMapOf()
                    data?.extras?.keySet()?.forEach {
                        ret[it] = data.extras[it]
                    }
                    println("---------->信息:$ret")
                    this.pendingResult?.success(if (ret.isEmpty()) null else ret)
                }
                this.methodCall = null
                this.pendingResult = null
                this.requestCode = 0
                return true
            }
            return false
        }
    
        private fun getActivityIntent(context: Context, activityClassName: String, params: Map<String, Any>? = null): Intent {
            val intent = Intent(context, Class.forName(activityClassName))
            with(intent) {
                params?.forEach { key, value ->
                    when (value) {
                        is Char -> putExtra(key, value)
                        is Short -> putExtra(key, value)
                        is Int -> putExtra(key, value)
                        is Long -> putExtra(key, value)
                        is Float -> putExtra(key, value)
                        is Double -> putExtra(key, value)
                        is Boolean -> putExtra(key, value)
                        is String -> putExtra(key, value)
                        is CharArray -> putExtra(key, value)
                        is ShortArray -> putExtra(key, value)
                        is IntArray -> putExtra(key, value)
                        is LongArray -> putExtra(key, value)
                        is FloatArray -> putExtra(key, value)
                        is DoubleArray -> putExtra(key, value)
                        is BooleanArray -> putExtra(key, value)
                        is Parcelable -> putExtra(key, value)
                        else -> putExtra(key, Gson().toJson(value)) //复杂类型会被转换成JSON-String
                    }
                }
            }
            return intent
        }
    
    }
    
  3. 对应的dart代码[RouterPlugin.dart]

    class RouterPlugin {
    
      static const MethodChannel _channel =
      const MethodChannel('router_plugin');
    
      static void startActivity(String activityClassName,
          [Map<String, dynamic> arguments]) =>
          _channel.invokeMethod("startActivity", {
            "activity": activityClassName,
            "arguments": arguments
          });
    
      static Future<dynamic> startActivityForResult(String activityClassName, int requestCode,
          [Map<String, dynamic> arguments]) =>
          _channel.invokeMethod("startActivityForResult", {
            "activity": activityClassName,
            "requestCode": requestCode,
            "arguments": arguments
          });
    
    }
    
  4. 主项目添加一个Activity,叫做HeloActivity,并编写以下代码

    class HeloActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_helo)
        }
    
        override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
            if (keyCode == KeyEvent.KEYCODE_BACK && event?.action == KeyEvent.ACTION_DOWN) {
                val data = Intent()
                data.putExtra("name", "谢尔顿")
                data.putExtra("age", 8)
                setResult(Activity.RESULT_OK, data)
                this.finish()
                return true
            }
            return super.onKeyDown(keyCode, event)
        }
    
    }
    
  5. 测试代码[main.dart]

    void main() => runApp(new MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          title: 'Flutter Demo',
          theme: new ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: new MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => new _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
    
      String backMessage; //返回信息
    
      _incrementCounter() async {
        var value = await RouterPlugin.startActivityForResult(
            "com.mrper.flutterapp.HeloActivity", 200); //启动一个原生页面
        setState(() {
          backMessage = value.toString();
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          appBar: new AppBar(
            title: new Text(widget.title),
          ),
          body: new Center(
            child: new Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                new Text(
                  '接收startActivityForResult返回的信息:',
                ),
                new Text(
                  '$backMessage',
                  style: Theme.of(context).textTheme.display1,
                ),
              ],
            ),
          ),
          floatingActionButton: new FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: new Icon(Icons.add),
          ),
        );
      }
    }
    
示例图片

结语

现目前能从Flutter跳转到原生UI了,但是如何从原生UI跳转到Flutter的UI,现目前也还没找到相应的策略,纠结!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容

  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,358评论 0 17
  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些阅读 2,028评论 0 2
  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi阅读 7,294评论 0 10
  • 如果他不喜欢我了呢?可能已经不喜欢了,可能不想喜欢了,可能从来就没喜欢过。 苍白,无力
    北京东路2006阅读 266评论 0 0
  • 昨晚跟朋友聊天,大家都在互问“买了什么,买了多少钱?”然后发现我们都没怎么买东西,好像对“双十一”一点都不敏感。 ...
    非法入境阅读 348评论 2 0