0

I'm trying to get data every 30 seconds but I don't understand how to do it. There is no problem with the Getx controller file I created. I am able to pull the data but it is not refreshing.

This is my controller:

class AllCoinController extends GetxController {
  var coinList = [].obs;
  var coinCounter = 0.obs;

 Future callAllCoins() async {
    try {
      final response = await http.get(url);

      if (response.statusCode == 200) {
        List<dynamic> values = [];
        values = allCoinsFromJson(response.body);
        coinCounter.value = values.length;

        if (values.length > 0) {
          for (int i = 0; i < values.length; i++) {
            if (values[i] != null) {
              coinList.add(values[i]);
            }
          }
        }
        return coinList;
      } else {
        print(response.statusCode);
      }
    } catch (e) {
      print(e.toString());
    }
  }

  @override
  void onInit() {
    callAllCoins();
    Timer.periodic(Duration(seconds: 30), (timer) => callAllCoins());
    super.onInit();
  }
}

And my Homepage:

    class HomePage extends StatelessWidget {
  final AllCoinController allCoinController = Get.put(AllCoinController());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Obx(
        () => ListView.builder(
          scrollDirection: Axis.vertical,
          itemCount: allCoinController.coinCounter.value,
          itemBuilder: (context, index) {
            return Container(
              width: 150,
              child: Row(
                children: [
                  SizedBox(
                    width: 50,
                    height: 50,
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Image.network(
                          allCoinController.coinList[index].image),
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Text(allCoinController.coinList[index].name),
                  ),
                  Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Text(allCoinController.coinList[index].symbol),
                  ),
                  Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Obx(
                      () => Text(allCoinController.coinList[index].currentPrice
                          .toString()),
                    ),
                  ),
                ],
              ),
            );
          },
        ),
      ),
    );
  }
}

There is no problem with the codes, the only problem is the timer is not working.

regenin
  • 291
  • 9
  • 18

2 Answers2

2

I think your controller has some problem. For example you are manually prepending values on the list by looping. You could simply use coinList.assignAll(values) after the REST call without writing all of the manual codes. One of the benefits the assignAll() method gives is that it notifies the changes. So therefore you don't need the coinCounter variable and you could just simply do:

... 
values = allCoinsFromJson(response.body);
coinList.assignAll(values);
...

And on ListView.builder use itemCount: allCoinController.coinList.length

S. M. JAHANGIR
  • 4,324
  • 1
  • 10
  • 30
  • Thank you very much it works but i have a question. What exactly "assignAll" does do? For example, can we use it in an application where the data does not need to be constantly updated. – regenin Jun 25 '21 at 21:22
  • `assignAll` simply replaces existing values in a `RxList<>` with the new iterable values. Where `addAll` simply appends new iterable value at the end of the existing one. You can use `assignAll` with `RxList` regardless whether data needs to be updated or not. But using Rx in that scenario is kind of overkill. Because the default behavior of Rx is to notify about the observers of any change, regardless of adding, replacing, deleting. So if your data doesn't change, don't use Rx. It has costs. – S. M. JAHANGIR Jun 26 '21 at 05:01
  • Thank you very much for the information. I think I can balance this situation by get data every 5 minutes using a timer. – regenin Jun 26 '21 at 18:31
1

The code you posted prepends new values to the list every 30 seconds, but count doesn't get increased. In order to show these new values, you either have to increase count with the number of nem items or replace existing values in the list (empty it before you add)

Also, take a note that the following code calls callAllCoins() twice on init.

@override
  void onInit() {
    callAllCoins(); // This should be removed
    Timer.periodic(Duration(seconds: 30), (timer) => callAllCoins()); // This is called right in this line, then every 30 sec.
    super.onInit();
  }

I provide you a basic example below about whats in my mind.

import 'dart:async';

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  final controller = Get.put(MyAppController());

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Container(
        child: Obx(() {
          print(controller.counter);
          return ListView.builder(
            itemBuilder: (context, index) => Text(controller.list[index]),
            itemCount: controller.counter.value,
          );
        }),
      ),
    );
  }
}

class MyAppController extends GetxController {
  var list = [].obs;
  var counter = 0.obs;

  callIncrement() {
    list.add('->');
    counter.value += 1;
  }

  @override
  void onInit() {
    Timer.periodic(Duration(seconds: 1), (_) => callIncrement());
    super.onInit();
  }
}

  • Thank you so much for answer. I just started using Getx. I don't understand exactly what to do. The timer was working correctly when I did it without using getx. Do you think I should use a state management. – regenin Jun 24 '21 at 20:44
  • You're question was not really about GetX or Flutter. Some algorithmical thinking instead. Keep on the good work and you will improve in these things :) I really like GetX, its an advanced state management library and so much more. – Patrik Szabó Jun 24 '21 at 20:48
  • https://medium.com/flutter-community/the-flutter-getx-ecosystem-state-management-881c7235511d I recomment you this article, this was the first one I read when decided to experiment some with GetX – Patrik Szabó Jun 24 '21 at 20:50
  • Thank you of course i will read but i mean here is different situaiton. Example i add this code line: floatingActionButton: FloatingActionButton( child: Icon(Icons.refresh), onPressed: () { allCoinController.callAllCoins(); }, ), But still doesn't work. Because i use stateles widget but, Shouldn't it work when using getx? – regenin Jun 24 '21 at 21:09
  • GetX does all the state things for you. I'm only guessing now, but you should wrap that FAB with Obx(). Furthermore, consider using GetX(builder: (controller) => WidgetTree()) format. Using GetX results in a much clearer code. – Patrik Szabó Jun 25 '21 at 07:25