Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moved the default BinaryMessenger instance to ServicesBinding #38464

Merged
merged 8 commits into from Aug 21, 2019

Conversation

adazh
Copy link
Contributor

@adazh adazh commented Aug 13, 2019

Description

Moved the [default BinaryMessenger] instance (

const BinaryMessenger defaultBinaryMessenger = _DefaultBinaryMessenger._();
) to ServicesBinding.

This PR reverts the revert of the original PR.

Related Issues

#37409

Tests

I added the following tests:

Unit/Widget tests updated.
Manually tested on the example platform_channel app.
Also ran the devicelab tests locally.

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I signed the CLA.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I updated/added relevant documentation (doc comments with ///).
  • All existing and new tests are passing.
  • The analyzer (flutter analyze --flutter-repo) does not report any problems on my PR.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Does your PR require Flutter developers to manually update their apps to accommodate your change?

@fluttergithubbot fluttergithubbot added a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) a: tests "flutter test", flutter_test, or one of our tests f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels. team Infra upgrades, team productivity, code health, technical debt. See also team: labels. labels Aug 13, 2019
@adazh
Copy link
Contributor Author

adazh commented Aug 13, 2019

Cc @amirh @mklim

@adazh
Copy link
Contributor Author

adazh commented Aug 14, 2019

Hmm... I've seen a lot of tests complaining about " | Because flutter_gallery depends on connectivity >=0.4.2+1 which requires Flutter SDK version >=1.2.0 <2.0.0, version solving failed." Any idea what the error is about?

@adazh adazh requested a review from tvolkert August 14, 2019 17:40
@tvolkert
Copy link
Contributor

The errors you're seeing are unrelated to this PR - I'd rebase against ToT and push the rebased commit to kick off fresh tests.

@@ -130,10 +131,16 @@ class MethodChannel {
/// The message codec used by this channel, not null.
final MethodCodec codec;

<<<<<<< HEAD
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bad merge. Looks like a lot of stuff got lost too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ya... still familiarizing myself with git... Trying to recover the commits..

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Phew... got everything back!

@@ -6,6 +6,7 @@ import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui;

import '../../foundation.dart';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import 'package:flutter/foundation.dart';

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to absolute path. But what's the rule for imported path? @goderbauer suggested using relative paths within the same package, but seems not always true?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Relative imports within the same layer / directory. services and foundation are different layers and so are treated as different packages.

@adazh adazh requested a review from tvolkert August 14, 2019 22:28
@@ -31,6 +31,9 @@ import 'platform_channel.dart';
class BinaryMessages {
BinaryMessages._();

/// The messenger which sends the platform messages, not null.
static final BinaryMessenger _binaryMessenger = ServicesBinding.instance.defaultBinaryMessenger;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible for this to be called before the binding is initialized?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BinaryMessages has been deprecated. Anyway, I replaced the ServicesBinding.instance.defaultBinaryMessenger with defaultBinaryMessenger to be safe.

Copy link
Contributor

@tvolkert tvolkert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. @amirh this is intentionally a hard-breaking change with a simple 1-line forwards-compatible fix. It's likely that a few plugins will need to be updated.

@tvolkert
Copy link
Contributor

@adazh can you post an update to the breaking change announcement (https://groups.google.com/d/msg/flutter-announce/sHAL2fBtJ1Y/mGjrKH3dEwAJ), since the original announcement didn't call out the failure case of needing to initialize the binding before calling runApp() in cases of plugin initialization (or the case of tests).

thx!

@adazh
Copy link
Contributor Author

adazh commented Aug 14, 2019

@adazh can you post an update to the breaking change announcement (https://groups.google.com/d/msg/flutter-announce/sHAL2fBtJ1Y/mGjrKH3dEwAJ), since the original announcement didn't call out the failure case of needing to initialize the binding before calling runApp() in cases of plugin initialization (or the case of tests).

thx!

Sure, will do. @tvolkert @amirh Is tomorrow morning a good time to land this change? What time do you suggest?

@tvolkert
Copy link
Contributor

@adazh if you could sync with @darrenaustin to find out the places that broke in Google's repo when the first attempt tried to roll, and send forwards-compatible fixes first, that would be very helpful, so we can land this once it's ready to roll and don't back up the roll again.

@basketball-ico
Copy link

@adazh
With this change I need to call WidgetsFlutterBinding.ensureInitialized() in the main if I want to call some code before call runApp like Firestore (For get some preferences), but this show a black screen before runApp is called , I want to keep the native launch screen like before this change (not show other widget), how can I do that?

@goderbauer
Copy link
Member

@basketball-ico Can you file an issue for this that shows some example code? Please mention me on the issue.

@goderbauer
Copy link
Member

I can reproduce this, see #39494.

@vikramkapoor
Copy link

I am seeing this issue on Flutter main and dev channels and adding WidgetFlutterBinding.ensureInitialized() at the start of Main() doesn't make any difference. I spent hours trying to debug it and gave up switched to stable channel to make it go away.

@tvolkert
Copy link
Contributor

tvolkert commented Sep 3, 2019

@vikramkapoor are you talking about #39494?

@vikramkapoor
Copy link

vikramkapoor commented Sep 3, 2019

Thanks for following up. What I meant is that I got the following exception due to the breaking change.

If you're running an application and need to access the binary messenger before `runApp()` has been called (for example, during plugin initialization), then you need to explicitly call the `WidgetsFlutterBinding.ensureInitialized()` first.
If you're running a test, you can call the `TestWidgetsFlutterBinding.ensureInitialized()` as the first line in your test's `main()` method to initialize the binding.
#0      defaultBinaryMessenger.<anonymous closure> 
package:flutter/…/services/binary_messenger.dart:73
#1      defaultBinaryMessenger 
package:flutter/…/services/binary_messenger.dart:86
#2      EventChannel.binaryMessenger 
package:flutter/…/services/platform_channel.dart:484
#3      EventChannel.receiveBroadcastStream.<anonymous closure> 
package:flutter/…/services/platform_channel.dart:504
<asynchronous suspension>
#4      _runGuarded  (dart:async/stream_controller.dart:805:24)
#5      _BroadcastStreamController._subscribe  (dart:async/broadcast_stream_controller.dart:213:7)
#6      _ControllerStream._createSubscription  (dart:async/stream_controller.dart:818:19)
#7      _StreamImpl.listen  (dart:async/stream_impl.dart:472:9)
#8      FlutterIsolate._isolateInitialize 
package:flutter_isolate/flutter_isolate.dart:104
#9      _flutterIsolateEntryPoint 
package:flutter_isolate/flutter_isolate.dart:132
#10     _runMainZoned.<anonymous closure>.<anonymous closure>  (dart:ui/hooks.dart:229:25)
#11     _rootRun  (dart:async/zone.dart:1124:13)
#12     _CustomZone.run  (dart:async/zone.dart:1021:19)
#13     _runZoned  (dart:async/zone.dart:1516:10)
#14     runZoned  (dart:async/zone.dart:1500:12)
#15     _runMainZoned.<anonymous closure>  (dart:ui/hooks.dart:221:5)
#16     _startIsolate.<anonymous closure>  (dart:isolate-patch/isolate_patch.dart:305:19)
#17     _RawReceivePortImpl._handleMessage  (dart:isolate-patch/isolate_patch.dart:172:12)

while running the following code after runApp() had already been called

 Globals.receivePort = ReceivePort();
            print("Spawning isolate 1");
            FlutterIsolate.spawn(isolate1, Globals.receivePort.sendPort).then((
                data) =>
            Globals.isolate = data);
            broadcastReceivePort =  Globals.receivePort.asBroadcastStream();

I added WidgetFlutterBinding.ensureInitialized() at the start of Main() as well as in the Isolate entry function . But the exception didn't go away after I did that on master and dev channels. It went away after switching to Stable channel. This was on an IOS build.

@adazh
Copy link
Contributor Author

adazh commented Sep 3, 2019

From the stack trace, the error was thrown when binaryMessenger.setMessageHandler was called within EventChannel's receiveBroadcastStream method.

@vikramkapoor Could you check where EventChannel(s) are initialized/receiveBroadcastStream is called in your code? This error should probably go away if WidgetFlutterBinding.ensureInitialized() is called beforehand.

@vikramkapoor
Copy link

@adazh
RunApp is called as first thing in my main() before receiveBroadcastStream. I had tried putting WidgetFlutterBinding.ensureInitialized() as the first line in main() before RunApp and it was still happening. This only happens on iOS and not on Android with the same code. I will investigate more a little later today and get back to this thread.

@vikramkapoor
Copy link

vikramkapoor commented Sep 6, 2019 via email

@adazh
Copy link
Contributor Author

adazh commented Sep 6, 2019

@adazh I tried calling WidgetFlutterBinding.ensureInitialized() as first thing in Main but I still get this error on iOS.  receiveBroadcastStream  is called in my code much after runApp has been called. It works fine on Android on the master channel but I had to go to stable channel on iOS to avoid this exception. Is there anything else I should investigate?  Vikram On Tuesday, September 3, 2019, 10:04:40 AM PDT, adazh notifications@github.com wrote: From the stack trace, the error was thrown when binaryMessenger.setMessageHandler was called within EventChannel's receiveBroadcastStream method. @vikramkapoor Could you see where EventChannel(s) are initialized/receiveBroadcastStream is called in your code? This error should probably go away if WidgetFlutterBinding.ensureInitialized() is called beforehand. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

I'm not aware of possible differences in bindings between Android and iOS. + @dnfield to see if he has any insight.

@dnfield
Copy link
Contributor

dnfield commented Sep 6, 2019

@vikramkapoor could you please file a new issue with a minimal reproduction for this? Feel free to tag me in it.

@vikramkapoor
Copy link

@dnfield Sure. I am working on minimal repro to file an issue

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) a: tests "flutter test", flutter_test, or one of our tests f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels. team Infra upgrades, team productivity, code health, technical debt. See also team: labels.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants