Flutter入门-与原生数据传递

为了实现Flutter与原生之间的数据传递,Flutter部分通过平台通道(platform channel)将消息发送到其应用程序的所在的宿主(iOS或Android)。宿主监听的平台通道,并接收该消息。

Flutter定义了三种不同类型的Channel:
BasicMessageChannel:用于传递字符串和半结构化信息,持续通信,收到消息后可以回复
MethodChannel:用于传递方法调用(method invocation),一次性通信
EventChannel:用于数据流(event streams)通信,持续通信,收到消息后无法回复。

这三种类型的Channel都是全双工通信,即Dart端可以主动发送消息给platform端;同样,platform端也可以主动发送消息给Dart端

一、BasicMessageChannel用法

1、Dart端到Native端

Dart端代码:

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

class MyBasicMessageChannel extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      routes: <String, WidgetBuilder>{
        'home': (BuildContext context) => BasicMessageChannelHome(),
        'second': (BuildContext context) => BasicMessageChannelSecond()
      },
      home: BasicMessageChannelHome (),
    );
  }
}


class BasicMessageChannelHome extends StatefulWidget {
  
  State<BasicMessageChannelHome> createState() =>
      BasicMessageChannelHomeState();
}

class BasicMessageChannelHomeState extends State<BasicMessageChannelHome> {
  var _basicMessage = BasicMessageChannel("BasicChannel", StringCodec());

  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: GestureDetector(
            child: Text('发送BasicMessageChannel'),
            onTap: () {
              _basicMessage.send('JumpNativeActivity').then((value) {
                print(value);
              });
            },
          ),
        ),
      ),
    );
  }

  
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      _basicMessage.setMessageHandler((message) async {
        print(message);
        return 'ACK FROM ART';
      });
    });
  }
}

Native端代码

package com.example.flutter_hello

import android.content.Context
import android.os.Bundle
import android.util.Log
import io.flutter.embedding.android.FlutterActivity
import io.flutter.plugin.common.BasicMessageChannel
import io.flutter.plugin.common.StringCodec

const val TAG:String="MainActivity"

class MainActivity : FlutterActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        var channel = BasicMessageChannel(
            flutterEngine.dartExecutor.binaryMessenger,
            "BasicChannel",
            StringCodec.INSTANCE
        )
        channel.setMessageHandler { message, reply ->
            android.util.Log.e(TAG,message)
            reply.reply("成功跳转")
        }
    }
}

二、MethodChannel用法

Dart端代码

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

class FlutterMethodChannel extends StatelessWidget {
  MethodChannel methodChannel = MethodChannel('nativeCall');

  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: GestureDetector(
          onTap: () {
            _callNativeMethod();
          },
          child: Center(
            child: Text('调用Native方法'),
          ),
        ),
      ),
    );
  }

  void _callNativeMethod() async {
    try {
      methodChannel.invokeMethod('nativeMethod');
    } catch (e) {
      print(e);
    }
  }
}

Native端代码

package com.example.flutter_hello

import android.content.Context
import android.util.Log
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.StringCodec

var INIT_PARAMS = "initParams"
const val TAG:String="MainActivity"

class MainActivity : FlutterActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.e(TAG,"onCreate")
        MethodChannel(
            flutterEngine!!.dartExecutor.binaryMessenger,
            "nativeCall"
        ).setMethodCallHandler { call, result ->
            run {
                if (call.method.equals("nativeMethod")) {
                    result.success("success")
                    Log.e(TAG, "Get Dart call method")
                }
            }
        }

}

三、EventChannel用法

该示例是Native端实时把网络连接状态发送给Dart端

Dart端代码


import 'dart:async';

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

class FlutterEventChannel extends StatefulWidget{
  
  State<FlutterEventChannel> createState() => _FlutterEventChannelState();
}

class _FlutterEventChannelState extends State<FlutterEventChannel> {
  EventChannel eventChannel=EventChannel('getNetworkState');
  String networkState="";

  StreamSubscription? subscription;
  
  void initState() {
    super.initState();
    subscription=eventChannel.receiveBroadcastStream().listen((event) {
      _handleEvent(event);
    });
  }

  
  void dispose() {
    super.dispose();
    subscription!.cancel();
  }

  
  Widget build(BuildContext context) {
     return MaterialApp(
       home: Scaffold(
         body: Center(
           child: Text('使用EventChannel:${networkState}'),
         ),
       ),
     );
  }

  void _handleEvent(int event) {
    setState(() {
      if(event==0){
        networkState="网络断开";
      }else{
        networkState="网络连接";
      }
    });
  }
}

Native端

采用单例模式,保存EventSink用来发送数据

package com.example.flutter_hello

import io.flutter.plugin.common.EventChannel

class GloableEventChannel {
    var eventSink: EventChannel.EventSink? = null

    private object Holder{
        val instance=GloableEventChannel()
    }

    companion object{
        fun getInstance()=Holder.instance
    }

}

网络广播接收者

package com.example.flutter_hello

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.net.ConnectivityManager
import android.os.Build
import android.widget.Toast
import androidx.annotation.Nullable
import io.flutter.plugin.common.EventChannel

class NetWorkStateReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        //检测API是不是小于21,因为到了API21之后getNetworkInfo(int networkType)方法被弃用
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            //获得ConnectivityManager对象
            val connMgr =
                context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            //获取ConnectivityManager对象对应的NetworkInfo对象
            //获取WIFI连接的信息
            val wifiNetworkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
            //获取移动数据连接的信息
            val dataNetworkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE)
            if (GloableEventChannel.getInstance().eventSink==null){
                return
            }
            if (wifiNetworkInfo!!.isConnected && dataNetworkInfo!!.isConnected) {
                GloableEventChannel.getInstance().eventSink!!.success(1)
            } else if (wifiNetworkInfo!!.isConnected && !dataNetworkInfo!!.isConnected) {
                GloableEventChannel.getInstance().eventSink!!.success(0)
            } else if (!wifiNetworkInfo!!.isConnected && dataNetworkInfo!!.isConnected) {
                GloableEventChannel.getInstance().eventSink!!.success(1)
            } else {
                GloableEventChannel.getInstance().eventSink!!.success(0)
            }
        } else {
            //获得ConnectivityManager对象
            val connMgr =
                context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            var connectedState = false
            //获取所有网络连接的信息
            val networks = connMgr.allNetworks
            //通过循环将网络信息逐个取出来
            for (i in networks.indices) {
                //获取ConnectivityManager对象对应的NetworkInfo对象
                val networkInfo = connMgr.getNetworkInfo(networks[i])
                if (networkInfo!!.isAvailable && networkInfo!!.isConnected) {
                    connectedState = true
                    break
                }
            }
            if (GloableEventChannel.getInstance().eventSink==null){
                return
            }
            GloableEventChannel.getInstance().eventSink!!.success(if (connectedState) 1 else 0)
        }
    }
}

注册网络状态广播

package com.example.flutter_hello

import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
import android.os.Bundle
import android.util.Log
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.StringCodec

const val TAG:String="MainActivity"

class MainActivity : FlutterActivity() {
    private lateinit var eventChannel:EventChannel
    private lateinit var networkIntentFilter:IntentFilter
    private val netWorkStateReceiver=NetWorkStateReceiver()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.e(TAG,"onCreate")
        networkIntentFilter=IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
        registerReceiver(netWorkStateReceiver,networkIntentFilter)
        eventChannel= EventChannel(flutterEngine!!.dartExecutor.binaryMessenger,"getNetworkState")
        eventChannel.setStreamHandler(object : EventChannel.StreamHandler {
            override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
                if (events != null) {
                    GloableEventChannel.getInstance().eventSink=events
                }
            }

            override fun onCancel(arguments: Any?) {

            }

        })
    }
    override fun onDestroy() {
        super.onDestroy()
        Log.e(TAG,"onDestroy")
        unregisterReceiver(netWorkStateReceiver)
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flutter中的TextField是一个常用的输入控件,它允许用户在应用程序中输入文本。 TextField通常用于表单中,可以接收用户输入的文本,比如用户名、密码、电子邮件地址等。 以下是一个基本的TextField示例: ```dart TextField( decoration: InputDecoration( hintText: '请输入文本', ), ); ``` 在上面的示例中,我们使用了decoration属性来设置TextField的外观,其中hintText属性用于设置提示文本。 TextField还有许多其他的属性可以设置,比如maxLength(允许输入的最大长度)、keyboardType(键盘类型)、obscureText(是否隐藏输入内容)等等。 下面是一个更完整的TextField示例: ```dart class MyTextField extends StatefulWidget { @override _MyTextFieldState createState() => _MyTextFieldState(); } class _MyTextFieldState extends State<MyTextField> { final TextEditingController _controller = TextEditingController(); @override Widget build(BuildContext context) { return TextField( controller: _controller, maxLength: 10, keyboardType: TextInputType.text, obscureText: true, decoration: InputDecoration( hintText: '请输入文本', labelText: '文本框', prefixIcon: Icon(Icons.text_fields), suffixIcon: IconButton( icon: Icon(Icons.clear), onPressed: () { setState(() { _controller.clear(); }); }, ), border: OutlineInputBorder(), ), onChanged: (value) { print('输入的文本为:$value'); }, ); } } ``` 在上面的示例中,我们使用了TextEditingController来控制TextField的文本内容,maxLength属性限制了用户输入的最大长度为10,keyboardType属性指定了键盘类型为文本类型,obscureText属性设置为true表示隐藏输入内容。 此外,我们还设置了decoration属性来自定义TextField的外观,包括了输入提示文本、标签文本、前缀图标、后缀图标和边框样式等。 最后,我们通过onChanged回调函数来监听用户输入的文本,并打印出来。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值