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("activity")
            if (activityClassName.isNullOrEmpty()) {
                Log.e(TAG, "RouterPlugin requires a activity class name.")
                return
            }
            val arguments = if (!call.hasArgument("arguments")) null else call.argument?>("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 = 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? = 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 arguments]) =>
          _channel.invokeMethod("startActivity", {
            "activity": activityClassName,
            "arguments": arguments
          });
    
      static Future startActivityForResult(String activityClassName, int requestCode,
          [Map 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 {
    
      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: [
                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 - 处理页面路由跳转(Dart -> Native[Java/Kotlin])_第1张图片
示例图片

结语

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

你可能感兴趣的:(Flutter - 处理页面路由跳转(Dart -> Native[Java/Kotlin]))