Flutter

8.1-Flutter混合开发

2019-05-28  本文已影响0人  YangDxg

混合开发Flutter集成步骤

创建Flutter module

项目目录xxx/flutter/Navive项目:

cd xxx/flutter/
flutter create -t module flutter_module

上面的代码会切换到Android/iOS项目的上一级目录,并创建flutter模块

flutter中文件用途

image

Flutter_module是上面创建的flutter module,Android Hybrid是Android工程

Flutter Android混合开发

添加flutter依赖

在Android工程中的settings.gradle文件中进行如下配置

include ':app'
setBinding(new Binding([gradle:this]))
evaluate(new File(
        settingsDir.parentFile,
        'flutter_module/.android/include_flutter.groovy'
))

同步后会在工程目录中显示我们的flutter module

image

在app的build.gradle中添加对flutter的依赖

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
        ...
    implementation project(':flutter')
}

使用flutter要求minSDK最小应该>=16

另外使用flutter也需要设置支持Java8特性

android {
  ...
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

在Java中调用Flutter module

Java中调用Flutter模块有俩种方式

使用Flutter.createView API的方式
View flutterView = Flutter.createView(
    MainActivity.this,
    getLifecycle(),
    "route1"
);
使用FlutterFragment的方式
FragmentTransaction tx = getSupportFragmentManager().beginTransaction();
tx.replace(R.id.someContainer,Flutter.createFragment('route1'));
tx.commit();

字符串"route1"用来告诉Dart代码在Flutter视图中显示哪个小部件,Flutter模块项目的lib/main.dart文件需要通过window.defaultRouteName来获取Native指定要显示的路由名,以确定要创建哪个窗口小部件并传递给runAPP:

调用Flutter module时传递数据

无论通过Flutter.createView的方式,还是通过Flutter.createFragment的方式,都允许我们加载Flutter module时传递一个String类型的initialRoute参数,也可以穿Json字符串.

Native代码

        mBtnCreate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                //为dart模块初始化所设置的参数
                ft.replace(R.id.container, Flutter.createFragment("{name:'yangdxg',dataList:['aa','bb','cc']}"));
                ft.commit();
            }
        });
    <Button
        android:id="@+id/btn_create"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Test" />

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </FrameLayout>

Dart代码

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

//使用window.defaultRouteName获取Native传递过来的参数
void main() => runApp(MyApp(initParams: window.defaultRouteName,));

class MyApp extends StatelessWidget {

  final String initParams;

  const MyApp({Key key, this.initParams}) :super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter 混合开发',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter 混合开发', initParams: initParams),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title, this.initParams}) : super(key: key);

  final String title;
  final String initParams;

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

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'initParams:${widget.initParams}',
            ),
            Text(
              '$_counter',
              style: Theme
                  .of(context)
                  .textTheme
                  .display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

Android调用Flutter

热重启/重新加载

混合开发后热重启/重新加载会失效,我们可以通过把flutter_moudle和Android工程进行关联恢复热重启/重新加载

调试Dart代码

发布应用

打包
生成Android签名证书

为Android项目生成签名证书(就是原生操作)

配置gradle
签名打包APK

terminal进入项目下的Android目录,运行如下代码

./gradlew assembleRelease

打包完成apk在app/build/outputs/apk

Flutter iOS混合开发

稍后补充

Flutter与Native通信

Flutter与Native的通信是通过Channel来完成的

消息使用Channel(平台通道)再客户端(UI)和主机(平台之间传递)

Flutter中的消息传递完全是异步的

Channel所支持的数据类型

Dart Android iOS
null null nil (NSNull when nested)
bool java.lang.Boolean NSNumber numberWithBool:
int java.lang.Integer NSNumber numberWithInt:
int, if 32 bits not enough java.lang.Long NSNumber numberWithLong:
double java.lang.Double NSNumber numberWithDouble:
String java.lang.String NSString
Uint8List byte[] FlutterStandardTypedData typedDataWithBytes:
Int32List int[] FlutterStandardTypedData typedDataWithInt32:
Int64List long[] FlutterStandardTypedData typedDataWithInt64:
Float64List double[] FlutterStandardTypedData typedDataWithFloat64:
List java.util.ArrayList NSArray
Map java.util.HashMap NSDictionary

Flutter定义了三种不同类型的Channel:

BasicMessageChannel用法

Dart端
const BasicMessageChannel(this.name,this.codec);

sendMessageHandler方法

void    sendMessageHandle(Future<T> handler(T message))

在创建好BasicMessageChannel后,如果要让其接收Native发来的消息,则需要调用它的setMessageHandler方法为其设置一个消息处理器

Future<T> send(T message)

MessageChannel方法

Dart端
const MethodChannel(this.name[this.codec=const StandardMethodCodec])

invokeMethod方法

Future<T> invokeMethod<T>(String method,[dynamic arguments])

EvnetChannel

Dart端
const EventChannel(this.name,[this.codec = const StandardMethodCodec()])

receiveBroadcastStream

Stream<dynamic> receivedBroadcastStream([dynamic arguments])

Flutter与Android通信

BasicMessageChannel用法

Native端
BasicMessageChannel(BinaryMessenger messenger, String name, MessageCodec<T> codec) {

setMessageHandle接收消息

void setMessageHandler(BasicMessageChannel.MessageHandler<T> handler)

创建好BasicMessageChannel后,如果要让其接收Dart发来的消息,则需要调用它的setMessageHandler方法为其设置一个消息处理器

public interface MessageHandler<H>{
    void onMessage(T var1,BasicMessageChannel.Repl<T> var2);
}

send方法,向Dart端发送消息

void send(T message);
void send(T message,BasicMessageChannel.Reply<T> callback)

MethodChannel用法

Native端
//会构造一个StandardMethodCodec.INSTANCE类型的MethodCodec
MethodChannel(BinaryMessage messager,String name)
//或
MethodChannel(BinaryMessage message,String name,MethodCodec codec)
setMethodCallhandler(@Nullable MethodChannel.MethodCallHandler handler)
public interface MethodCallHandler{
    void onMethodCall(MethodCall var1,MethodChannel.Result var2);
}

EventChannel用法

Native端
EventChannel(BinaryMessenger messenger, String name) 
EventChannel(BinaryMessenger messenger, String name, MethodCodec codec)

接收消息

setStreamHandler(EventChannel.StreamHandler handler)
public interface StreamHandler{
    void onListen(Object args,EventChannel.EventSink eventSink);
    void onCancle(Object o);
}

Flutter与Android通信实战

Flutter与iOS通信

上一篇 下一篇

猜你喜欢

热点阅读