0
IOWebSocketChannel? ioChannel;
List<CustomRunners>? oldData = [];
List<CustomRunners>? newData = [];
void getSocket(){
    ioChannel = IOWebSocketChannel.connect(
      Uri.parse(
          'wss://xxx.xyz/port=${widget.port}/?logged=true&source=0'),
      headers: {
        'Origin': 'https://abc.io',
      },
    );

    ioChannel?.stream.listen((message) {
      final data = jsonDecode(message);

        if (data[0] != null) {
          final match = SocketModel.fromJson(data[0]);

          newData!.clear();
          for (var item in match.runners!) {
            var obj = CustomRunners(
                marketId: match.marketId,
                runnerName: item.runnerName,
                selectionId: item.selectionId,
                status: item.status,
                exchangePrices: item.exchangePrices,
                lastPriceTraded: item.lastPriceTraded,
                totalMatched: item.totalMatched);

            newData?.add(obj);
          }
          if (newData!.isNotEmpty) {
            oldData!.clear();
            setState(() {
              oldData?.addAll(newData!);
            });
          }
        }
    });
  }
                SizedBox(
                  height: 150,
                  width: MediaQuery.of(context).size.width,
                  child: ListView.builder(
                    physics: NeverScrollableScrollPhysics(),
                    itemCount: newData.length,
                    itemBuilder: (context, index) {
                      var obj = newData[index];
                      var obj2 = oldData[index];

                      if (obj.exchangePrices!.availableToBack!.length == 0 ||
                          obj.exchangePrices!.availableToBack![0].size ==
                              null ||
                          obj2.exchangePrices!.availableToBack![0].size ==
                              null) {
                        back = Color(0xff72bbef);
                      } else {
                        var newAvailSize =
                            obj.exchangePrices!.availableToBack![0].size!;
                        var oldAvailSize =
                            obj2.exchangePrices!.availableToBack![0].size!;

                        if (newAvailSize > oldAvailSize) {
                          back = Color(0xff00FFFF);
                        } else if (newAvailSize < oldAvailSize) {
                          back = Colors.yellowAccent;
                          print(
                              "get  yellowwwwww $newAvailSize and $oldAvailSize");
                        } else if (newAvailSize == oldAvailSize) {
                          back = Color(0xff72bbef);
                        }
                      }
                      }

                      return Row(
                        children: [
                          Expanded(
                            flex: 2,
                            child: AnimatedContainer(
                                duration: Duration(
                                    milliseconds: 50), // animation duration
                                curve: Curves.ease, //
                                height: 50,
                                decoration: BoxDecoration(
                                    color: back,
                                    border: Border(
                                        top: BorderSide(
                                            width: 0.2, color: Colors.black),
                                        bottom: BorderSide(
                                            width: 0.2, color: Colors.black))),
                                child: Text(obj.exchangePrices!.availableToBack![0]
                                        .price
                                        .toString())
                              ),
                          ),
                        ],
                      );
                    },
                  ),
                ),

I have two array oldData and newData. This array getting data from web socket and these data refreshing continuously.I'm trying to change color of container if newData array is greater than oldData array then color will be blue and if newData array is less than oldData array then color will be red else color will be white.I have written the code but unable to get exact output.

This is a code which i have written to change the color of container but color is not changing if i'm clearing the oldData array.In both array getting same data after clearing oldData array.

Can someone help me with this.

Tintin V
  • 23
  • 4
  • when you change the variable of 'back' you need to put it in a setState to rebuild the ui and see the changes – Texv Apr 21 '23 at 04:55
  • i tried that but not worked – Tintin V Apr 21 '23 at 05:07
  • try doing the length comparison and assign color inside your getSocket() function after setting the new oldData (oldData?.addAll(newData!);) – Texv Apr 21 '23 at 05:15
  • i didn't understand exactly. – Tintin V Apr 21 '23 at 05:17
  • actually, can you print the length of both lists and tell us the printed log output? I feel like your old and new list is always the same length, because you are clearing oldData and re-defining it so its always same as newlist – Texv Apr 21 '23 at 05:24
  • yes after clearing oldData both array having same length – Tintin V Apr 21 '23 at 05:26
  • thats why the color is not changing, because they'e always the same length. From what i understand in your question is that you are not seeing color changes? – Texv Apr 21 '23 at 05:32
  • yes this is the problem im getting and i need to clear oldData to assign a newData array data. – Tintin V Apr 21 '23 at 05:34
  • im confused exactly where should i clear the oldData – Tintin V Apr 21 '23 at 05:40

4 Answers4

0

To achieve colour changes you have to set value notifier which notifies that value changes & rebuild only that particular widget,

First declare your back variable like this,

ValueNotifier<Color> back = ValueNotifier<Color>(Colors.white);

where you update back value write this,

if (newAvailSize > oldAvailSize) {

       back.value = Color(0xff00FFFF);
         back.notifyListeners();

} 
else if (newAvailSize < oldAvailSize) {
                          
        back.value = Colors.yellowAccent;
        back.notifyListeners();
      print("get  yellowwwwww $newAvailSize and $oldAvailSize");

 } else if (newAvailSize == oldAvailSize) {

      back.value = Color(0xff72bbef);
        back.notifyListeners();
}

In your return function set ValueListenableBuilder

ValueListenableBuilder(
    valueListenable: back,
    builder: (context, backValue, child) {
      return Row(
        children: [
          Expanded(
            flex: 2,
            child: AnimatedContainer(
                duration: Duration(
                    milliseconds: 50), // animation duration
                curve: Curves.ease, //
                height: 50,
                decoration: BoxDecoration(
                    color: backValue,
                    border: Border(
                        top: BorderSide(
                            width: 0.2, color: Colors.black),
                        bottom: BorderSide(
                            width: 0.2, color: Colors.black))),
                child: Text(obj.exchangePrices!.availableToBack![0]
                    .price
                    .toString())
            ),
          ),
        ],
      );
    }
)
Dharini
  • 700
  • 7
  • 20
  • i have tried with this code but color is not changing in both array getting same data so its checking always else if (newAvailSize == oldAvailSize) this condition – Tintin V Apr 21 '23 at 05:10
0

Both of your arrays newData and oldData will always be the same length because you are clearing oldData and adding newData into it every time it receive a new item, so you will never see changes in color because they're always the same length.

Can you try to make a new instance of list instead? so in your getSocket() instead of

if (newData!.isNotEmpty) {
  oldData!.clear();
  setState(() {
    oldData?.addAll(newData!);
  });
}

try this:

if (newData!.isNotEmpty) {
  setState(() {
    oldData = List<CustomRunners>.from(newData!); 
  });
}

Also maybe move the color comparison out of the listview.builder? because you're doing a comparison for every item in the list. you might wanna label it outside instead. Heres an example using switch case method:

Color back(double? newValue, double? oldValue) {
  if (newValue == null || oldValue == null) {
    return Color();
  }

  switch (newValue.compareTo(oldValue)) {
    case > 0:
      return Color();
    case < 0:
      return Color();
    case 0:
      return Color();
    default:
      return Color();
  }
}

so in listview.builder:

var back = getColor(
        obj.exchangePrices?.availableToBack?.first.size,
        obj2.exchangePrices?.availableToBack?.first.size,
      );
Texv
  • 1,225
  • 10
  • 14
0

It’s like whenever newdata comes last newdata you want to set in old data array so you have to first replace your oldData with current newData then after clear newData & add new records

set oldData before clearing newData

if (newData!.isNotEmpty) {
            oldData!.clear();
            setState(() {
              oldData?.addAll(newData!);
            });
          }

newData!.clear();

…..
Dharini
  • 700
  • 7
  • 20
  • after this getting error in log. ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════ The following IndexError was thrown building: RangeError (index): Index out of range: no indices are valid: 0 When the exception was thrown, this was the stack: – Tintin V Apr 21 '23 at 08:06
  • because your logic goes wrong here var obj = newData[index]; var obj2 = oldData[index]; newData is not same as oldData so the index many not be exist in oldData & if you want to compare your values then not use index use some of your array elements unique id – Dharini Apr 21 '23 at 12:09
  • this error comes when im refreshing page and after back page to current page – Tintin V Apr 22 '23 at 03:40
  • this error getting when page load first time – Tintin V Apr 22 '23 at 04:02
  • you’ve to put condition for empty array or check whether index is exist then only execute your logic – Dharini Apr 22 '23 at 07:10
  • exactly where should i check – Tintin V Apr 22 '23 at 07:14
  • When page initialise which first executed & if there is no data then put loader. You can find exactly on which line getting error from logs over there print your array length so you can find where exactly issue is – Dharini Apr 22 '23 at 07:20
  • hey i have i one more question can you please check once https://stackoverflow.com/questions/76107404/bad-state-the-backgroundisolatebinarymessenger-instance-value-is-invalid-until – Tintin V Apr 26 '23 at 05:53
0

try this line of code in Container:

color: (newData.length > oldData.length) ? Colors.blue : (newData.length < oldData.length) ? Colors.red : Colors.white,
Vivek Chib
  • 837
  • 1
  • 2
  • 13