Flutter 在平台方法调用中异步返回结果

Flutter 在平台方法调用中异步返回结果

Flutter 在平台方法调用中异步返回结果

asynchronous_method_channel 是一个在 Flutter 和 Native 之间异步调用方法时,支持异步返回结果的插件。

在利用 Flutter 编写跨平台应用时,一些功能需要调用 Native 方法才能实现,可以利用 Flutter 为我们提供的 MethodChannel 实现。对与 Flutter 来说,所有的 Native 方法调用都是异步返回的,但是对于 Native 来说,对于来自 Flutter 的方法调用,我们要返回的结果却不能异步返回,如果我们尝试在执行异步操作之后调用result.success(something),执行时会得到java.lang.IllegalStateException: Reply already submitted的错误信息。所以 AsynchronousMethodChannel 是对 MethodChannel 的一次封装,为其添加了异步返回方法调用结果的功能。因为对于 Flutter,和 Native 的通信即方法调用必须在平台主线程,但我们又知道应该尽量避免在主线程进行耗时操作,所以需要有一个措施来支持平台方法调用时异步返回结果,即编写本库的目的。

关于 asynchronous_method_channel

Package: https://pub.dev/packages/asynchronous_method_channel

Example: https://github.com/microtears/asynchronous-method-channel/tree/master/example

Repository: https://github.com/microtears/asynchronous-method-channel

Documentation: https://pub.dev/documentation/asynchronous_method_channel/latest/

View/report issues: https://github.com/microtears/asynchronous-method-channel/issues

Flutter 配置

version: v1.9.1+hotfix.6

channel: master

在 Android 上通过 AsynchronousMethodChannel 和 kotlin 编写插件

下面是一个利用 kotlin 协程执行异步任务并返回结果的示例。

在正式开始之前,需要我们了解的一件事是:Flutter 应用程序中 Android 模块的 gradle 不会自动导入我们需要的 Java 包,您必须手动添加以下代码。

import io.flutter.plugins.asynchronous_method_channel.AsynchronousMethodChannel

class MainActivity: FlutterActivity() , AsynchronousMethodChannel.MethodCallHandler {

companion object{

const val CHANNEL="AsynchronousMethodChannelExample"

}

private var parentJob = Job()

private val coroutineContext: CoroutineContext

get() = parentJob + Dispatchers.Main

private val scope = CoroutineScope(coroutineContext)

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

GeneratedPluginRegistrant.registerWith(this)

AsynchronousMethodChannel(flutterView, CHANNEL).setMethodCallHandler(this)

}

override fun onMethodCall(call: MethodCall, result: AsynchronousMethodChannel.Result) {

when (call.method) {

"getBatteryLevel" -> {

result.success(null)

scope.launch(Dispatchers.IO){

// Do something

// Perform asynchronous time-consuming tasks

// Just return results after 2 seconds

delay(2000)

// The method in AsynchronousMethodChannel.Result must be called on the main thread of the platform

scope.launch(Dispatchers.Main){

result.successAsynchronous(getBatteryLevel().toString())

}

}

}

else -> result.notImplemented()

}

}

private fun getBatteryLevel(): Int {

val batteryLevel: Int

batteryLevel = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

val batteryManager = getSystemService(Context.BATTERY_SERVICE) as BatteryManager

batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)

} else {

val intent = ContextWrapper(applicationContext).registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))

intent!!.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100 / intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)

}

return batteryLevel

}

override fun onDestroy() {

// cancel all asynchronous jobs

scope.cancel()

super.onDestroy()

}

}

在 Flutter 上通过 AsynchronousMethodChannel 和 dart 编写插件

下面是一个在 Flutter 应用程序中使用 AsynchronousMethodChannel 的示例。

class _MyAppState extends State {

static final platform =

AsynchronousMethodChannel('AsynchronousMethodChannelExample');

String _batteryLevel = 'Unknown';

String _timeInfo = "";

static const style = TextStyle(

fontSize: 16,

fontFamily: "monospace",

);

@override

void initState() {

super.initState();

initPlatformState();

}

// Platform messages are asynchronous, so we initialize in an async method.

Future initPlatformState() async {

String batteryLevel;

// Platform messages may fail, so we use a try/catch PlatformException.

try {

final sb = StringBuffer();

final startAt = DateTime.now();

sb.writeln("[start] [$startAt]");

batteryLevel =

await platform.invokeAsynchronousMethod("getBatteryLevel");

final endAt = DateTime.now();

sb.writeln("[end ] [$endAt]");

sb.writeln("[tag ] [hours:minutes:seconds:us]");

sb.writeln("[total] [${endAt.difference(startAt)}]");

_timeInfo = sb.toString();

} on PlatformException {

batteryLevel = 'Failed to get platform version.';

}

// If the widget was removed from the tree while the asynchronous platform

// message was in flight, we want to discard the reply rather than calling

// setState to update our non-existent appearance.

if (!mounted) return;

setState(() {

_batteryLevel = batteryLevel;

});

}

@override

Widget build(BuildContext context) {

return MaterialApp(

home: Scaffold(

appBar: AppBar(

title: const Text('AsynchronousMethodChannel example app'),

),

body: Padding(

padding: const EdgeInsets.all(20.0),

child: Column(

crossAxisAlignment: CrossAxisAlignment.start,

children: [

Text('Battery level: $_batteryLevel\n', style: style),

Text(_timeInfo, style: style),

Center(

child: FlatButton(

onPressed: initPlatformState,

child: Text("Get battery level"),

),

),

],

),

),

),

);

}

}

截图

在测试时使用 AsynchronousMethodChannel

void main() {

TestWidgetsFlutterBinding.ensureInitialized();

final AsynchronousMethodChannel channel =

AsynchronousMethodChannel('asynchronous_method_channel');

setUp(() {

channel.setMockAsynchronousMethodCallHandler(

(MethodCall methodCall, MockResult result) async {

switch (methodCall.method) {

case "asynchronousMethod":

// Delay 30 milliseconds to return results

Future.delayed(Duration(milliseconds: 30),

() => result.success(methodCall.arguments));

break;

case "syncMethod":

return "ok";

break;

case "getBatteryLevel":

result.success("100");

break;

}

return null;

});

});

tearDown(() {

channel.setMockAsynchronousMethodCallHandler(null);

});

test('testMethod', () async {

expect(

await channel.invokeAsynchronousMethod(

"asynchronousMethod",

{"arg": "arg1"},

),

{"arg": "arg1"},

);

expect(

await channel.invokeMethod("syncMethod"),

"ok",

);

expect(

await channel.invokeAsynchronousMethod("getBatteryLevel"),

"100",

);

});

}

在 IOS 上使用 AsynchronousMethodChannel

预计在下一个版本发布。

关于更多

请参阅示例。

相关推荐

璜怎么读
365速发国际靠谱么

璜怎么读

📅 12-30 👁️ 4224
青桐资本荣获“最佳财务顾问综合榜”、“最佳财务顾问活跃榜”、“低空经济产业活跃机构”|青桐荣誉
More translations of在哪里in English
healthy 365 app

More translations of在哪里in English

📅 11-03 👁️ 2056
陈小春《相依为命》[FLAC/MP3
healthy 365 app

陈小春《相依为命》[FLAC/MP3

📅 07-02 👁️ 1726
这样的提拉米苏,不要买!不能吃!
365速发国际靠谱么

这样的提拉米苏,不要买!不能吃!

📅 11-05 👁️ 9786
亚洲队世界杯历史最好战绩(过去与现在的对比,亚洲队在世界杯赛场上的突破与进步)
【問題】煲機要煲多久?幾次? @影音視聽討論區 哈啦板
鱼鲞烤肉的做法与步骤
healthy 365 app

鱼鲞烤肉的做法与步骤

📅 10-05 👁️ 8720
正常心跳是多少?心跳快慢藏警訊,秒懂心臟健康關鍵密碼