Getx: You cannot add event to closed Stream

Created on 25 Nov 2020  路  11Comments  路  Source: jonataslaw/getx

i have a issue

You cannot add event to closed Stream
'package:get/get_rx/src/rx_stream/get_stream.dart':
Failed assertion: line 90 pos 12: '!isClosed'

I just want to change the variable, but get an error like that

class ProductDetailController extends GetxController {

var textQuantityProductDetail = 0.obs;
var textfieldQuantity = TextEditingController().obs;

void setIncQuantity({value}) {
textQuantityProductDetail.value = value;
textfieldQuantity.value.text = textQuantityProductDetail.value.toString();
}

}

this error affects many functions that were previously normal,
even in other classes

Without a valid reproduction code

Most helpful comment

@muhammadsaddamnur try put your function controller in onReady() not onInit(). widget need a time for build. that's work for me

All 11 comments

Hi @muhammadsaddamnur, provide the code of your view (StatelessWidget) that uses this controller.

Hi @eduardoflorence this view of productDetail

class ProductDetail extends StatelessWidget {
  final controller = Get.put(ProductDetailController(),
      tag: Get.arguments[0]['id'], permanent: true);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Obx(
        () => controller.loadingProductDetail.value
            ? Center(
                child: CircularProgressIndicator(),
              )
            : Text('body')
      bottomNavigationBar: Obx(
        () => controller.loadingProductDetail.value
            ? SizedBox()
            : BottomAppBar(
                elevation: 10,
                child: Container(
                  height: 70,
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceAround,
                    children: [
                      Obx(
                        () => controller.productDetail.value.value == null
                            ? Expanded(
                                flex: 1,
                                child: Container(
                                    height: 40,
                                    child: IdShimmerCustom(
                                      height: 40,
                                    )),
                              )
                            : Expanded(
                                flex: 1,
                                child: ButtonWidget(
                                  isLoading: controller.loadingAddToCart.value,
                                  widget: Row(
                                    mainAxisAlignment: MainAxisAlignment.center,
                                    children: [
                                      Icon(
                                        Icons.shopping_cart,
                                        color: ColorsSetting.white,
                                      ),
                                      SizedBox(
                                        width: 5,
                                      ),
                                      TextWidget(
                                        'Buy',
                                        color: ColorsSetting.white,
                                        fontWeight: FontWeight.bold,
                                      )
                                    ],
                                  ),
                                  isEnable: controller.productDetail.value.value
                                          .productStock.isEmpty
                                      ? false
                                      : true,
                                  onTap: () {
                                    Get.bottomSheet(
                                        Container(
                                          height: MediaQuery.of(context)
                                                  .size
                                                  .height /
                                              1.2,
                                          child: ProductDetailVariant(
                                              appBar: false,
                                              tag: controller.id.toString()),
                                        ),
                                        isScrollControlled: true,
                                        shape: RoundedRectangleBorder(
                                          borderRadius: BorderRadius.only(
                                              topLeft: Radius.circular(10),
                                              topRight: Radius.circular(10)),
                                        ),
                                        clipBehavior: Clip.antiAlias);
                                  },
                                )),
                      ),
                    ],
                  ),
                )),
      ),
    );
  }
}

and this is a view of page in bottomsheet

class ProductDetailVariant extends StatelessWidget {
  final bool appBar;
  final String tag;
  ProductDetailVariant({Key key, this.appBar = true, @required this.tag})
      : super(key: key);
  @override
  Widget build(BuildContext context) {
    final ProductDetailController controller = Get.find(tag: tag);

    return Scaffold(
      resizeToAvoidBottomPadding: false,
      appBar: AppBar(
        title: TextWidget('Detail Pesanan'),
        centerTitle: true,
        elevation: 0,
        automaticallyImplyLeading: false,
        actions: [
          IconButton(
              icon: Icon(Icons.cancel_sharp),
              onPressed: () {
                Get.back();
              })
        ],
      ),
      body: Column(
        children: [
          Expanded(
            child: ListView(
              children: [
                Container(
                  color: Color(0xffF5F5F5),
                  child: Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Row(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Container(
                          height: 70,
                          width: 70,
                          color: Colors.red,
                          child: Text('ini gambar ke - '),
                        ),
                        SizedBox(
                          width: 5,
                        ),
                        Obx(() => controller.loadingProductDetail.value
                            ? CircularProgressIndicator()
                            : Flexible(
                                child: TextWidget(
                                controller
                                    .productDetail.value.value.productName,
                                maxLines: 5,
                              )))

                      ],
                    ),
                  ),
                ),

                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: TextWidget(
                    'Jumlah',
                    maxLines: 3,
                    fontWeight: FontWeight.bold,
                  ),
                ),
                Row(
                  children: [
                    ButtonIconCircleWidget(
                      icon: Icons.remove,
                      onTap: () {
                        if (controller.textQuantityProductDetail.value >
                            controller.productDetail.value.value.minimumOrder)
                          controller.setDecQuantity(
                              value: int.parse(
                                  (controller.textQuantityProductDetail.value -
                                          1)
                                      .toString()));
                      },
                    ),

                    Container(
                      width: 60,
                      child: Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: TextFieldWidget(
                          controller: controller.textfieldQuantity.value,
                          textFieldType: TextFieldType.rounded,
                          textInputType: TextInputType.number,
                          inputFormatters: <TextInputFormatter>[
                            FilteringTextInputFormatter.digitsOnly
                          ],
                          onChange: (value) {
                            controller.setQuantity(value: int.parse(value));
                          },
                        ),
                      ),
                    ),
                    ButtonIconCircleWidget(
                      icon: Icons.add,
                      onTap: () {
                        if (controller.textQuantityProductDetail.value <
                            controller
                                .productDetail
                                .value
                                .value
                                .productStock[controller.radioValue.value]
                                .publicProductInStock)
                          controller.setIncQuantity(
                              value: int.parse(
                                  (controller.textQuantityProductDetail.value +
                                          1)
                                      .toString()));
                      },
                    ),
                  ],
                )
              ],
            ),
          ),
          Obx(() => Padding(
                padding: const EdgeInsets.all(8.0),
                child: ButtonWidget(
                  widget: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Icon(
                        Icons.shopping_cart,
                        color: ColorsSetting.white,
                      ),
                      SizedBox(
                        width: 5,
                      ),
                      TextWidget(
                        'Buy',
                        color: ColorsSetting.white,
                        fontWeight: FontWeight.bold,
                      )
                    ],
                  ),
                  isEnable: controller.textQuantityProductDetail.value == 0
                      ? false
                      : controller.textQuantityProductDetail.value <=
                              controller
                                  .productDetail
                                  .value
                                  .value
                                  .productStock[controller.radioValue.value]
                                  .publicProductInStock
                          ? true
                          : false,
                  onTap: () async {
                    Get.back();
                    await controller.addToCart(
                        productId: controller.productDetail.value.value.id,
                        siteLocation: controller
                            .productDetail
                            .value
                            .value
                            .productStock[controller.radioValue.value]
                            .siteLocation
                            .supplierSiteLocationId,
                        quantity: controller.textfieldQuantity.value.text);
                  },
                ),
              ))
        ],
      ),
    );
  }
}

You must place Get.put as the first line of the build method of the ProductDetail. This is because the Flutter executes the code before the build method very quickly, even before the navigation takes place.

Before:

class ProductDetail extends StatelessWidget {
  final controller = Get.put(ProductDetailController(),
      tag: Get.arguments[0]['id'], permanent: true);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Obx(
        () => controller.loadingProductDetail.value
            ? Center(
                child: CircularProgressIndicator(),
              )
            : Text('body')
      bottomNavigationBar: Obx(
  ...

After:

class ProductDetail extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    final controller = Get.put(ProductDetailController(), tag: Get.arguments[0]['id'], permanent: true);  // Insert Here

    return Scaffold(
      body: Obx(
        () => controller.loadingProductDetail.value
            ? Center(
                child: CircularProgressIndicator(),
              )
            : Text('body')),        // Miss missing "),"
      bottomNavigationBar: Obx(
  ...

Hi @eduardoflorence i try this, but i get same error

I have the same problem:

Stateless widget:

class AccountFormPage extends StatelessWidget {
  final AccountFormPageController ctrl = Get.put(AccountFormPageController());

  @override
  Widget build(BuildContext context) { ... }
}

Controller:

class AccountFormPageController extends GetxController {
  final working = false.obs;
  ...
  Future<void> save() async {
    working(true);
    ...
    working(false); // this throws the exception
  }
  ...
}

Error:

[VERBOSE-2:ui_dart_state.cc(177)] Unhandled Exception: 'package:get/get_rx/src/rx_stream/get_stream.dart': Failed assertion: line 95 pos 12: '!isClosed': You cannot add event to closed Stream

For me it works correctly. Here's an example:

import 'package:flutter/material.dart';
import 'package:get/get.dart';

void main() {
  runApp(GetMaterialApp(home: HomePage()));
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('HOME')),
      body: Center(
        child: ElevatedButton(
          child: Text('Go to Account Page'),
          onPressed: () => Get.to(() => AccountFormPage()),
        ),
      ),
    );
  }
}

class AccountFormPage extends StatelessWidget {
  final AccountFormPageController ctrl = Get.put(AccountFormPageController());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Page2')),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Center(
            child: Obx(
              () => ctrl.working.value ?? false
                  ? CircularProgressIndicator()
                  : SizedBox(height: 16),
            ),
          ),
          ElevatedButton(onPressed: ctrl.save, child: Text('Save'))
        ],
      ),
    );
  }
}

class AccountFormPageController extends GetxController {
  final working = false.obs;

  Future<void> save() async {
    working(true);
    await 3.seconds.delay();
    working(false);
  }
}

The problem is gone after: flutter upgrade

Update: The problem appears randomly. I don't know why yet. Some Controllers just work and others don't. But all of them have the same structure.

Try to add this just after the declaration of the controller on the stateless widget:

controller.onStart();

@muhammadsaddamnur try put your function controller in onReady() not onInit(). widget need a time for build. that's work for me

i have a issue

You cannot add event to closed Stream
'package:get/get_rx/src/rx_stream/get_stream.dart':
Failed assertion: line 90 pos 12: '!isClosed'

I just want to change the variable, but get an error like that

class ProductDetailController extends GetxController {

var textQuantityProductDetail = 0.obs;
var textfieldQuantity = TextEditingController().obs;
void setIncQuantity({value}) {
textQuantityProductDetail.value = value;
textfieldQuantity.value.text = textQuantityProductDetail.value.toString();
}

}

this error affects many functions that were previously normal,
even in other classes

I found out that the issue is may be due to the observable stream getting closed or any subscriptions to it getting closed when the Getx or Obx widget that uses it is removed from the widget tree.I still didn't figured out what's the solution for it but i'll try to update it here once i get something

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aytunch picture aytunch  路  4Comments

ad-on-is picture ad-on-is  路  3Comments

NiranjanShah picture NiranjanShah  路  4Comments

wailashraf71 picture wailashraf71  路  4Comments

rupamking1 picture rupamking1  路  3Comments