Flutter 与Android原生界面通信

转载Flutter集成到Android项目三部曲 - ezbuy_Metal团队 - 掘金专栏

3. 嵌入View并传递参数

上面虽然能够跳转指定页面了,但是很显然,有一个很大的问题:不能传递参数。

这是Flutter的静态路由的一个很大的弊端,虽然通过动态路由可以传递参数和接收返回值,但是动态路由没法给原生调用。

 Navigator.of(context)
                .push(new MaterialPageRoute(builder: (context) {
              return new NextPage(params);
            })).then((String value) {
              setState(() {
                params = value;
              });
            });
复制代码

有一个Flutter的路由库:Fluro,可以实现静态路由传参,例如这样:

传参

var bodyJson = '{"user":1281,"pass":3041}';
router.navigateTo(context, '/home/$bodyJson');
复制代码

接收

Router router = new Router();

void main() {
  router.define('/home/:data', handler: new Handler(
      handlerFunc: (BuildContext context, Map params) {
        return new FluroHomePage(params['data'][0]);
      }));
  runApp(MyApp());
}
复制代码

但是,这种方式在Flutter内部还行,却无法给原生调用,在原生里面通过Flutter.createView的时候,是没法使用Fluro的,只能是默认的路由。

调研了很多方案,最后,没有办法了,只好采用最笨的方法:通过MethodChannel来传递参数。

这里需要注意的是MethodChannel的调用,应该FlutterView已经创建完成,所以需要通过flutterView.post(new Runnable())来执行了,直接执行是不会传参给Flutter的。

原生传参给Flutter

原生调用

MethodChannel channel = new MethodChannel(flutterView, CHANNEL);
channel.invokeMethod("invokeFlutterMethod", "hello,flutter", new MethodChannel.Result() {
    @Override
    public void success(@Nullable Object o) {
        Log.i("flutter","1.原生调用invokeFlutterMethod-success:"+o.toString());
    }
    @Override
    public void error(String s, @Nullable String s1, @Nullable Object o) {
        Log.i("flutter","1.原生调用invokeFlutterMethod-error");
    }
    @Override
    public void notImplemented() {
        Log.i("flutter","1.原生调用invokeFlutterMethod-notImplemented");
    }
});
复制代码

Flutter执行

platform.setMethodCallHandler((handler) {
      Future future=Future((){
        switch (handler.method) {
          case "invokeFlutterMethod":
            String args = handler.arguments;
            print("2.Flutter执行invokeFlutterMethod:${args}");
            return "this is flutter result";
        }
      });
      return future;
    });
复制代码

Flutter传参给原生

Flutter调用

print("3.Flutter调用invokeNativeMethod");
int result =
    await platform.invokeMethod("invokeNativeMethod", "hello,native");
print("5.收到原生执行结果:${result}");
复制代码

原生执行

channel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
    @Override
    public void onMethodCall(MethodCall call, MethodChannel.Result result) {
        switch (call.method) {
            case "invokeNativeMethod":
                String args = (String) call.arguments;
                Log.i("flutter","4.原生执行invokeNativeMethod:"+args);
                result.success(200);
                break;
            default:
        }
    }
});
复制代码

最后贴一下这个传参页面的完整代码吧,主要就是跑了一下:

  1. 原生调用invokeFlutterMethod
  2. Flutter执行invokeFlutterMethod
  3. Flutter调用invokeNativeMethod
  4. 原生执行invokeNativeMethod

Android:

public class ChannelFlutterActivity extends AppCompatActivity {

    private static final String CHANNEL = "com.ezbuy.flutter";

    FlutterView flutterView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_channel);
        FrameLayout frFlutter = findViewById(R.id.fr_flutter);
        flutterView = getFlutterView("channelPage");
        frFlutter.addView(flutterView);
        flutterView.post(new Runnable() {
            @Override
            public void run() {
                initMethodChannel(flutterView);
            }
        });
    }

    public FlutterView initMethodChannel(FlutterView flutterView) {
        MethodChannel channel = new MethodChannel(flutterView, CHANNEL);
        //1.原生调用Flutter方法
        channel.invokeMethod("invokeFlutterMethod", "hello,flutter", new MethodChannel.Result() {
            @Override
            public void success(@Nullable Object o) {
                Log.i("flutter","1.原生调用invokeFlutterMethod-success:"+o.toString());
            }

            @Override
            public void error(String s, @Nullable String s1, @Nullable Object o) {
                Log.i("flutter","1.原生调用invokeFlutterMethod-error");
            }

            @Override
            public void notImplemented() {
                Log.i("flutter","1.原生调用invokeFlutterMethod-notImplemented");
            }
        });
        Log.i("flutter","1.原生调用invokeFlutterMethod");
        //4.Flutter调用原生方法的监听
        channel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
            @Override
            public void onMethodCall(MethodCall call, MethodChannel.Result result) {
                switch (call.method) {
                    case "invokeNativeMethod":
                        String args = (String) call.arguments;
                        Log.i("flutter","4.原生执行invokeNativeMethod:"+args);
                        result.success(200);
                        break;
                    default:
                }
            }
        });
        return flutterView;
    }

    public FlutterView getFlutterView(String initialRoute) {
        return Flutter.createView(
                this,
                getLifecycle(),
                initialRoute
        );
    }
}
复制代码

Flutter

class ChannelPage extends StatefulWidget {

  ChannelPage();

  @override
  _ChannelPageState createState() => _ChannelPageState();
}

class _ChannelPageState extends State {
  static const platform = const MethodChannel('com.ezbuy.flutter');

  String data;

  @override
  void initState() {
    super.initState();
    data ="默认data";
    initChannel();
  }

  @override
  Widget build(BuildContext context) {
    //必须用Scaffold包裹
    return Scaffold(body: new Center(child: new Text(data)));
  }

  void initChannel() {
    platform.setMethodCallHandler((handler) {
      Future future=Future((){
        switch (handler.method) {
          case "invokeFlutterMethod":
            String args = handler.arguments;
            print("2.Flutter执行invokeFlutterMethod:${args}");
            setState(() {
              data = "2.Flutter执行invokeFlutterMethod:${args}";
            });
            invokeNativeMethod();
            return "this is flutter result";
        }
      });
      return future;
    });
  }

  void invokeNativeMethod() async {
    print("3.Flutter调用invokeNativeMethod");
    int result =
        await platform.invokeMethod("invokeNativeMethod", "hello,native");
    print("5.收到原生执行结果:${result}");
  }

}

作者:ezbuy_Metal团队
链接:https://juejin.im/post/5c6f77d7f265da2dbb122fe1
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

图片发自App

你可能感兴趣的:(Flutter 与Android原生界面通信)