Skip to content

Commit b166353

Browse files
committed
fix: fixed bad null safety implementation
1 parent 7c9f9bc commit b166353

File tree

5 files changed

+84
-48
lines changed

5 files changed

+84
-48
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 4.2.1
2+
3+
* Improved nullsafety
4+
15
## 4.2.0
26

37
* Null safe merged to master

lib/src/controller.dart

+22-22
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@ part of flutter_unity_widget;
22

33
typedef void UnityCreatedCallback(UnityWidgetController controller);
44

5-
final UnityViewFlutterPlatform _unityViewFlutterPlatform =
6-
UnityViewFlutterPlatform.instance;
7-
85
class UnityWidgetController {
96
final _UnityWidgetState _unityWidgetState;
107

@@ -25,7 +22,7 @@ class UnityWidgetController {
2522
/// in [UnityWidget.onUnityCreated] callback.
2623
static Future<UnityWidgetController> init(
2724
int id, _UnityWidgetState unityWidgetState) async {
28-
await _unityViewFlutterPlatform.init(id);
25+
await UnityViewFlutterPlatform.instance.init(id);
2926
return UnityWidgetController._(
3027
unityWidgetState,
3128
unityId: id,
@@ -34,30 +31,31 @@ class UnityWidgetController {
3431

3532
@visibleForTesting
3633
MethodChannel? get channel {
37-
if (_unityViewFlutterPlatform is MethodChannelUnityViewFlutter) {
38-
return (_unityViewFlutterPlatform as MethodChannelUnityViewFlutter)
34+
if (UnityViewFlutterPlatform.instance is MethodChannelUnityViewFlutter) {
35+
return (UnityViewFlutterPlatform.instance
36+
as MethodChannelUnityViewFlutter)
3937
.channel(unityId);
4038
}
4139
return null;
4240
}
4341

4442
void _connectStreams(int unityId) {
4543
if (_unityWidgetState.widget.onUnityMessage != null) {
46-
_onUnityMessageSub = _unityViewFlutterPlatform
44+
_onUnityMessageSub = UnityViewFlutterPlatform.instance
4745
.onUnityMessage(unityId: unityId)
4846
.listen((UnityMessageEvent e) =>
4947
_unityWidgetState.widget.onUnityMessage!(e.value));
5048
}
5149

5250
if (_unityWidgetState.widget.onUnitySceneLoaded != null) {
53-
_onUnitySceneLoadedSub = _unityViewFlutterPlatform
51+
_onUnitySceneLoadedSub = UnityViewFlutterPlatform.instance
5452
.onUnitySceneLoaded(unityId: unityId)
5553
.listen((UnitySceneLoadedEvent e) =>
5654
_unityWidgetState.widget.onUnitySceneLoaded!(e.value));
5755
}
5856

5957
if (_unityWidgetState.widget.onUnityUnloaded != null) {
60-
_onUnityUnloadedSub = _unityViewFlutterPlatform
58+
_onUnityUnloadedSub = UnityViewFlutterPlatform.instance
6159
.onUnityUnloaded(unityId: unityId)
6260
.listen((_) => _unityWidgetState.widget.onUnityUnloaded!());
6361
}
@@ -67,7 +65,7 @@ class UnityWidgetController {
6765
/// Returns `true` if unity player is ready.
6866
Future<bool?>? isReady() {
6967
if (!_unityWidgetState.widget.enablePlaceholder) {
70-
return _unityViewFlutterPlatform.isReady(unityId: unityId);
68+
return UnityViewFlutterPlatform.instance.isReady(unityId: unityId);
7169
}
7270
return null;
7371
}
@@ -76,7 +74,7 @@ class UnityWidgetController {
7674
/// Returns `true` if unity player is paused.
7775
Future<bool?>? isPaused() {
7876
if (!_unityWidgetState.widget.enablePlaceholder) {
79-
return _unityViewFlutterPlatform.isPaused(unityId: unityId);
77+
return UnityViewFlutterPlatform.instance.isPaused(unityId: unityId);
8078
}
8179
return null;
8280
}
@@ -85,7 +83,7 @@ class UnityWidgetController {
8583
/// Returns `true` if unity player is loaded.
8684
Future<bool?>? isLoaded() {
8785
if (!_unityWidgetState.widget.enablePlaceholder) {
88-
return _unityViewFlutterPlatform.isLoaded(unityId: unityId);
86+
return UnityViewFlutterPlatform.instance.isLoaded(unityId: unityId);
8987
}
9088
return null;
9189
}
@@ -94,7 +92,7 @@ class UnityWidgetController {
9492
/// Returns `true` if unity player is in background.
9593
Future<bool?>? inBackground() {
9694
if (!_unityWidgetState.widget.enablePlaceholder) {
97-
return _unityViewFlutterPlatform.inBackground(unityId: unityId);
95+
return UnityViewFlutterPlatform.instance.inBackground(unityId: unityId);
9896
}
9997
return null;
10098
}
@@ -104,7 +102,8 @@ class UnityWidgetController {
104102
/// Returns `true` if unity player was created succesfully.
105103
Future<bool?>? create() {
106104
if (!_unityWidgetState.widget.enablePlaceholder) {
107-
return _unityViewFlutterPlatform.createUnityPlayer(unityId: unityId);
105+
return UnityViewFlutterPlatform.instance
106+
.createUnityPlayer(unityId: unityId);
108107
}
109108
return null;
110109
}
@@ -118,7 +117,7 @@ class UnityWidgetController {
118117
/// ```
119118
Future<void>? postMessage(String gameObject, methodName, message) {
120119
if (!_unityWidgetState.widget.enablePlaceholder) {
121-
return _unityViewFlutterPlatform.postMessage(
120+
return UnityViewFlutterPlatform.instance.postMessage(
122121
unityId: unityId,
123122
gameObject: gameObject,
124123
methodName: methodName,
@@ -138,7 +137,7 @@ class UnityWidgetController {
138137
Future<void>? postJsonMessage(
139138
String gameObject, String methodName, Map<String, dynamic> message) {
140139
if (!_unityWidgetState.widget.enablePlaceholder) {
141-
return _unityViewFlutterPlatform.postJsonMessage(
140+
return UnityViewFlutterPlatform.instance.postJsonMessage(
142141
unityId: unityId,
143142
gameObject: gameObject,
144143
methodName: methodName,
@@ -151,15 +150,15 @@ class UnityWidgetController {
151150
/// Pause the unity in-game player with this method
152151
Future<void>? pause() {
153152
if (!_unityWidgetState.widget.enablePlaceholder) {
154-
return _unityViewFlutterPlatform.pausePlayer(unityId: unityId);
153+
return UnityViewFlutterPlatform.instance.pausePlayer(unityId: unityId);
155154
}
156155
return null;
157156
}
158157

159158
/// Resume the unity in-game player with this method idf it is in a paused state
160159
Future<void>? resume() {
161160
if (!_unityWidgetState.widget.enablePlaceholder) {
162-
return _unityViewFlutterPlatform.resumePlayer(unityId: unityId);
161+
return UnityViewFlutterPlatform.instance.resumePlayer(unityId: unityId);
163162
}
164163
return null;
165164
}
@@ -168,7 +167,8 @@ class UnityWidgetController {
168167
/// It works for Android and iOS is WIP
169168
Future<void>? openInNativeProcess() {
170169
if (!_unityWidgetState.widget.enablePlaceholder) {
171-
return _unityViewFlutterPlatform.openInNativeProcess(unityId: unityId);
170+
return UnityViewFlutterPlatform.instance
171+
.openInNativeProcess(unityId: unityId);
172172
}
173173
return null;
174174
}
@@ -177,15 +177,15 @@ class UnityWidgetController {
177177
/// iOS is WIP. For more information please read [Unity Docs](https://docs.unity3d.com/2020.2/Documentation/Manual/UnityasaLibrary.html)
178178
Future<void>? unload() {
179179
if (!_unityWidgetState.widget.enablePlaceholder) {
180-
return _unityViewFlutterPlatform.unloadPlayer(unityId: unityId);
180+
return UnityViewFlutterPlatform.instance.unloadPlayer(unityId: unityId);
181181
}
182182
return null;
183183
}
184184

185185
/// Quits unity player. Note that this kills the current flutter process, thus quiting the app
186186
Future<void>? quit() {
187187
if (!_unityWidgetState.widget.enablePlaceholder) {
188-
return _unityViewFlutterPlatform.quitPlayer(unityId: unityId);
188+
return UnityViewFlutterPlatform.instance.quitPlayer(unityId: unityId);
189189
}
190190
return null;
191191
}
@@ -203,7 +203,7 @@ class UnityWidgetController {
203203

204204
void dispose() {
205205
_cancelSubscriptions();
206-
_unityViewFlutterPlatform.dispose(unityId: unityId);
206+
UnityViewFlutterPlatform.instance.dispose(unityId: unityId);
207207
}
208208
}
209209

lib/src/device_method.dart

+52-23
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,56 @@
11
part of flutter_unity_widget;
22

3+
/// Error thrown when an unknown unity ID is provided to a method channel API.
4+
class UnknownUnityIDError extends Error {
5+
/// Creates an assertion error with the provided [unityId] and optional
6+
/// [message].
7+
UnknownUnityIDError(this.unityId, [this.message]);
8+
9+
/// The unknown ID.
10+
final int unityId;
11+
12+
/// Message describing the assertion error.
13+
final Object? message;
14+
15+
String toString() {
16+
if (message != null) {
17+
return "Unknown unity ID $unityId: ${Error.safeToString(message)}";
18+
}
19+
return "Unknown unity ID $unityId";
20+
}
21+
}
22+
323
class MethodChannelUnityViewFlutter extends UnityViewFlutterPlatform {
424
// Every method call passes the int unityId
5-
final Map<int, MethodChannel?> _channels = {};
25+
late final Map<int, MethodChannel> _channels = {};
626

727
/// Accesses the MethodChannel associated to the passed unityId.
8-
MethodChannel? channel(int unityId) {
9-
return _channels[unityId];
28+
MethodChannel channel(int unityId) {
29+
MethodChannel? channel = _channels[unityId];
30+
if (channel == null) {
31+
throw UnknownUnityIDError(unityId);
32+
}
33+
return channel;
1034
}
1135

12-
/// Initializes the platform interface with [id].
13-
///
14-
/// This method is called when the plugin is first initialized.
15-
@override
16-
Future<void> init(int unityId) {
17-
MethodChannel? channel;
18-
if (!_channels.containsKey(unityId)) {
36+
MethodChannel ensureChannelInitialized(int unityId) {
37+
MethodChannel? channel = _channels[unityId];
38+
if (channel == null) {
1939
channel = MethodChannel('plugin.xraph.com/unity_view_$unityId');
2040
channel.setMethodCallHandler(
2141
(MethodCall call) => _handleMethodCall(call, unityId));
2242
_channels[unityId] = channel;
2343
}
24-
return channel!.invokeMethod<void>('unity#waitForUnity');
44+
return channel;
45+
}
46+
47+
/// Initializes the platform interface with [id].
48+
///
49+
/// This method is called when the plugin is first initialized.
50+
@override
51+
Future<void> init(int unityId) {
52+
MethodChannel channel = ensureChannelInitialized(unityId);
53+
return channel.invokeMethod<void>('unity#waitForUnity');
2554
}
2655

2756
/// Dispose of the native resources.
@@ -65,27 +94,27 @@ class MethodChannelUnityViewFlutter extends UnityViewFlutterPlatform {
6594

6695
@override
6796
Future<bool?> isPaused({required int unityId}) async {
68-
return await channel(unityId)!.invokeMethod('unity#isPaused');
97+
return await channel(unityId).invokeMethod('unity#isPaused');
6998
}
7099

71100
@override
72101
Future<bool?> isReady({required int unityId}) async {
73-
return await channel(unityId)!.invokeMethod('unity#isReady');
102+
return await channel(unityId).invokeMethod('unity#isReady');
74103
}
75104

76105
@override
77106
Future<bool?> isLoaded({required int unityId}) async {
78-
return await channel(unityId)!.invokeMethod('unity#isLoaded');
107+
return await channel(unityId).invokeMethod('unity#isLoaded');
79108
}
80109

81110
@override
82111
Future<bool?> inBackground({required int unityId}) async {
83-
return await channel(unityId)!.invokeMethod('unity#inBackground');
112+
return await channel(unityId).invokeMethod('unity#inBackground');
84113
}
85114

86115
@override
87116
Future<bool?> createUnityPlayer({required int unityId}) async {
88-
return await channel(unityId)!.invokeMethod('unity#createPlayer');
117+
return await channel(unityId).invokeMethod('unity#createPlayer');
89118
}
90119

91120
@override
@@ -170,7 +199,7 @@ class MethodChannelUnityViewFlutter extends UnityViewFlutterPlatform {
170199
required String gameObject,
171200
required String methodName,
172201
required String message}) async {
173-
await channel(unityId)!.invokeMethod('unity#postMessage', <String, dynamic>{
202+
await channel(unityId).invokeMethod('unity#postMessage', <String, dynamic>{
174203
'gameObject': gameObject,
175204
'methodName': methodName,
176205
'message': message,
@@ -183,7 +212,7 @@ class MethodChannelUnityViewFlutter extends UnityViewFlutterPlatform {
183212
required String gameObject,
184213
required String methodName,
185214
required Map message}) async {
186-
await channel(unityId)!.invokeMethod('unity#postMessage', <String, dynamic>{
215+
await channel(unityId).invokeMethod('unity#postMessage', <String, dynamic>{
187216
'gameObject': gameObject,
188217
'methodName': methodName,
189218
'message': json.encode(message),
@@ -192,26 +221,26 @@ class MethodChannelUnityViewFlutter extends UnityViewFlutterPlatform {
192221

193222
@override
194223
Future<void> pausePlayer({required int unityId}) async {
195-
await channel(unityId)!.invokeMethod('unity#pausePlayer');
224+
await channel(unityId).invokeMethod('unity#pausePlayer');
196225
}
197226

198227
@override
199228
Future<void> resumePlayer({required int unityId}) async {
200-
await channel(unityId)!.invokeMethod('unity#resumePlayer');
229+
await channel(unityId).invokeMethod('unity#resumePlayer');
201230
}
202231

203232
@override
204233
Future<void> openInNativeProcess({required int unityId}) async {
205-
await channel(unityId)!.invokeMethod('unity#openInNativeProcess');
234+
await channel(unityId).invokeMethod('unity#openInNativeProcess');
206235
}
207236

208237
@override
209238
Future<void> unloadPlayer({required int unityId}) async {
210-
await channel(unityId)!.invokeMethod('unity#unloadPlayer');
239+
await channel(unityId).invokeMethod('unity#unloadPlayer');
211240
}
212241

213242
@override
214243
Future<void> quitPlayer({required int unityId}) async {
215-
await channel(unityId)!.invokeMethod('unity#quitPlayer');
244+
await channel(unityId).invokeMethod('unity#quitPlayer');
216245
}
217246
}

lib/src/unity_view.dart

+5-2
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class _UnityWidgetState extends State<UnityWidget> {
7171
Text('Placeholder mode enabled, no native code will be called');
7272
}
7373

74-
return _unityViewFlutterPlatform.buildView(
74+
return UnityViewFlutterPlatform.instance.buildView(
7575
creationParams,
7676
widget.gestureRecognizers,
7777
onPlatformViewCreated,
@@ -81,7 +81,10 @@ class _UnityWidgetState extends State<UnityWidget> {
8181
Future<void> onPlatformViewCreated(int id) async {
8282
final controller = await UnityWidgetController.init(id, this);
8383
_controller.complete(controller);
84-
widget.onUnityCreated(controller);
84+
final UnityCreatedCallback? onUnityCreated = widget.onUnityCreated;
85+
if (onUnityCreated != null) {
86+
onUnityCreated(controller);
87+
}
8588
print('*********************************************');
8689
print('** flutter unity controller setup complete **');
8790
print('*********************************************');

pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: flutter_unity_widget
22
description: Flutter Unity 3D widget for embedding Unity game scenes in flutter. This library now supports Unity as a Library.
3-
version: 4.2.0
3+
version: 4.2.1
44
#authors:
55
# - Rex Raphael <rex.raphael@outlook.com>
66
# - Thomas Stockx <thomas@stockxit.com>

0 commit comments

Comments
 (0)