jonataslaw / getx

Open screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with Get.
MIT License
10.31k stars 1.61k forks source link

Computed values #1309

Closed leonardocustodio closed 3 years ago

leonardocustodio commented 3 years ago

I'm not sure if I understood how computed values work.

I thought this was supposed to work:

var isListeningRadio = false.obs;
  var playingState = ProcessingState.idle.obs;

  RadioState get radioState {
    if (isListeningRadio.isFalse) {
      return RadioState.stopped;
    } else {
      if (playingState == ProcessingState.ready.obs) {
        return RadioState.playing;
      }
      return RadioState.loading;
    }
  }

  @override
  void onInit() {
    super.onInit();
    player.playbackEventStream.listen((state) {
      playingState = state.processingState.obs;
      print(state.processingState);
    });
  }

  Future<void> switchRadio() async {
    isListeningRadio.toggle();
    if (isListeningRadio.isTrue) {
      await player.play();
    } else {
      await player.stop();
    }

And in the UI part:

Obx(() {
                var radioState = _controller.radioState;

                if (radioState == RadioState.playing) {
                  return Center(
                    child: Image.asset('lib/ui/assets/pause.png'),
                  );
                } else if (radioState == RadioState.loading) {
                  return Center(
                    child: CircularProgressIndicator(),
                  );
                }
                return Center(
                  child: Image.asset('lib/ui/assets/logoradiocap.png'),
                );
              }),

It does work when changing the isListeningRadio variable, but when the streams changes the playingState, it does not work. So basically it shows only stopped and loading but never playing.

And I can confirm that the ready state is called and the playingState is assigned as ProcessingState.ready.obs

MedwinCorreo commented 3 years ago

playingState.value ?

eduardoflorence commented 3 years ago

if (playingState.value == ProcessingState.ready) { ... playingState.value = state.processingState;

leonardocustodio commented 3 years ago

Tried:

final isListeningRadio = false.obs;
final playingState = ProcessingState.idle.obs;

  RadioState get radioState {
    if (isListeningRadio.isFalse) {
      return RadioState.stopped;
    } else {
      if (playingState.value == ProcessingState.ready) {
        return RadioState.playing;
      }
      return RadioState.loading;
    }
  }

  @override
  void onInit() {
    super.onInit();
    player.playbackEventStream.listen((state) {
      playingState.value = state.processingState;
      print(state.processingState);
    });
  }

  Future<void> switchRadio() async {
    isListeningRadio.toggle();
    if (isListeningRadio.isTrue) {
      await player.play();
    } else {
      await player.stop();
    }

Did not work as well. It only rebuilds the widget when isListeningRadio changes..... But not when playingState changes...

eduardoflorence commented 3 years ago

I did a simulation and the reactivity of isListeningRadio worked:

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: Container(
        child: ElevatedButton(
          child: Text('Go to page 2'),
          onPressed: () => Get.to(() => Page2()),
        ),
      ),
    );
  }
}

class Page2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final _controller = Get.put(Page2Controller());
    return Scaffold(
      appBar: AppBar(title: Text('Page2')),
      body: Obx(
        () {
          var radioState = _controller.radioState;

          if (radioState == RadioState.playing) {
            return Center(
              child: ElevatedButton(
                child: Text('Pause'),
                onPressed: () {},
              ),
            );
          } else if (radioState == RadioState.loading) {
            return Center(
              child: CircularProgressIndicator(),
            );
          }
          return Center(
            child: Text('LogoRadio'),
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _controller.switchRadio,
        child: Icon(Icons.power),
      ),
    );
  }
}

enum RadioState { stopped, loading, playing }

enum ProcessingState { idle, ready }

class Page2Controller extends GetxController {
  final isListeningRadio = false.obs;
  final playingState = ProcessingState.idle.obs;

  RadioState get radioState {
    if (isListeningRadio.isFalse) {
      return RadioState.stopped;
    } else {
      if (playingState.value == ProcessingState.ready) {
        return RadioState.playing;
      }
      return RadioState.loading;
    }
  }

  @override
  void onInit() {
    super.onInit();
    /* player.playbackEventStream.listen((state) {
      playingState.value = state.processingState;
      print(state.processingState);
    }); */
    Future.delayed(Duration(seconds: 10))
        .then((_) => playingState.value = ProcessingState.ready);
  }

  Future<void> switchRadio() async {
    isListeningRadio.toggle();
    if (isListeningRadio.isTrue) {
      // await player.play();
    } else {
      // await player.stop();
    }
  }
}
leonardocustodio commented 3 years ago

Not sure why it didn't work but I used "ever" to make that and it worked fine. I'm closing the issue thanks a lot guys.

happy-little-one commented 2 years ago

I do nothing , just declare another variable which is compted from it, it works fine.

you can see it at https://github.com/happy-little-one/flutter-ddd-architecture .