美文网首页Flutter圈子FlutterAndroid开发经验谈
Flutter - 处理页面路由跳转(Dart -> Na

Flutter - 处理页面路由跳转(Dart -> Na

作者: Cosecant | 来源:发表于2018-04-01 15:45 被阅读293次

    背景

    最近一直在考虑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,现目前也还没找到相应的策略,纠结!

    相关文章

      网友评论

      • 4a209d63df90:这个还需要什么配置吗?写完之后调用报异常
        ` MissingPluginException(No implementation found for method startActivity on channel router_plugin)`
        Cosecant:@胭脂染雪 dart里调用的java端对应的java方法没实现
      • 燃烧的鱼丸:突然想问个很傻的问题,比如用安卓原生开发好的一些组件,通过flutter引入后打包生成IOS端的APP,可以在IOS中使用不?
        Cosecant:@燃烧的鱼丸 当然不行😂

      本文标题:Flutter - 处理页面路由跳转(Dart -> Na

      本文链接:https://www.haomeiwen.com/subject/rixacftx.html