Flutter与Android的混合开发(3)Flutter如何跳转到Activity,如何传值

2,288 阅读4分钟
  1. 如何在现有Android项目里嵌入Flutter Module
  2. Activity如何跳转到Flutter页面,如何传值
  3. Flutter如何跳转到Activity,如何传值
  4. Android模块与Flutter模块的交互

全部源码已上传github

Flutter跳转Activity有2种方式:

  1. 通过Channel通知Android层跳转
  2. 直接让Flutter页面嵌入Android的View

Flutter如何跳转到Activity,如何传值

我们修改一下之前的MainActivity,增加我们这次的示例代码

Android代码

MainActivity.kt

package com.liuhc.myapplication

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import io.flutter.view.FlutterMain
import kotlinx.android.synthetic.main.activity_main.*
import org.jetbrains.anko.startActivity

/**
 * 描述:首页
 * 作者:liuhc
 * 创建日期:2019-09-05 on 11:21 AM
 */
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        //强烈建议放到Application里初始化,初始化一次即可,放这里只是举个例子
        FlutterMain.startInitialization(this)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //addContentView方式添加FlutterView
        page1.setOnClickListener {
            startActivity<Page1Activity>()
        }

        //普通Fragment方式添加FlutterView
        page2.setOnClickListener {
            startActivity<Page2Activity>()
        }

        //使用FlutterFragmentActivity
        page3.setOnClickListener {
            startActivity<PageFlutterFragmentActivity>()
        }

        //使用FlutterActivity
        page4.setOnClickListener {
            startActivity<PageFlutterActivity>()
        }

        //addContentView方式添加FlutterView并传递参数
        page1Param.setOnClickListener {
            startActivity<Page1ParamActivity>()
        }

        //解决debug模式下黑屏的另一种方式
        noBlack.setOnClickListener {
            startActivity<DebugNoBlackActivity>()
        }

        //进入Flutter页面演示通过Channel跳转到Activity
        jumpByChannel.setOnClickListener {
            startActivity<JumpActivityFlutterWidget>()
        }

        //进入嵌入了Android平台的View的Flutter页面
        insertAndroidView.setOnClickListener {
            startActivity<InsertAndroidViewFlutterWidget>()
        }
    }

}

JumpActivityFlutterWidget.kt

package com.liuhc.myapplication

import android.os.Bundle
import io.flutter.app.FlutterActivity
import io.flutter.plugin.common.MethodChannel
import io.flutter.view.FlutterMain
import org.jetbrains.anko.startActivity

/**
 * 描述:这个页面包含FlutterView,然后点击FlutterView中的按钮跳转到另一个Activity,
 * 这种方式其实只是调用Channel通信而已
 *
 * 作者:liuhc
 * 创建日期:2019-09-04 on 23:30
 */
class JumpActivityFlutterWidget : FlutterActivity() {

    private lateinit var methodChannel: MethodChannel

    override fun onCreate(savedInstanceState: Bundle?) {
        //强烈建议放到Application里初始化,初始化一次即可,放这里只是举个例子
        FlutterMain.startInitialization(this)
        //intent的参数设置必须在super.onCreate之前,因为super.onCreate里会取这些参数
        intent.action = "android.intent.action.RUN"
        intent.putExtra("route", "page4")
        super.onCreate(savedInstanceState)
        initMethodChannel()
        //调用super.onCreate(savedInstanceState)之后flutterView才有值,
        //所以如果需要注册插件,则应该放到super.onCreate(savedInstanceState)代码之后才可以
        flutterView.enableTransparentBackground()
    }

    //Flutter跳转Activity的方式1,使用Channel
    private fun initMethodChannel() {
        methodChannel = MethodChannel(
            this.registrarFor("pluginKeyMainActivity").messenger(),
            "MainActivityMethodChannel"
        )
        methodChannel.setMethodCallHandler { methodCall, result ->
            if (methodCall.method == "jumpTestActivity") {
                startActivity<TestActivity>()
            }
        }
    }
}

TestActivity.kt

package com.liuhc.myapplication

import android.annotation.SuppressLint
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.widget.LinearLayout
import android.widget.TextView

/**
 * 描述:
 * 作者:liuhc
 * 创建日期:2019-09-05 on 14:31
 */
class TestActivity : AppCompatActivity() {

    @SuppressLint("SetTextI18n")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val linearLayout = LinearLayout(this)
        val layoutParam = LinearLayout.LayoutParams(
            LinearLayout.LayoutParams.MATCH_PARENT,
            LinearLayout.LayoutParams.MATCH_PARENT
        )
        val textView = TextView(this)
        textView.text = "TestActivity:我被跳转过来了"
        val viewParam = LinearLayout.LayoutParams(
            LinearLayout.LayoutParams.WRAP_CONTENT,
            LinearLayout.LayoutParams.WRAP_CONTENT
        )
        linearLayout.addView(textView, viewParam)
        setContentView(linearLayout, layoutParam)
    }

}

InsertAndroidViewFlutterWidget.kt

package com.liuhc.myapplication

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import io.flutter.view.FlutterMain
import kotlinx.android.synthetic.main.activity_main.*
import org.jetbrains.anko.startActivity

/**
 * 描述:首页
 * 作者:liuhc
 * 创建日期:2019-09-05 on 11:21 AM
 */
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        //强烈建议放到Application里初始化,初始化一次即可,放这里只是举个例子
        FlutterMain.startInitialization(this)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //addContentView方式添加FlutterView
        page1.setOnClickListener {
            startActivity<Page1Activity>()
        }

        //普通Fragment方式添加FlutterView
        page2.setOnClickListener {
            startActivity<Page2Activity>()
        }

        //使用FlutterFragmentActivity
        page3.setOnClickListener {
            startActivity<PageFlutterFragmentActivity>()
        }

        //使用FlutterActivity
        page4.setOnClickListener {
            startActivity<PageFlutterActivity>()
        }

        //addContentView方式添加FlutterView并传递参数
        page1Param.setOnClickListener {
            startActivity<Page1ParamActivity>()
        }

        //解决debug模式下黑屏的另一种方式
        noBlack.setOnClickListener {
            startActivity<DebugNoBlackActivity>()
        }

        //进入Flutter页面演示通过Channel跳转到Activity
        jumpByChannel.setOnClickListener {
            startActivity<JumpActivityFlutterWidget>()
        }

        //进入嵌入了Android平台的View的Flutter页面
        insertAndroidView.setOnClickListener {
            startActivity<InsertAndroidViewFlutterWidget>()
        }
    }

}

Dart代码

main.dart

import 'dart:convert';
import 'dart:ui';

import 'package:flutter/material.dart';

import 'insert_android_view_page.dart';
import 'invoke_method_page.dart';
import 'jump_activity_page.dart';
import 'my_home_page.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      //方式1
      home: _getWidgetByRoute(window.defaultRouteName),
      //方式2 如果route相同,优先匹配routes而不是home
      routes: <String, WidgetBuilder>{
        "page1": (context) => MyHomePage(
              title: "匹配到了page1",
              message: "通过routes变量",
            ),
        "page2": (context) => MyHomePage(
              title: "匹配到了page2",
              message: "通过routes变量",
            ),
        "page3": (context) => MyHomePage(
              title: "匹配到了page3",
              message: "通过routes变量",
            ),
        "page4": (context) => JumpActivityPage(),
        "page5": (context) => InsertAndroidViewPage(),
      },
      //当通过routes和home的返回值都为null的话,才会从onUnknownRoute寻找
      onUnknownRoute: (RouteSettings settings) {
        return new PageRouteBuilder(pageBuilder: (BuildContext context, _, __) {
          //这里为返回的Widget
          return MyHomePage(
            title: "没有匹配到",
            message: "通过onUnknownRoute变量",
          );
        });
      },
    );
  }
}

//如果要接收平台层发送的参数,除了使用Channel以外(这种方式不是正常的方式,强烈不推荐),就只能通过window.defaultRouteName了,
//因为routes的route只能提前定义好,无法动态判断
Widget _getWidgetByRoute(String jsonStr) {
  print("json=$jsonStr");
  String _route;
  Map<String, dynamic> jsonMap;
  try {
    jsonMap = json.decode(jsonStr);
    _route = jsonMap["path"];
  } catch (e) {
    print(e);
    _route = jsonStr;
  }
  switch (_route) {
    //接收到了匹配的规则,跳转到flutter指定页面
    case 'page1':
      return MyHomePage(
        title: "匹配到了page1",
        message: "通过home变量",
      );
    case 'page1Param':
      return MyHomePage(
        title: "匹配到了page1Param",
        message: jsonMap["param"],
      );
    case "InvokeMethodPage":
      return InvokeMethodPage(
        title: jsonMap["title"],
        channelName: jsonMap["channelName"],
        androidMethod: jsonMap["androidMethod"],
      );
    default:
      return MyHomePage(
        title: "没有匹配到",
        message: "通过home变量",
      );
  }
}

jump_activity_page.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class JumpActivityPage extends StatefulWidget {
  @override
  _JumpActivityPageState createState() => _JumpActivityPageState();
}

class _JumpActivityPageState extends State<JumpActivityPage> {

  MethodChannel _methodChannel;

  @override
  void initState() {
    _methodChannel = MethodChannel("MainActivityMethodChannel");
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("我是Flutter页面"),
      ),
      body: RaisedButton(
        child: Text("点我通过发送Channel消息通知Android层跳转页面"),
        onPressed: (){
          _methodChannel.invokeMethod("jumpTestActivity");
        },
      ),
    );
  }
}

insert_android_view_page.dart

import 'dart:io' show Platform;

import 'package:flutter/material.dart';

/// 描述:嵌入AndroidView
/// 作者:liuhc
/// 创建日期:2019-09-05 on 3:20 PM
class InsertAndroidViewPage extends StatefulWidget {
  @override
  _InsertAndroidViewPageState createState() => _InsertAndroidViewPageState();
}

class _InsertAndroidViewPageState extends State<InsertAndroidViewPage> {
  GlobalKey key = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("我来演示如何嵌入AndroidView"),
        ),
        body: Platform.isAndroid ? AndroidView(key: key, viewType: 'InsertAndroidView') : Text("ios和Android实现原理一样"));
  }
}

欢迎加入Flutter开发群457664582,点击加入,大家一起学习讨论