flutterfire icon indicating copy to clipboard operation
flutterfire copied to clipboard

🐛 [firebase_database] Listener overwritten by .get()

Open proczak1 opened this issue 3 years ago • 9 comments
trafficstars

Bug report

Describe the bug When i do: REFERENCE.orderByKey().startAt(...).endAt(...) to listen to changes (onAdded, onChanged, onRemoved) it is working fine, unless i make another request for the same database REFERENCE like: REFERENCE.orderByKey().startAt(...).endAt(...).get() with let's say smaller range. Then first listener show results for range from .GET()

Steps to reproduce

Steps to reproduce the behavior:

  1. Start listeners (onAdded, change, removed) for REFERENCE.orderByKey().startAt(START).endAt(END)
  2. Get data from database with: REFERENCE..orderByKey().startAt(START2).endAt(END2) (with smaller range than above)
  3. Listeners starts showing data from START2 to END2

Expected behavior

Listener should show data from START to END

Sample project

Database items: ref/items (key, value): (1,1), (2,2), (10,10), (31, 31) onPressed: (){ Query query = FirebaseDatabase.instance.ref().child('items').orderByKey().startAt('1').endAt('31'); query.onChildAdded.listen((event) { print('added ${event.snapshot.key}'); }); FirebaseDatabase.instance.ref().child('items').orderByKey().startAt('10').endAt('20').get(); }

Console output: I/flutter ( 8219): added 10


Additional context

Add any other context about the problem here.


Flutter doctor

Run flutter doctor and paste the output below:

Click To Expand
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 3.0.5, on Microsoft Windows [Version 10.0.22000.795], locale pl-PL)
[√] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
[√] Chrome - develop for the web
[√] Visual Studio - develop for Windows (Visual Studio Community 2022 17.1.6)
[√] Android Studio (version 2020.3)
[√] Android Studio (version 2021.2)
[√] VS Code (version 1.69.2)
[√] Connected device (4 available)
[√] HTTP Host Availability

• No issues found!


Flutter dependencies

Run flutter pub deps -- --style=compact and paste the output below:

Click To Expand
 firebase_auth: ^3.4.1
  firebase_analytics: ^9.1.12
  firebase_database: ^9.0.18
  firebase_messaging: ^11.4.4
  firebase_storage: ^10.3.1
  firebase_core: ^1.19.1
  google_mobile_ads: ^1.3.0
  firebase_crashlytics: ^2.8.4
  firebase_dynamic_links: ^4.3.1
  cloud_functions: ^3.3.3

proczak1 avatar Jul 20 '22 06:07 proczak1

@proczak1 You didn't fill the issue template completely, so we can't properly debug the behavior you are reporting. Please provide flutter doctor -v, plugin version, a complete minimal reproducible code sample along with actual vs expected behavior.

Thanks.

darshankawar avatar Jul 20 '22 11:07 darshankawar

Sorry for that. Fixed

proczak1 avatar Jul 22 '22 07:07 proczak1

a complete minimal reproducible code sample along with actual vs expected behavior.

Also please provide this.

darshankawar avatar Jul 22 '22 08:07 darshankawar

Done

proczak1 avatar Jul 22 '22 11:07 proczak1

Thanks for the update and sorry for coming back late on this. Is this happening on mobile (android, ios specifically) or on web ? Also, if you try once() instead of get(), do you get expected behavior ?

darshankawar avatar Jul 26 '22 11:07 darshankawar

Android and iOS. Didn't test web With once result is proper

wt., 26 lip 2022, 13:51 użytkownik darshankawar @.***> napisał:

Thanks for the update and sorry for coming back late on this. Is this happening on mobile (android, ios specifically) or on web ? Also, if you try once() instead of get(), do you get expected behavior ?

— Reply to this email directly, view it on GitHub https://github.com/firebase/flutterfire/issues/9158#issuecomment-1195381990, or unsubscribe https://github.com/notifications/unsubscribe-auth/ATQCCYVAOFS6DRCKSWLEQTDVV7GK5ANCNFSM54CNUWUQ . You are receiving this because you were mentioned.Message ID: @.***>

proczak1 avatar Jul 26 '22 13:07 proczak1

Can you try below code sample wherein onValue listener is getting called after reading data using get() and see if using it, you see correct behavior ?

code sample

// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';

import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/foundation.dart' show defaultTargetPlatform, kIsWeb;
import 'package:flutter/material.dart';

import 'firebase_options.dart';

// Change to false to use live database instance.
const USE_DATABASE_EMULATOR = false;
// The port we've set the Firebase Database emulator to run on via the
// `firebase.json` configuration file.
const emulatorPort = 9000;
// Android device emulators consider localhost of the host machine as 10.0.2.2
// so let's use that if running on Android.
final emulatorHost =
    (!kIsWeb && defaultTargetPlatform == TargetPlatform.android)
        ? '10.0.2.2'
        : 'localhost';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  if (USE_DATABASE_EMULATOR) {
    FirebaseDatabase.instance.useDatabaseEmulator(emulatorHost, emulatorPort);
  }

  runApp(
    const MaterialApp(
      title: 'Flutter Database Example',
      home: MyHomePage(),
    ),
  );
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  late DatabaseReference _counterRef;
  late DatabaseReference _messagesRef;
  late StreamSubscription<DatabaseEvent> _counterSubscription;
  late StreamSubscription<DatabaseEvent> _messagesSubscription;

  String _kTestKey = 'Hello';
  String _kTestValue = 'world!';
  FirebaseException? _error;
  bool initialized = false;

  @override
  void initState() {
    init();
    super.initState();
  }

  Future<void> init() async {
    _counterRef = FirebaseDatabase.instance.ref('counter');

    final database = FirebaseDatabase.instance;

    _messagesRef = database.ref('messages');

    database.setLoggingEnabled(false);

    if (!kIsWeb) {
      database.setPersistenceEnabled(true);
      database.setPersistenceCacheSizeBytes(10000000);
    }

    if (!kIsWeb) {
      await _counterRef.keepSynced(true);
    }

    setState(() {
      initialized = true;
    });

    try {
      final counterSnapshot = await _counterRef.get();

      print(
        'Connected to directly configured database and read '
        '${counterSnapshot.value}',
      );
    } catch (err) {
      print(err);
    }

    _counterSubscription = _counterRef.onValue.listen(
      (DatabaseEvent event) {
        setState(() {
          _error = null;
          _counter = (event.snapshot.value ?? 0) as int;
        });
      },
      onError: (Object o) {
        final error = o as FirebaseException;
        setState(() {
          _error = error;
        });
      },
    );

    // made changes here compared to the firebase_database example code
    final messagesQuery = _messagesRef.orderByChild(_kTestKey).limitToFirst(10);

    _messagesSubscription = messagesQuery.onValue.listen(
      (DatabaseEvent event) {
        print('onValue called : ${event.snapshot.children.length}');
      },
      onError: (Object o) {
        final error = o as FirebaseException;
        print('Error: ${error.code} ${error.message}');
      },
    );
  }

  @override
  void dispose() {
    super.dispose();
    _messagesSubscription.cancel();
    _counterSubscription.cancel();
  }

  Future<void> _increment() async {
    await _counterRef.set(ServerValue.increment(1));

    await _messagesRef
        .push()
        .set(<String, String>{_kTestKey: '$_kTestValue $_counter'});
  }

  @override
  Widget build(BuildContext context) {
    if (!initialized) return Container();

    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter Database Example'),
      ),
      body: Column(
        children: [
          Flexible(
            child: Center(
              child: _error == null
                  ? Text(
                      'Button tapped $_counter time${_counter == 1 ? '' : 's'}.\n\n'
                      'This includes all devices, ever.',
                    )
                  : Text(
                      'Error retrieving button tap count:\n${_error!.message}',
                    ),
            ),
          ),
          // made changes here compared to the firebase_database example code
          ElevatedButton(
            onPressed: () {
              print('called >>>>>> get single data');
              _messagesRef.orderByChild(_kTestKey).limitToFirst(1).get();
            },
            child: const Text('get single data'),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _increment,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

You might need to modify this code per your case.

darshankawar avatar Jul 27 '22 08:07 darshankawar

After 10 messages i still get notified with: onValue called : 10

proczak1 avatar Jul 27 '22 11:07 proczak1

Thanks for the update. Using the code sample provided earlier, I see same behavior as reported, but I am not completely sure if this is expected behavior or a potential bug with how get() retrieves the data. Also, the fact that using once(), it works as expected.

May be a related issue on how get() retrieves the data, which may be related to the api itself:

https://github.com/firebase/flutterfire/issues/9067

darshankawar avatar Jul 28 '22 09:07 darshankawar

Any update on this? Once is not an option as its result is just from cache. .get() every time crushes listener. Makes no sense...

proczak1 avatar Sep 06 '22 13:09 proczak1

It also seems like this happens ONLY if listener has both startAt and endAt

proczak1 avatar Sep 06 '22 13:09 proczak1

Hi, I'm a maintainer on the RTDB JS SDK team and it should have been resolved in a previous version. Can you please try upgrading flutterfire?

maneesht avatar Nov 02 '22 19:11 maneesht

@proczak1 - is this still occurring on native platforms?

russellwheatley avatar May 24 '23 15:05 russellwheatley

Hey @proczak1. We need more information to resolve this issue but there hasn't been an update in 7 weekdays. I'm marking the issue as stale and if there are no new updates in the next 7 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

google-oss-bot avatar Nov 29 '23 02:11 google-oss-bot

Since there haven't been any recent updates here, I am going to close this issue.

@proczak1 if you're still experiencing this problem and want to continue the discussion just leave a comment here and we are happy to re-open this.

google-oss-bot avatar Dec 08 '23 02:12 google-oss-bot