1. 概要
上記は「MethodChannel」を使い、Native(Android)側と連携する内容でした。
今回は「EventChannel」を使い、Native(Android)側と連携する内容です。
対象としては開発を1年程やってて自分で最初から開発してみたい方になります。そのため細かい用語などの説明はしません。
2. FlutterとNativeの連携方法
こちらを参考
3. プロジェクトの準備
3-1. プロジェクトを作成
4. ソースコード(Kotlin)
4-1. android/app/src/main/kotlin/com/example/batterylevel/MainActivity.kt
- このファイルはFlutterプロジェクトを作成すると、自動生成されるので内容を変更
package com.example.event_channel_counter
import android.os.Handler
import android.os.Looper
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.EventChannel
class MainActivity : FlutterActivity() {
private val eventChannel = "samples.flutter.dev/counter"
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
EventChannel(flutterEngine.dartExecutor.binaryMessenger, eventChannel).setStreamHandler(
CounterHandler
)
}
}
object CounterHandler : EventChannel.StreamHandler {
private val handler = Handler(Looper.getMainLooper())
private var eventSink: EventChannel.EventSink? = null
private var counter: Int = 0
private val runnable: Runnable = object : Runnable {
override fun run() {
countUp()
}
}
fun countUp() {
eventSink?.success(counter++)
handler.postDelayed(runnable, 1000)
}
override fun onListen(arguments: Any?, sink: EventChannel.EventSink) {
eventSink = sink
handler.post(runnable)
}
override fun onCancel(arguments: Any?) {
eventSink = null
handler.removeCallbacks(runnable)
}
}
- EventChannel
- https://api.flutter.dev/javadoc/io/flutter/plugin/common/EventChannel.html
- setStreamHandler
- 当チャンネルにてストリームハンドラー(イベントリスナー)を設定
- Looper
- https://developer.android.com/reference/kotlin/android/os/Looper
- スレッドにて作成されたメッセージをFIFOで処理するMessageQueue
- Handler
- https://developer.android.com/reference/kotlin/android/os/Handler
- LooperでMessageQueue管理ができるようにするハンドラー
- post / postDelayed
- メッセージをMessageQueueに追加
- 1000ms(1秒)毎に発生し、カウントアップ
- EventChannel.StreamHandler
- onListen
- イベントストリームでのリクエストを管理
- EventChannelが確立されたら、呼ばれる
- onListen
- EventChannel.EventSink
- https://api.flutter.dev/javadoc/io/flutter/plugin/common/EventChannel.EventSink.html
- success
- 送信するイベントを設定
- Event callback
- 「CHANNEL」について
- samples.flutter.dev/counter
- Flutter側との通路
The client and host sides of a channel are connected through a channel name passed in the channel constructor. All channel names used in a single app must be unique; prefix the channel name with a unique ‘domain prefix’, for example:
Writing custom platform-specific code | Fluttersamples.flutter.dev/battery
.
5. ソースコード(Dart)
5-1. lib/main.dart
import 'package:flutter/material.dart';
import 'views/counter_page.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyCounterPage(),
);
}
}
5-2. lib/views/counter_page.dart
import 'package:flutter/material.dart';
import '../repository/counter_repository.dart';
class MyCounterPage extends StatelessWidget {
const MyCounterPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Counter from platform of android'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
StreamBuilder<int>(
stream: streamCounter(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(
'${snapshot.data}',
style: Theme.of(context).textTheme.headline4,
);
} else {
return const CircularProgressIndicator();
}
}),
],
),
),
);
}
}
- StreamBuilder
- https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html
- ストリームの最新のデータで自身を再構築するウィジェット
5-3. lib/repository/counter_repository.dart
import 'package:flutter/services.dart';
Stream<int> streamCounter() {
const counterChannel = EventChannel('samples.flutter.dev/counter');
return counterChannel.receiveBroadcastStream().map((event) {
return int.parse(event.toString());
});
}
- EventChannel
- samples.flutter.dev/counter
- Native側との通路
- receiveBroadcastStream
- 上記チャンネル名で確立されたチャンネルにて、Native側からのイベントを受信
- samples.flutter.dev/counter
6. 結果
6-1. 1秒間隔でカウントアップ
下記ページにて、MessageChannelで連携する内容を書いたので合わせて読んで頂けますと幸いです。
7. 参考
投稿者プロフィール
-
開発好きなシステムエンジニアです。
卓球にハマってます。