Flutter混编工程之通讯之路

import 'package:flutter/services.dart';
/// This class includes implementation of two platform methods [increment],
/// and [decrement] which are used to increment and decrement value
/// of count respectively.
class Counter {
  /// Creates a [MethodChannel] with the specified name to invoke platform method.
  /// In order to communicate across platforms, the name of MethodChannel
  /// should be same on native and dart side.
  static MethodChannel methodChannel = const MethodChannel('methodChannelDemo');
/// This method is responsible to increment and return the value of count.
  static Future<int> increment({required int counterValue}) async {
    final result = await methodChannel.invokeMethod<int>('increment', {'count': counterValue});
    return result!;
  }
/// This method is responsible to decrement and return the value of count.
  static Future<int> decrement({required int counterValue}) async {
    final result = await methodChannel.invokeMethod<int>('decrement', {'count': counterValue});
    return result!;
  }
}
onPressed: () async {
  try {
    final value = await Counter.increment(counterValue: count);
    setState(() => count = value);
  } catch (error) {
  }
},
MethodChannel(flutterEngine.dartExecutor, "methodChannelDemo")
        .setMethodCallHandler { call, result ->
            val count: Int? = call.argument<Int>("count")
if (count == null) {
                result.error("INVALID ARGUMENT", "Value of count cannot be null", null)
            } else {
                when (call.method) {
                    "increment" -> result.success(count + 1)
                    "decrement" -> result.success(count - 1)
                    else -> result.notImplemented()
                }
            }
        }
import 'package:flutter/services.dart';
/// This class includes the implementation for [EventChannel] to listen to value
/// changes from the Accelerometer sensor from native side. It has a [readings]
/// getter to provide a stream of [AccelerometerReadings].
class Accelerometer {
  static const _eventChannel = EventChannel('eventChannelDemo');
/// Method responsible for providing a stream of [AccelerometerReadings] to listen
  /// to value changes from the Accelerometer sensor.
  static Stream<AccelerometerReadings> get readings {
    return _eventChannel.receiveBroadcastStream().map(
          (dynamic event) => AccelerometerReadings(
            event[0] as double,
            event[1] as double,
            event[2] as double,
          ),
        );
  }
}
class AccelerometerReadings {
  /// Acceleration force along the x-axis.
  final double x;
/// Acceleration force along the y-axis.
  final double y;
/// Acceleration force along the z-axis.
  final double z;
AccelerometerReadings(this.x, this.y, this.z);
}
child: StreamBuilder<AccelerometerReadings>(
  stream: Accelerometer.readings,
  builder: (context, snapshot) {
    if (snapshot.hasError) {
      return Text((snapshot.error as PlatformException).message!);
    } else if (snapshot.hasData) {
      return Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            'x axis: ' + snapshot.data!.x.toStringAsFixed(3),
            style: textStyle,
          ),
          Text(
            'y axis: ' + snapshot.data!.y.toStringAsFixed(3),
            style: textStyle,
          ),
          Text(
            'z axis: ' + snapshot.data!.z.toStringAsFixed(3),
            style: textStyle,
          )
        ],
      );
    }
class AccelerometerStreamHandler(sManager: SensorManager, s: Sensor) : EventChannel.StreamHandler, SensorEventListener {
    private val sensorManager: SensorManager = sManager
    private val accelerometerSensor: Sensor = s
    private lateinit var eventSink: EventChannel.EventSink
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
        if (events != null) {
            eventSink = events
            sensorManager.registerListener(this, accelerometerSensor, SensorManager.SENSOR_DELAY_UI)
        }
    }
override fun onCancel(arguments: Any?) {
        sensorManager.unregisterListener(this)
    }
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}
override fun onSensorChanged(sensorEvent: SensorEvent?) {
        if (sensorEvent != null) {
            val axisValues = listOf(sensorEvent.values[0], sensorEvent.values[1], sensorEvent.values[2])
            eventSink.success(axisValues)
        } else {
            eventSink.error("DATA_UNAVAILABLE", "Cannot get accelerometer data", null)
        }
    }
}
val sensorManger: SensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val accelerometerSensor: Sensor = sensorManger.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
EventChannel(flutterEngine.dartExecutor, "eventChannelDemo")
        .setStreamHandler(AccelerometerStreamHandler(sensorManger, accelerometerSensor))
/// This class manages a [BasicMessageChannel] that can return an image loaded
/// from a native asset. The [BasicMessageChannel] uses [StandardMessageCodec]
/// since it supports [Uint8List], which is used to transport the image data.
class PlatformImageFetcher {
  static const _basicMessageChannel = BasicMessageChannel<dynamic>('platformImageDemo', StandardMessageCodec());
/// Method responsible for providing the platform image.
  static Future<Uint8List> getImage() async {
    final reply = await _basicMessageChannel.send('getImage') as Uint8List?;
    if (reply == null) {
      throw PlatformException(
        code: 'Error',
        message: 'Failed to load Platform Image',
        details: null,
      );
    }
    return reply;
  }
}
child: FutureBuilder<Uint8List>(
  future: imageData,
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.none) {
      return const Placeholder();
    } else if (snapshot.hasError) {
      return Center(
        child: Text(
          (snapshot.error as PlatformException).message!,
        ),
      );
    } else if (snapshot.connectionState ==
        ConnectionState.done) {
      return Image.memory(
        snapshot.data!,
        fit: BoxFit.fill,
      );
    }
    return const CircularProgressIndicator();
  },
// Registers a MessageHandler for BasicMessageChannel to receive a message from Dart and send
// image data in reply.
BasicMessageChannel(flutterEngine.dartExecutor, "platformImageDemo", StandardMessageCodec())
        .setMessageHandler { message, reply ->
            if (message == "getImage") {
                val inputStream: InputStream = assets.open("eat_new_orleans.jpg")
                reply.reply(inputStream.readBytes())
            }
        }
@override
void initState() {
  super.initState();
  // Receives a string of json object from the platform and converts it to PetModel.
  const BasicMessageChannel<String?>('stringCodecDemo', StringCodec()).setMessageHandler((message) async {
    if (message == null) {
      showSnackBar('An error occurred while adding pet details.', context);
    } else {
      setState(() {
        petListModel = PetListModel.fromJson(message);
      });
    }
    return null;
  });
}
class PetListMessageChannel {
  static const _jsonMessageCodecChannel = BasicMessageChannel<dynamic>('jsonMessageCodecDemo', JSONMessageCodec());
/// Method to add a new pet to the list.
  ///
  /// Demonstrates how to use [BasicMessageChannel] and [JSONMessageCodec] to
  /// send more structured data to platform like a [Map] in this case.
  static void addPetDetails(PetDetails petDetails) {
    _jsonMessageCodecChannel.send(petDetails.toJson());
  }
class PetListMessageChannel {
static const _binaryCodecChannel = BasicMessageChannel('binaryCodecDemo', BinaryCodec());
/// Method to remove a pet from the list.
  ///
  /// Demonstrates how to use [BasicMessageChannel] and [BinaryCodec] to
  /// send [ByteData] to platform. If the reply received is null, then
  /// we will throw a [PlatformException].
  static Future<void> removePet(int index) async {
    final uInt8List = utf8.encoder.convert(index.toString());
    final reply = await _binaryCodecChannel.send(uInt8List.buffer.asByteData());
    if (reply == null) {
      throw PlatformException(
        code: 'INVALID INDEX',
        message: 'Failed to delete pet details',
        details: null,
      );
    }
  }
}
// Registers a MessageHandler for BasicMessageChannel to receive pet details to be
// added in petList and send the it back to Dart using stringCodecChannel.
BasicMessageChannel(flutterEngine.dartExecutor, "jsonMessageCodecDemo", JSONMessageCodec.INSTANCE)
        .setMessageHandler { message, reply ->
            petList.add(0, gson.fromJson(message.toString(), object : TypeToken<Map<String, String>>() {}.type))
            stringCodecChannel.send(gson.toJson(mapOf("petList" to petList)))
        }
val petList = mutableListOf<Map<String, String>>()
val gson = Gson()
// A BasicMessageChannel for sending petList to Dart.
val stringCodecChannel = BasicMessageChannel(flutterEngine.dartExecutor, "stringCodecDemo", StringCodec.INSTANCE)
// Registers a MessageHandler for BasicMessageChannel to receive the index of pet
// details to be removed from the petList and send the petList back to Dart using
// stringCodecChannel. If the index is not in the range of petList, we send null
// back to Dart.
BasicMessageChannel(flutterEngine.dartExecutor, "binaryCodecDemo", BinaryCodec.INSTANCE)
        .setMessageHandler { message, reply ->
            val index = String(message!!.array()).toInt()
            if (index >= 0 && index < petList.size) {
                petList.removeAt(index)
                val replyMessage = "Removed Successfully"
                reply.reply(ByteBuffer.allocateDirect(replyMessage.toByteArray().size)
                    .put(replyMessage.toByteArray()))
                stringCodecChannel.send(gson.toJson(mapOf("petList" to petList)))
            } else {
                reply.reply(null)
            }
        }

flutter实现按键监听

开发中,有时候需要监听按键事件,flutter自身就支持此功能,并不需要在更底层的平台原生代码中实现。flutter要实现按键监听,直接使用RawKeyboardListener这个Widget即可:

移动跨平台框架Flutter介绍和学习线路

Flutter是一款移动应用程序SDK,一份代码可以同时生成iOS和Android两个高性能、高保真的应用程序。Flutter目标是使开发人员能够交付在不同平台上都感觉自然流畅的高性能应用程序。我们兼容滚动行为、排版、图标等方面的差异。

Flutter支持Web开发了!

Flutter作为一个可移植的UI框架,已经支持现代Web应用开发了!我们很开心已经发布了SDK预览版,这样你可以在Web浏览器里直接运行你的Flutter UI代码。

深入理解Flutter多线程

Flutter默认是单线程任务处理的,如果不开启新的线程,任务默认在主线程中处理。和iOS应用很像,在Dart的线程中也存在事件循环和消息队列的概念,但在Dart中线程叫做isolate。

Flutter 局部路由实现

Flutter是借鉴React的开发思想实现的,在子组件的插槽上,React有this.props.children,Vue有<slot></slot>。当然Flutter也有类似的Widget,那就是Navigator,不过是以router的形式实现(像<router-view></router-view>)。

Flutter For Web

用来构建漂亮、定制化应用的跨平台的 UI 框架 Flutter 现在已经支持 Web 开发了。我们很高兴推出了一个预览版的 SDK 可以让开发者直接使用 Flutter UI 和业务逻辑代码构建 web 应用

Flutter 与 iOS 原生 WebView 对比

本文对比的是 UIWebView、WKWebView、flutter_webview_plugin(在 iOS 中使用的是 WKWebView)的加载速度,内存使用情况。测试网页打开的速度,只需要获取 WebView 在开始加载网页和网页加载完成时的时间戳

如何代码获取 Flutter APP 的 FPS

众所周知,官方提供了好几个办法来让我们在开发 Flutter app 的过程中可以使用查看 fps等性能数据,如 devtools ,具体见文档 Debugging Flutter apps 、 Flutter performance profiling等。

在Flutter中使用Android、iOS的原生 View

我们在进行Flutter开发的时候,有时候是需要用到原生的View,比如WebView、MapView、第三方广告SDK等,Flutter提供了AndroidView、UiKitView可以实现相关功能。

Flutter 混合开发 (交互通信)

Flutter 与原生之间的通信依赖灵活的消息传递方式:1,Flutter 部分通过平台通道将消息发送到其应用程序的所在的宿主环境(原生应用)。2,宿主环境通过监听平台通道,接收消息。

点击更多...