-
Notifications
You must be signed in to change notification settings - Fork 4k
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
[firebase_core] Add platform interface #1324
[firebase_core] Add platform interface #1324
Conversation
/cc @ditman |
Just merged in the latest Android lifecycle dependency change. PTAL and I will start on migrating |
For context:
|
Friendly ping. This is a pre-req for landing Web support for |
packages/firebase_core/firebase_core_platform_interface/README.md
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but I'm not the owner so let's wait for their approval. All my comments are minor nits/typos so feel free to disregard.
packages/firebase_core/firebase_core_platform_interface/README.md
Outdated
Show resolved
Hide resolved
...ges/firebase_core/firebase_core_platform_interface/lib/firebase_core_platform_interface.dart
Show resolved
Hide resolved
packages/firebase_core/firebase_core_platform_interface/lib/src/firebase_app_data.dart
Outdated
Show resolved
Hide resolved
packages/firebase_core/firebase_core_platform_interface/lib/src/firebase_options.dart
Show resolved
Hide resolved
...ges/firebase_core/firebase_core_platform_interface/lib/src/method_channel_firebase_core.dart
Outdated
Show resolved
Hide resolved
...s/firebase_core/firebase_core_platform_interface/test/method_channel_firebase_core_test.dart
Show resolved
Hide resolved
import 'firebase_options.dart'; | ||
|
||
/// A data class storing the name and options of a Firebase app. | ||
class FirebaseAppData { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This relates to #1392 which @kroikie just landed.
Generally in Flutterfire we try to match the native Firebase APIs as closely as we can while remaining idiomatic to the target platform. There's no equivalent to the FirebaseAppData class in the native Firebase API. There's just FirebaseApp
and our Dart version of it exposes a Future<FirebaseOptions> options
getter.
The reason why we put an asynchronous options
on firebase_core's FirebaseApp
is that we wanted the developer to be able to say FirebaseApp.instance
and start using that app
immediately without calling await
.
It seems odd, although not necessarily wrong to have a class FirebaseOptions
that matches the naming in the app-facing API exactly and is designed to be exported, but then have another class FirebaseAppData
that serves a similar function to FirebaseApp
but has a slightly different class behavior and can't be exported. It seems that the main difference is that FirebaseOptions
is a pure data class whereas FirebaseApp
has some behavior.
It seems like for every class we have the following options. All of them avoid exposing nonstandard classes (FirebaseAppData
) to the end developer.
- We could write the platform interface class in a way that can be exported and reused (so firebase_core and firebase_core_platform_interface share both the same class). This approach would match what's going on with
FirebaseOptions
but makes it harder to make breaking changes in firebase_core because they might also break firebase_core_platform_interface. - Use Dart namespaces to disambiguate app-facing classes and platform interface classes, e.g. having a class called
FirebaseApp
but don't require it to match firebase_core'sFirebaseApp
. The same could apply toFirebaseOptions
. It could be confusing to have two identically named classes that are subtly different, but it makes it clear that both classes refer to the same native SDK concept on different layers. One of them could extend the other without polluting public API with classes that don't have a native SDK equivalent. - We can have the platform interface class names be visually distinguishable from the class name in the the app-facing package (e.g.
FirebaseAppData
orPlatformFirebaseApp
). This might make make the code more readable within the app-facing package because it's obvious that the class is a more primitive representation of an app-facing class. However, it isn't possible to extend the platform class without exposing a platform implementation base class to the end developer.
Right now you're doing Option 1 for FirebaseOptions
and Option 3 for FirebaseApp
. Starting off with Option 1 and then moving to Option 2 or 3 later is possible, although here it would force the platform interface to use the same asynchronous API for options.
Here's a sketch of what it might look like to do option 3 with FirebaseApp
(i.e. PlatformFirebaseApp
instead of FirebaseAppData
).
export 'firebase_core_platform_implementation.dart' show FirebaseOptions;
class FirebaseApp {
static Map<String, FirebaseApp> _apps = <String, FirebaseApp>{};
/// Retrieves a [FirebaseApp] that was previously configured using [configure].
///
/// If no name is provided, the default is used.
factory FirebaseApp.instanceFor({ String name }) {
if (name == null) {
return FirebaseApp.instance;
}
String app = _apps[name];
assert(app != null);
return app;
}
/// Returns the default (first initialized) instance of the FirebaseApp.
static final FirebaseApp instance = FirebaseApp(name: defaultAppName);
@visibleForTesting
FirebaseApp({ @required String this.name });
/// The name of this Firebase app.
final String name;
/// The options that this app was configured with.
Future<FirebaseOptions> get options {
PlatformFirebaseApp platformApp = await FirebaseCorePlatform.instance.appNamed(name);
return platformApp.options;
}
/// Configures the app named [name] with the given [options].
///
/// Returns a previously configured app if there is one.
/// Reconfiguring an app is not supported.
static Future<FirebaseApp> configure({
@required String name,
@required FirebaseOptions options,
}) async {
if (options != null) {
await FirebaseCorePlatform.instance.configure(name, options);
}
PlatformFirebaseApp platformApp = await FirebaseCorePlatform.instance.appNamed(name);
FirebaseApp app = FirebaseApp._(platformApp);
_apps[name] = app;
return app;
}
}
In the platform interface:
class PlatformFirebaseApp {
PlatformFirebaseApp(this.name, this.options);
/// The name of this Firebase app.
final String name;
/// The options that this app was configured with.
final FirebaseOptions options;
@override
bool operator ==(dynamic other) {
if (identical(this, other)) return true;
if (other is! FirebaseAppData) return false;
return other.name == name && other.options == options;
}
@override
int get hashCode => hash2(name, options);
@override
String toString() => '$FirebaseApp($name)';
}
abstract class FirebaseCorePlatform {
/// Returns the data for the Firebase app with the given [name].
///
/// If there is no such app, returns null.
Future<FirebaseApp> appNamed(String name);
/// Configures the app named [name] with the given [options].
Future<FirebaseApp> configure(String name, FirebaseOptions options);
}
Also add documentation clarifying the distinction.
I renamed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, you'll want to fix the formatting issue here:
https://github.com/FirebaseExtended/flutterfire/runs/300074657
Merging the latest master will get you #1404 which should fix the other build failure.
Thanks, @ditman. I'm pretty sure that's what I'm seeing here. I'll make a PR that applies that change to FlutterFire |
Everything was green and approved, so I merged this! |
(I've also added @hterkelsen as collaborator of the repo, @collinjackson) |
* bump core version to 0.4.1+4 (firebase#1395) * Remove deprecated firebase-core dependency (firebase#1417) * Remove deprecated firebase-core dependency * [firebase_auth] getIdToken use actual refresh value instead of checking if object exists (firebase#1334) * getIdToken use actual refresh value instead of checking if object exists * getIdToken refresh integration test * update xcode to v11 (firebase#1420) * Update FirebaseApp creation in tests (firebase#1406) * [firebase_database] Support v2 android embedder. (firebase#287) * [firebase_remote_config] Support v2 android embedder. (firebase#282) * [CI] Add version to example apps (firebase#1426) * Add hardcode version to example apps * [firebase_core] Add platform interface (firebase#1324) * Move firebase_core to firebase_core/firebase_core * Add firebase_core_platform_interface package * Update cirrus scripts and documentation * [firebase_dynamic_links] Add support of expanding from short links (firebase#1381) * Fixes strict compilation errors. (firebase#1331) * Upgrade crashlytics to v2 plugin API (firebase#1370) * Upgraded Crashlytics to v2 of Flutter Plugins. * Format documentation lists (See also & Errors) correctly (firebase#298) Fix documentation list format. * [firebase_auth] Fix NoSuchMethodError exception in `reauthenticateWithCredential` (firebase#237) * [firebase_auth] Fix NoSuchMethodError exception Fix NoSuchMethodError exception when calling FirebaseUser.reauthenticateWithCredential * add integration test * Fix analyzer warnings Co-Authored-By: Collin Jackson <jackson@google.com> * [cloud_firestore] [firebase_performance] fix analyzer warnings (firebase#1453) * fix analyzer warnings * [CI] Skip flaky firebase_performance driver tests (firebase#1452) * Skip flaky firebase_performance driver tests * [firebase_auth] Added missing Exception to the reauthenticateWithCredential docs (firebase#1448) (firebase#1449) * Added missing Exception to the reauthenticateWithCredential docs (firebase#1448) * [firebase_remote_config] Bumps Android Firebase dependency to 19.0.3 (firebase#1443) * Bump AGP, Gradle & Google Services Plugin * Bumps dependency to Firebase Config 19.0.3 * Replaces a deprecated method usage with the updated version * [firebase_messaging] Use UNUserNotificationCenter for ios 10+ (firebase#121) * Use UNUserNotificationCenter for ios 10+ * Add swift documentation * Move http test to README * Update CONTRIBUTING.md (firebase#1473) Removes obsolete recommendations about removing mockito (which is now used in testing federated plugins). * [firebase_core] Migrate to platform_interface (firebase#1472) * [firebase_messaging] Add an ArgumentError when passing invalid background message (firebase#252) * [firebase_dynamic_links] support v2 embedding (firebase#1372) * [cloud_firestore] Fix test that used FirebaseApp.channel (firebase#1476) * [cloud_firestore] Fix test that used FirebaseApp.channel * dartfmt * bump version * Fixed dynamic issue * Fixed dynamic issue * FIxed Object to list of object mapping * Fixed text result expectation * Reverted some changes * Satisfying formatter * Added android x to pass the test * Fixed changed log auto formatting
Description
Adds a platform interface for
firebase_core
.NOTE: This contains a copy of
FirebaseOptions
. In a follow-up CL which migratesfirebase_core
to use this platform interface, I will deleteFirebaseOptions
frompackage:firebase_core
and export it fromfirebase_core
. I moved it here because the platform interface should be typed, and prefer to not useMap
for data.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.///
).flutter analyze
) does not report any problems on my PR.Breaking Change
Does your PR require plugin users to manually update their apps to accommodate your change?