Skip to content

Commit 0f14d4f

Browse files
authored
[pigeon] Allow multi instance support with message channel name suffix (#6224)
Adds the ability to instantiate any api using a suffix string to allow for unique instances. partial flutter/flutter#66710
1 parent 3ff376b commit 0f14d4f

File tree

60 files changed

+3843
-1497
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+3843
-1497
lines changed

packages/pigeon/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 18.0.0
2+
3+
* Adds message channel suffix option to all APIs.
4+
* **Breaking Change** [dart] Changes `FlutterApi` `setup` to `setUp`.
5+
16
## 17.3.0
27

38
* [swift] Adds `@SwiftClass` annotation to allow choice between `struct` and `class` for data classes.

packages/pigeon/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ When targeting a Flutter version that supports the
7575
the threading model for handling HostApi methods can be selected with the
7676
`TaskQueue` annotation.
7777

78+
### Multi-Instance Support
79+
80+
Host and Flutter APIs now support the ability to provide a unique message channel suffix string
81+
to the api to allow for multiple instances to be created and operate in parallel.
82+
7883
## Usage
7984

8085
1) Add pigeon as a `dev_dependency`.

packages/pigeon/example/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ class _ExampleFlutterApi implements MessageFlutterApi {
223223
}
224224
}
225225
// ···
226-
MessageFlutterApi.setup(_ExampleFlutterApi());
226+
MessageFlutterApi.setUp(_ExampleFlutterApi());
227227
```
228228

229229
### Swift

packages/pigeon/example/app/android/app/src/main/java/io/flutter/plugins/Messages.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -268,11 +268,20 @@ public interface ExampleHostApi {
268268
}
269269
/** Sets up an instance of `ExampleHostApi` to handle messages through the `binaryMessenger`. */
270270
static void setUp(@NonNull BinaryMessenger binaryMessenger, @Nullable ExampleHostApi api) {
271+
setUp(binaryMessenger, "", api);
272+
}
273+
274+
static void setUp(
275+
@NonNull BinaryMessenger binaryMessenger,
276+
@NonNull String messageChannelSuffix,
277+
@Nullable ExampleHostApi api) {
278+
messageChannelSuffix = messageChannelSuffix.isEmpty() ? "" : "." + messageChannelSuffix;
271279
{
272280
BasicMessageChannel<Object> channel =
273281
new BasicMessageChannel<>(
274282
binaryMessenger,
275-
"dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.getHostLanguage",
283+
"dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.getHostLanguage"
284+
+ messageChannelSuffix,
276285
getCodec());
277286
if (api != null) {
278287
channel.setMessageHandler(
@@ -295,7 +304,8 @@ static void setUp(@NonNull BinaryMessenger binaryMessenger, @Nullable ExampleHos
295304
BasicMessageChannel<Object> channel =
296305
new BasicMessageChannel<>(
297306
binaryMessenger,
298-
"dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.add",
307+
"dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.add"
308+
+ messageChannelSuffix,
299309
getCodec());
300310
if (api != null) {
301311
channel.setMessageHandler(
@@ -324,7 +334,8 @@ static void setUp(@NonNull BinaryMessenger binaryMessenger, @Nullable ExampleHos
324334
BasicMessageChannel<Object> channel =
325335
new BasicMessageChannel<>(
326336
binaryMessenger,
327-
"dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.sendMessage",
337+
"dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.sendMessage"
338+
+ messageChannelSuffix,
328339
getCodec());
329340
if (api != null) {
330341
channel.setMessageHandler(
@@ -356,9 +367,16 @@ public void error(Throwable error) {
356367
/** Generated class from Pigeon that represents Flutter messages that can be called from Java. */
357368
public static class MessageFlutterApi {
358369
private final @NonNull BinaryMessenger binaryMessenger;
370+
private final String messageChannelSuffix;
359371

360372
public MessageFlutterApi(@NonNull BinaryMessenger argBinaryMessenger) {
373+
this(argBinaryMessenger, "");
374+
}
375+
376+
public MessageFlutterApi(
377+
@NonNull BinaryMessenger argBinaryMessenger, @NonNull String messageChannelSuffix) {
361378
this.binaryMessenger = argBinaryMessenger;
379+
this.messageChannelSuffix = messageChannelSuffix.isEmpty() ? "" : "." + messageChannelSuffix;
362380
}
363381

364382
/** Public interface for sending reply. */
@@ -369,7 +387,8 @@ public MessageFlutterApi(@NonNull BinaryMessenger argBinaryMessenger) {
369387

370388
public void flutterMethod(@Nullable String aStringArg, @NonNull Result<String> result) {
371389
final String channelName =
372-
"dev.flutter.pigeon.pigeon_example_package.MessageFlutterApi.flutterMethod";
390+
"dev.flutter.pigeon.pigeon_example_package.MessageFlutterApi.flutterMethod"
391+
+ messageChannelSuffix;
373392
BasicMessageChannel<Object> channel =
374393
new BasicMessageChannel<>(binaryMessenger, channelName, getCodec());
375394
channel.send(

packages/pigeon/example/app/android/app/src/main/kotlin/dev/flutter/pigeon_example_app/Messages.g.kt

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,18 @@ interface ExampleHostApi {
119119
val codec: MessageCodec<Any?> by lazy { ExampleHostApiCodec }
120120
/** Sets up an instance of `ExampleHostApi` to handle messages through the `binaryMessenger`. */
121121
@Suppress("UNCHECKED_CAST")
122-
fun setUp(binaryMessenger: BinaryMessenger, api: ExampleHostApi?) {
122+
fun setUp(
123+
binaryMessenger: BinaryMessenger,
124+
api: ExampleHostApi?,
125+
messageChannelSuffix: String = ""
126+
) {
127+
val separatedMessageChannelSuffix =
128+
if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
123129
run {
124130
val channel =
125131
BasicMessageChannel<Any?>(
126132
binaryMessenger,
127-
"dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.getHostLanguage",
133+
"dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.getHostLanguage$separatedMessageChannelSuffix",
128134
codec)
129135
if (api != null) {
130136
channel.setMessageHandler { _, reply ->
@@ -144,7 +150,7 @@ interface ExampleHostApi {
144150
val channel =
145151
BasicMessageChannel<Any?>(
146152
binaryMessenger,
147-
"dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.add",
153+
"dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.add$separatedMessageChannelSuffix",
148154
codec)
149155
if (api != null) {
150156
channel.setMessageHandler { message, reply ->
@@ -167,7 +173,7 @@ interface ExampleHostApi {
167173
val channel =
168174
BasicMessageChannel<Any?>(
169175
binaryMessenger,
170-
"dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.sendMessage",
176+
"dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.sendMessage$separatedMessageChannelSuffix",
171177
codec)
172178
if (api != null) {
173179
channel.setMessageHandler { message, reply ->
@@ -192,14 +198,20 @@ interface ExampleHostApi {
192198
}
193199
/** Generated class from Pigeon that represents Flutter messages that can be called from Kotlin. */
194200
@Suppress("UNCHECKED_CAST")
195-
class MessageFlutterApi(private val binaryMessenger: BinaryMessenger) {
201+
class MessageFlutterApi(
202+
private val binaryMessenger: BinaryMessenger,
203+
private val messageChannelSuffix: String = ""
204+
) {
196205
companion object {
197206
/** The codec used by MessageFlutterApi. */
198207
val codec: MessageCodec<Any?> by lazy { StandardMessageCodec() }
199208
}
200209

201210
fun flutterMethod(aStringArg: String?, callback: (Result<String>) -> Unit) {
202-
val channelName = "dev.flutter.pigeon.pigeon_example_package.MessageFlutterApi.flutterMethod"
211+
val separatedMessageChannelSuffix =
212+
if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
213+
val channelName =
214+
"dev.flutter.pigeon.pigeon_example_package.MessageFlutterApi.flutterMethod$separatedMessageChannelSuffix"
203215
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
204216
channel.send(listOf(aStringArg)) {
205217
if (it is List<*>) {

packages/pigeon/example/app/ios/Runner/Messages.g.swift

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,13 @@ class ExampleHostApiSetup {
131131
/// The codec used by ExampleHostApi.
132132
static var codec: FlutterStandardMessageCodec { ExampleHostApiCodec.shared }
133133
/// Sets up an instance of `ExampleHostApi` to handle messages through the `binaryMessenger`.
134-
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: ExampleHostApi?) {
134+
static func setUp(
135+
binaryMessenger: FlutterBinaryMessenger, api: ExampleHostApi?, messageChannelSuffix: String = ""
136+
) {
137+
let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
135138
let getHostLanguageChannel = FlutterBasicMessageChannel(
136-
name: "dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.getHostLanguage",
139+
name:
140+
"dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.getHostLanguage\(channelSuffix)",
137141
binaryMessenger: binaryMessenger, codec: codec)
138142
if let api = api {
139143
getHostLanguageChannel.setMessageHandler { _, reply in
@@ -148,7 +152,7 @@ class ExampleHostApiSetup {
148152
getHostLanguageChannel.setMessageHandler(nil)
149153
}
150154
let addChannel = FlutterBasicMessageChannel(
151-
name: "dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.add",
155+
name: "dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.add\(channelSuffix)",
152156
binaryMessenger: binaryMessenger, codec: codec)
153157
if let api = api {
154158
addChannel.setMessageHandler { message, reply in
@@ -166,7 +170,7 @@ class ExampleHostApiSetup {
166170
addChannel.setMessageHandler(nil)
167171
}
168172
let sendMessageChannel = FlutterBasicMessageChannel(
169-
name: "dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.sendMessage",
173+
name: "dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.sendMessage\(channelSuffix)",
170174
binaryMessenger: binaryMessenger, codec: codec)
171175
if let api = api {
172176
sendMessageChannel.setMessageHandler { message, reply in
@@ -193,14 +197,16 @@ protocol MessageFlutterApiProtocol {
193197
}
194198
class MessageFlutterApi: MessageFlutterApiProtocol {
195199
private let binaryMessenger: FlutterBinaryMessenger
196-
init(binaryMessenger: FlutterBinaryMessenger) {
200+
private let messageChannelSuffix: String
201+
init(binaryMessenger: FlutterBinaryMessenger, messageChannelSuffix: String = "") {
197202
self.binaryMessenger = binaryMessenger
203+
self.messageChannelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
198204
}
199205
func flutterMethod(
200206
aString aStringArg: String?, completion: @escaping (Result<String, FlutterError>) -> Void
201207
) {
202208
let channelName: String =
203-
"dev.flutter.pigeon.pigeon_example_package.MessageFlutterApi.flutterMethod"
209+
"dev.flutter.pigeon.pigeon_example_package.MessageFlutterApi.flutterMethod\(messageChannelSuffix)"
204210
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger)
205211
channel.sendMessage([aStringArg] as [Any?]) { response in
206212
guard let listResponse = response as? [Any?] else {

packages/pigeon/example/app/lib/main.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class _ExampleFlutterApi implements MessageFlutterApi {
2020

2121
void main() {
2222
// #docregion main-dart-flutter
23-
MessageFlutterApi.setup(_ExampleFlutterApi());
23+
MessageFlutterApi.setUp(_ExampleFlutterApi());
2424
// #enddocregion main-dart-flutter
2525
runApp(const MyApp());
2626
}

packages/pigeon/example/app/lib/src/messages.g.dart

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -97,16 +97,21 @@ class ExampleHostApi {
9797
/// Constructor for [ExampleHostApi]. The [binaryMessenger] named argument is
9898
/// available for dependency injection. If it is left null, the default
9999
/// BinaryMessenger will be used which routes to the host platform.
100-
ExampleHostApi({BinaryMessenger? binaryMessenger})
101-
: __pigeon_binaryMessenger = binaryMessenger;
100+
ExampleHostApi(
101+
{BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
102+
: __pigeon_binaryMessenger = binaryMessenger,
103+
__pigeon_messageChannelSuffix =
104+
messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
102105
final BinaryMessenger? __pigeon_binaryMessenger;
103106

104107
static const MessageCodec<Object?> pigeonChannelCodec =
105108
_ExampleHostApiCodec();
106109

110+
final String __pigeon_messageChannelSuffix;
111+
107112
Future<String> getHostLanguage() async {
108-
const String __pigeon_channelName =
109-
'dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.getHostLanguage';
113+
final String __pigeon_channelName =
114+
'dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.getHostLanguage$__pigeon_messageChannelSuffix';
110115
final BasicMessageChannel<Object?> __pigeon_channel =
111116
BasicMessageChannel<Object?>(
112117
__pigeon_channelName,
@@ -134,8 +139,8 @@ class ExampleHostApi {
134139
}
135140

136141
Future<int> add(int a, int b) async {
137-
const String __pigeon_channelName =
138-
'dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.add';
142+
final String __pigeon_channelName =
143+
'dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.add$__pigeon_messageChannelSuffix';
139144
final BasicMessageChannel<Object?> __pigeon_channel =
140145
BasicMessageChannel<Object?>(
141146
__pigeon_channelName,
@@ -163,8 +168,8 @@ class ExampleHostApi {
163168
}
164169

165170
Future<bool> sendMessage(MessageData message) async {
166-
const String __pigeon_channelName =
167-
'dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.sendMessage';
171+
final String __pigeon_channelName =
172+
'dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.sendMessage$__pigeon_messageChannelSuffix';
168173
final BasicMessageChannel<Object?> __pigeon_channel =
169174
BasicMessageChannel<Object?>(
170175
__pigeon_channelName,
@@ -198,12 +203,17 @@ abstract class MessageFlutterApi {
198203

199204
String flutterMethod(String? aString);
200205

201-
static void setup(MessageFlutterApi? api,
202-
{BinaryMessenger? binaryMessenger}) {
206+
static void setUp(
207+
MessageFlutterApi? api, {
208+
BinaryMessenger? binaryMessenger,
209+
String messageChannelSuffix = '',
210+
}) {
211+
messageChannelSuffix =
212+
messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
203213
{
204214
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<
205215
Object?>(
206-
'dev.flutter.pigeon.pigeon_example_package.MessageFlutterApi.flutterMethod',
216+
'dev.flutter.pigeon.pigeon_example_package.MessageFlutterApi.flutterMethod$messageChannelSuffix',
207217
pigeonChannelCodec,
208218
binaryMessenger: binaryMessenger);
209219
if (api == null) {

packages/pigeon/example/app/macos/Runner/messages.g.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,17 @@ NSObject<FlutterMessageCodec> *PGNExampleHostApiGetCodec(void);
5656
extern void SetUpPGNExampleHostApi(id<FlutterBinaryMessenger> binaryMessenger,
5757
NSObject<PGNExampleHostApi> *_Nullable api);
5858

59+
extern void SetUpPGNExampleHostApiWithSuffix(id<FlutterBinaryMessenger> binaryMessenger,
60+
NSObject<PGNExampleHostApi> *_Nullable api,
61+
NSString *messageChannelSuffix);
62+
5963
/// The codec used by PGNMessageFlutterApi.
6064
NSObject<FlutterMessageCodec> *PGNMessageFlutterApiGetCodec(void);
6165

6266
@interface PGNMessageFlutterApi : NSObject
6367
- (instancetype)initWithBinaryMessenger:(id<FlutterBinaryMessenger>)binaryMessenger;
68+
- (instancetype)initWithBinaryMessenger:(id<FlutterBinaryMessenger>)binaryMessenger
69+
messageChannelSuffix:(nullable NSString *)messageChannelSuffix;
6470
- (void)flutterMethodAString:(nullable NSString *)aString
6571
completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion;
6672
@end

packages/pigeon/example/app/macos/Runner/messages.g.m

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,21 @@ - (FlutterStandardReader *)readerWithData:(NSData *)data {
138138

139139
void SetUpPGNExampleHostApi(id<FlutterBinaryMessenger> binaryMessenger,
140140
NSObject<PGNExampleHostApi> *api) {
141+
SetUpPGNExampleHostApiWithSuffix(binaryMessenger, api, @"");
142+
}
143+
144+
void SetUpPGNExampleHostApiWithSuffix(id<FlutterBinaryMessenger> binaryMessenger,
145+
NSObject<PGNExampleHostApi> *api,
146+
NSString *messageChannelSuffix) {
147+
messageChannelSuffix = messageChannelSuffix.length > 0
148+
? [NSString stringWithFormat:@".%@", messageChannelSuffix]
149+
: @"";
141150
{
142151
FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc]
143-
initWithName:@"dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.getHostLanguage"
152+
initWithName:[NSString stringWithFormat:@"%@%@",
153+
@"dev.flutter.pigeon.pigeon_example_package."
154+
@"ExampleHostApi.getHostLanguage",
155+
messageChannelSuffix]
144156
binaryMessenger:binaryMessenger
145157
codec:PGNExampleHostApiGetCodec()];
146158
if (api) {
@@ -159,7 +171,11 @@ void SetUpPGNExampleHostApi(id<FlutterBinaryMessenger> binaryMessenger,
159171
}
160172
{
161173
FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc]
162-
initWithName:@"dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.add"
174+
initWithName:
175+
[NSString
176+
stringWithFormat:@"%@%@",
177+
@"dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.add",
178+
messageChannelSuffix]
163179
binaryMessenger:binaryMessenger
164180
codec:PGNExampleHostApiGetCodec()];
165181
if (api) {
@@ -181,7 +197,10 @@ void SetUpPGNExampleHostApi(id<FlutterBinaryMessenger> binaryMessenger,
181197
}
182198
{
183199
FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc]
184-
initWithName:@"dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.sendMessage"
200+
initWithName:[NSString stringWithFormat:@"%@%@",
201+
@"dev.flutter.pigeon.pigeon_example_package."
202+
@"ExampleHostApi.sendMessage",
203+
messageChannelSuffix]
185204
binaryMessenger:binaryMessenger
186205
codec:PGNExampleHostApiGetCodec()];
187206
if (api) {
@@ -210,21 +229,31 @@ void SetUpPGNExampleHostApi(id<FlutterBinaryMessenger> binaryMessenger,
210229

211230
@interface PGNMessageFlutterApi ()
212231
@property(nonatomic, strong) NSObject<FlutterBinaryMessenger> *binaryMessenger;
232+
@property(nonatomic, strong) NSString *messageChannelSuffix;
213233
@end
214234

215235
@implementation PGNMessageFlutterApi
216236

217237
- (instancetype)initWithBinaryMessenger:(NSObject<FlutterBinaryMessenger> *)binaryMessenger {
218-
self = [super init];
238+
return [self initWithBinaryMessenger:binaryMessenger messageChannelSuffix:@""];
239+
}
240+
- (instancetype)initWithBinaryMessenger:(NSObject<FlutterBinaryMessenger> *)binaryMessenger
241+
messageChannelSuffix:(nullable NSString *)messageChannelSuffix {
242+
self = [self init];
219243
if (self) {
220244
_binaryMessenger = binaryMessenger;
245+
_messageChannelSuffix = [messageChannelSuffix length] == 0
246+
? @""
247+
: [NSString stringWithFormat:@".%@", messageChannelSuffix];
221248
}
222249
return self;
223250
}
224251
- (void)flutterMethodAString:(nullable NSString *)arg_aString
225252
completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion {
226-
NSString *channelName =
227-
@"dev.flutter.pigeon.pigeon_example_package.MessageFlutterApi.flutterMethod";
253+
NSString *channelName = [NSString
254+
stringWithFormat:@"%@%@",
255+
@"dev.flutter.pigeon.pigeon_example_package.MessageFlutterApi.flutterMethod",
256+
_messageChannelSuffix];
228257
FlutterBasicMessageChannel *channel =
229258
[FlutterBasicMessageChannel messageChannelWithName:channelName
230259
binaryMessenger:self.binaryMessenger

0 commit comments

Comments
 (0)