From 498b1cfb9f75551f4ba94fce2b9d7fbf15312122 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Sun, 7 Jul 2019 20:04:25 -0700 Subject: [PATCH 1/6] Move calls to UI thread --- packages/firebase_database/CHANGELOG.md | 7 ++ .../database/FirebaseDatabasePlugin.java | 86 +++++++++++-------- packages/firebase_database/pubspec.yaml | 2 +- 3 files changed, 59 insertions(+), 36 deletions(-) diff --git a/packages/firebase_database/CHANGELOG.md b/packages/firebase_database/CHANGELOG.md index 38078502a07a..aeabbb92873b 100644 --- a/packages/firebase_database/CHANGELOG.md +++ b/packages/firebase_database/CHANGELOG.md @@ -1,3 +1,10 @@ +## 3.0.1 + +* Ensure that all channel calls to the Dart side from the Java side are done + on the UI thread. This change allows transactions to work with upcoming + engine changes, which require channel calls be made on the UI thread. + **Note** this is an Android only change, the iOS implementation was not impacted. + ## 3.0.0 * Update Android dependencies to latest. diff --git a/packages/firebase_database/android/src/main/java/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.java b/packages/firebase_database/android/src/main/java/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.java index 2f1f7145b9d9..af462c2c54e7 100644 --- a/packages/firebase_database/android/src/main/java/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.java +++ b/packages/firebase_database/android/src/main/java/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.java @@ -4,6 +4,7 @@ package io.flutter.plugins.firebase.database; +import android.app.Activity; import android.util.Log; import android.util.SparseArray; import com.google.android.gms.tasks.Task; @@ -37,6 +38,7 @@ public class FirebaseDatabasePlugin implements MethodCallHandler { private static final String TAG = "FirebaseDatabasePlugin"; private final MethodChannel channel; + private final Activity activity; private static final String EVENT_TYPE_CHILD_ADDED = "_EventType.childAdded"; private static final String EVENT_TYPE_CHILD_REMOVED = "_EventType.childRemoved"; private static final String EVENT_TYPE_CHILD_CHANGED = "_EventType.childChanged"; @@ -50,11 +52,12 @@ public class FirebaseDatabasePlugin implements MethodCallHandler { public static void registerWith(PluginRegistry.Registrar registrar) { final MethodChannel channel = new MethodChannel(registrar.messenger(), "plugins.flutter.io/firebase_database"); - channel.setMethodCallHandler(new FirebaseDatabasePlugin(channel)); + channel.setMethodCallHandler(new FirebaseDatabasePlugin(channel, registrar.activity())); } - private FirebaseDatabasePlugin(MethodChannel channel) { + private FirebaseDatabasePlugin(MethodChannel channel, Activity activity) { this.channel = channel; + this.activity = activity; } private DatabaseReference getReference(FirebaseDatabase database, Map arguments) { @@ -333,7 +336,7 @@ public Transaction.Result doTransaction(MutableData mutableData) { final Task> updateMutableDataTCSTask = updateMutableDataTCS.getTask(); - Map doTransactionMap = new HashMap<>(); + final Map doTransactionMap = new HashMap<>(); doTransactionMap.put("transactionKey", arguments.get("transactionKey")); final Map snapshotMap = new HashMap<>(); @@ -342,39 +345,46 @@ public Transaction.Result doTransaction(MutableData mutableData) { doTransactionMap.put("snapshot", snapshotMap); // Return snapshot to Dart side for update. - channel.invokeMethod( - "DoTransaction", - doTransactionMap, - new MethodChannel.Result() { - @Override - @SuppressWarnings("unchecked") - public void success(Object result) { - updateMutableDataTCS.setResult((Map) result); - } - - @Override - public void error( - String errorCode, String errorMessage, Object errorDetails) { - String exceptionMessage = - "Error code: " - + errorCode - + "\nError message: " - + errorMessage - + "\nError details: " - + errorDetails; - updateMutableDataTCS.setException(new Exception(exceptionMessage)); - } - - @Override - public void notImplemented() { - updateMutableDataTCS.setException( - new Exception("DoTransaction not implemented on Dart side.")); - } - }); + activity.runOnUiThread( + new Runnable() { + @Override + public void run() { + channel.invokeMethod( + "DoTransaction", + doTransactionMap, + new MethodChannel.Result() { + @Override + @SuppressWarnings("unchecked") + public void success(Object result) { + updateMutableDataTCS.setResult((Map) result); + } + + @Override + public void error( + String errorCode, String errorMessage, Object errorDetails) { + String exceptionMessage = + "Error code: " + + errorCode + + "\nError message: " + + errorMessage + + "\nError details: " + + errorDetails; + updateMutableDataTCS.setException(new Exception(exceptionMessage)); + } + + @Override + public void notImplemented() { + updateMutableDataTCS.setException( + new Exception("DoTransaction not implemented on Dart side.")); + } + }); + } + } + ); try { // Wait for updated snapshot from the Dart side. - Map updatedSnapshotMap = + final Map updatedSnapshotMap = Tasks.await( updateMutableDataTCSTask, (int) arguments.get("transactionTimeout"), @@ -394,7 +404,7 @@ public void notImplemented() { @Override public void onComplete( DatabaseError databaseError, boolean committed, DataSnapshot dataSnapshot) { - Map completionMap = new HashMap<>(); + final Map completionMap = new HashMap<>(); completionMap.put("transactionKey", arguments.get("transactionKey")); if (databaseError != null) { completionMap.put("error", asMap(databaseError)); @@ -408,7 +418,13 @@ public void onComplete( } // Invoke transaction completion on the Dart side. - result.success(completionMap); + activity.runOnUiThread( + new Runnable() { + public void run() { + result.success(completionMap); + } + } + ); } }); break; diff --git a/packages/firebase_database/pubspec.yaml b/packages/firebase_database/pubspec.yaml index 1728d09c58b8..f44db8afa38f 100755 --- a/packages/firebase_database/pubspec.yaml +++ b/packages/firebase_database/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Database, a cloud-hosted NoSQL database with realtime data syncing across Android and iOS clients, and offline access. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/firebase_database -version: 3.0.0 +version: 3.0.1 flutter: plugin: From 8dfa6769154248cc461ec3576cfd160c6100a448 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Sun, 7 Jul 2019 21:28:25 -0700 Subject: [PATCH 2/6] Tweak changelog --- packages/firebase_database/CHANGELOG.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/firebase_database/CHANGELOG.md b/packages/firebase_database/CHANGELOG.md index aeabbb92873b..cb5ca28d6b9b 100644 --- a/packages/firebase_database/CHANGELOG.md +++ b/packages/firebase_database/CHANGELOG.md @@ -1,9 +1,8 @@ ## 3.0.1 -* Ensure that all channel calls to the Dart side from the Java side are done - on the UI thread. This change allows transactions to work with upcoming - engine changes, which require channel calls be made on the UI thread. - **Note** this is an Android only change, the iOS implementation was not impacted. +* Updated transactions implementation on Android for compatibility with + newer versions of Flutter engine that require channel calls be made + on the UI thread. ## 3.0.0 From ce7c9e35647224b3abddbfcba973db7348dc01a3 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Sun, 7 Jul 2019 21:52:57 -0700 Subject: [PATCH 3/6] Fix analyzer errors --- packages/firebase_database/CHANGELOG.md | 2 ++ packages/firebase_database/test/firebase_database_test.dart | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/firebase_database/CHANGELOG.md b/packages/firebase_database/CHANGELOG.md index cb5ca28d6b9b..ce64433b0883 100644 --- a/packages/firebase_database/CHANGELOG.md +++ b/packages/firebase_database/CHANGELOG.md @@ -3,6 +3,8 @@ * Updated transactions implementation on Android for compatibility with newer versions of Flutter engine that require channel calls be made on the UI thread. +* Updated unit test to use `defaultBinaryMessenger` instead of + `BinaryMessages.handlePlatformMessage`. ## 3.0.0 diff --git a/packages/firebase_database/test/firebase_database_test.dart b/packages/firebase_database/test/firebase_database_test.dart index 9aa56f0ec19a..1c442619369d 100755 --- a/packages/firebase_database/test/firebase_database_test.dart +++ b/packages/firebase_database/test/firebase_database_test.dart @@ -38,7 +38,7 @@ void main() { Map updatedValue; Future simulateEvent( int transactionKey, final MutableData mutableData) async { - await BinaryMessages.handlePlatformMessage( + await defaultBinaryMessenger.handlePlatformMessage( channel.name, channel.codec.encodeMethodCall( MethodCall( @@ -455,7 +455,7 @@ void main() { const String errorDetails = 'Some details'; final Query query = database.reference().child('some path'); Future simulateError(String errorMessage) async { - await BinaryMessages.handlePlatformMessage( + await defaultBinaryMessenger.handlePlatformMessage( channel.name, channel.codec.encodeMethodCall( MethodCall('Error', { @@ -496,7 +496,7 @@ void main() { final String path = 'foo'; final Query query = database.reference().child(path); Future simulateEvent(String value) async { - await BinaryMessages.handlePlatformMessage( + await defaultBinaryMessenger.handlePlatformMessage( channel.name, channel.codec.encodeMethodCall( MethodCall('Event', { From 1ca6a5daf40ee39088256c52565ec69cbc882342 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 8 Jul 2019 05:57:55 -0700 Subject: [PATCH 4/6] reformat --- .../database/FirebaseDatabasePlugin.java | 81 +++++++++---------- .../firebase_database/example/lib/main.dart | 65 +++++---------- 2 files changed, 58 insertions(+), 88 deletions(-) diff --git a/packages/firebase_database/android/src/main/java/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.java b/packages/firebase_database/android/src/main/java/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.java index af462c2c54e7..c3fb751e5070 100644 --- a/packages/firebase_database/android/src/main/java/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.java +++ b/packages/firebase_database/android/src/main/java/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.java @@ -346,41 +346,41 @@ public Transaction.Result doTransaction(MutableData mutableData) { // Return snapshot to Dart side for update. activity.runOnUiThread( - new Runnable() { - @Override - public void run() { - channel.invokeMethod( - "DoTransaction", - doTransactionMap, - new MethodChannel.Result() { - @Override - @SuppressWarnings("unchecked") - public void success(Object result) { - updateMutableDataTCS.setResult((Map) result); - } - - @Override - public void error( - String errorCode, String errorMessage, Object errorDetails) { - String exceptionMessage = - "Error code: " - + errorCode - + "\nError message: " - + errorMessage - + "\nError details: " - + errorDetails; - updateMutableDataTCS.setException(new Exception(exceptionMessage)); - } - - @Override - public void notImplemented() { - updateMutableDataTCS.setException( - new Exception("DoTransaction not implemented on Dart side.")); - } - }); - } - } - ); + new Runnable() { + @Override + public void run() { + channel.invokeMethod( + "DoTransaction", + doTransactionMap, + new MethodChannel.Result() { + @Override + @SuppressWarnings("unchecked") + public void success(Object result) { + updateMutableDataTCS.setResult((Map) result); + } + + @Override + public void error( + String errorCode, String errorMessage, Object errorDetails) { + String exceptionMessage = + "Error code: " + + errorCode + + "\nError message: " + + errorMessage + + "\nError details: " + + errorDetails; + updateMutableDataTCS.setException( + new Exception(exceptionMessage)); + } + + @Override + public void notImplemented() { + updateMutableDataTCS.setException( + new Exception("DoTransaction not implemented on Dart side.")); + } + }); + } + }); try { // Wait for updated snapshot from the Dart side. @@ -419,12 +419,11 @@ public void onComplete( // Invoke transaction completion on the Dart side. activity.runOnUiThread( - new Runnable() { - public void run() { - result.success(completionMap); - } - } - ); + new Runnable() { + public void run() { + result.success(completionMap); + } + }); } }); break; diff --git a/packages/firebase_database/example/lib/main.dart b/packages/firebase_database/example/lib/main.dart index 96673e566a91..3b0b20baa553 100755 --- a/packages/firebase_database/example/lib/main.dart +++ b/packages/firebase_database/example/lib/main.dart @@ -54,42 +54,18 @@ class _MyHomePageState extends State { @override void initState() { super.initState(); - // Demonstrates configuring to the database using a file + print('connecting'); _counterRef = FirebaseDatabase.instance.reference().child('counter'); - // Demonstrates configuring the database directly - final FirebaseDatabase database = FirebaseDatabase(app: widget.app); - _messagesRef = database.reference().child('messages'); - database.reference().child('counter').once().then((DataSnapshot snapshot) { - print('Connected to second database and read ${snapshot.value}'); - }); - database.setPersistenceEnabled(true); - database.setPersistenceCacheSizeBytes(10000000); - _counterRef.keepSynced(true); - _counterSubscription = _counterRef.onValue.listen((Event event) { - setState(() { - _error = null; - _counter = event.snapshot.value ?? 0; - }); - }, onError: (Object o) { - final DatabaseError error = o; - setState(() { - _error = error; - }); - }); - _messagesSubscription = - _messagesRef.limitToLast(10).onChildAdded.listen((Event event) { - print('Child added: ${event.snapshot.value}'); - }, onError: (Object o) { - final DatabaseError error = o; - print('Error: ${error.code} ${error.message}'); + FirebaseDatabase.instance.reference().once().then((DataSnapshot snapshot) { + print('Connected to database and read ${snapshot.value}'); }); } @override void dispose() { super.dispose(); - _messagesSubscription.cancel(); - _counterSubscription.cancel(); +// _messagesSubscription.cancel(); +// _counterSubscription.cancel(); } Future _increment() async { @@ -143,27 +119,22 @@ class _MyHomePageState extends State { ), title: const Text('Anchor to bottom'), ), - Flexible( - child: FirebaseAnimatedList( - key: ValueKey(_anchorToBottom), - query: _messagesRef, - reverse: _anchorToBottom, - sort: _anchorToBottom - ? (DataSnapshot a, DataSnapshot b) => b.key.compareTo(a.key) - : null, - itemBuilder: (BuildContext context, DataSnapshot snapshot, - Animation animation, int index) { - return SizeTransition( - sizeFactor: animation, - child: Text("$index: ${snapshot.value.toString()}"), - ); - }, - ), - ), ], ), floatingActionButton: FloatingActionButton( - onPressed: _increment, + onPressed: () async { + final DatabaseReference ref = + FirebaseDatabase.instance.reference().child('counter'); + final DataSnapshot snapshot = await ref.once(); + final int value = snapshot.value ?? 0; + final TransactionResult transactionResult = + await ref.runTransaction((MutableData mutableData) async { + mutableData.value = (mutableData.value ?? 0) + 1; + return mutableData; + }); + assert(transactionResult.committed, true); + assert(transactionResult.dataSnapshot.value > value, true); + }, tooltip: 'Increment', child: const Icon(Icons.add), ), From 0511b651200ea958879cd8289d27928003bf6b18 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 8 Jul 2019 06:19:18 -0700 Subject: [PATCH 5/6] Revert changes to example --- .../firebase_database/example/lib/main.dart | 65 ++++++++++++++----- 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/packages/firebase_database/example/lib/main.dart b/packages/firebase_database/example/lib/main.dart index 3b0b20baa553..96673e566a91 100755 --- a/packages/firebase_database/example/lib/main.dart +++ b/packages/firebase_database/example/lib/main.dart @@ -54,18 +54,42 @@ class _MyHomePageState extends State { @override void initState() { super.initState(); - print('connecting'); + // Demonstrates configuring to the database using a file _counterRef = FirebaseDatabase.instance.reference().child('counter'); - FirebaseDatabase.instance.reference().once().then((DataSnapshot snapshot) { - print('Connected to database and read ${snapshot.value}'); + // Demonstrates configuring the database directly + final FirebaseDatabase database = FirebaseDatabase(app: widget.app); + _messagesRef = database.reference().child('messages'); + database.reference().child('counter').once().then((DataSnapshot snapshot) { + print('Connected to second database and read ${snapshot.value}'); + }); + database.setPersistenceEnabled(true); + database.setPersistenceCacheSizeBytes(10000000); + _counterRef.keepSynced(true); + _counterSubscription = _counterRef.onValue.listen((Event event) { + setState(() { + _error = null; + _counter = event.snapshot.value ?? 0; + }); + }, onError: (Object o) { + final DatabaseError error = o; + setState(() { + _error = error; + }); + }); + _messagesSubscription = + _messagesRef.limitToLast(10).onChildAdded.listen((Event event) { + print('Child added: ${event.snapshot.value}'); + }, onError: (Object o) { + final DatabaseError error = o; + print('Error: ${error.code} ${error.message}'); }); } @override void dispose() { super.dispose(); -// _messagesSubscription.cancel(); -// _counterSubscription.cancel(); + _messagesSubscription.cancel(); + _counterSubscription.cancel(); } Future _increment() async { @@ -119,22 +143,27 @@ class _MyHomePageState extends State { ), title: const Text('Anchor to bottom'), ), + Flexible( + child: FirebaseAnimatedList( + key: ValueKey(_anchorToBottom), + query: _messagesRef, + reverse: _anchorToBottom, + sort: _anchorToBottom + ? (DataSnapshot a, DataSnapshot b) => b.key.compareTo(a.key) + : null, + itemBuilder: (BuildContext context, DataSnapshot snapshot, + Animation animation, int index) { + return SizeTransition( + sizeFactor: animation, + child: Text("$index: ${snapshot.value.toString()}"), + ); + }, + ), + ), ], ), floatingActionButton: FloatingActionButton( - onPressed: () async { - final DatabaseReference ref = - FirebaseDatabase.instance.reference().child('counter'); - final DataSnapshot snapshot = await ref.once(); - final int value = snapshot.value ?? 0; - final TransactionResult transactionResult = - await ref.runTransaction((MutableData mutableData) async { - mutableData.value = (mutableData.value ?? 0) + 1; - return mutableData; - }); - assert(transactionResult.committed, true); - assert(transactionResult.dataSnapshot.value > value, true); - }, + onPressed: _increment, tooltip: 'Increment', child: const Icon(Icons.add), ), From 52b8e6d1a0bf35f50751e742f5dd62aeb08b087a Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 8 Jul 2019 08:38:49 -0700 Subject: [PATCH 6/6] Update packages/firebase_database/CHANGELOG.md Co-Authored-By: Chris Yang --- packages/firebase_database/CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/firebase_database/CHANGELOG.md b/packages/firebase_database/CHANGELOG.md index 934aa7957a75..0e032e4dc2d3 100644 --- a/packages/firebase_database/CHANGELOG.md +++ b/packages/firebase_database/CHANGELOG.md @@ -16,7 +16,6 @@ ## 3.0.1 * Suppress deprecation warning for BinaryMessages. See: https://github.com/flutter/flutter/issues/33446 ->>>>>>> origin/master ## 3.0.0