skip to Main Content

I have a model:

import 'dart:convert';

Forecast forecastFromJson(String str) => Forecast.fromJson(json.decode(str));

String forecastToJson(Forecast data) => json.encode(data.toJson());

class Forecast {
  List<ListElement> list;

  Forecast({
    required this.list,
  });

  factory Forecast.fromJson(Map<String, dynamic> json) => Forecast(
    list: List<ListElement>.from(json["list"].map((x) => ListElement.fromJson(x))),
  );

  Map<String, dynamic> toJson() => {
    "list": List<dynamic>.from(list.map((x) => x.toJson())),
  };
}

class ListElement {
  int dt;
  Main main;
  DateTime dtTxt;

  ListElement({
    required this.dt,
    required this.main,
    required this.dtTxt,
  });

  factory ListElement.fromJson(Map<String, dynamic> json) => ListElement(
    dt: json["dt"],
    main: Main.fromJson(json["main"]),
    dtTxt: DateTime.parse(json["dt_txt"]),
  );

  Map<String, dynamic> toJson() => {
    "dt": dt,
    "main": main.toJson(),
    "dt_txt": dtTxt.toIso8601String(),
  };
}

class Main {
  double temp;
  int humidity;

  Main({
    required this.temp,
    required this.humidity,
  });

  factory Main.fromJson(Map<String, dynamic> json) => Main(
    temp: json["temp"]?.toDouble(),
    humidity: json["humidity"],
  );

  Map<String, dynamic> toJson() => {
    "temp": temp,
    "humidity": humidity,
  };
}

And there is a part of the code that outputs a list:

return  ListView.separated(
                  padding: const EdgeInsets.all(8),
                  itemCount: state.forecast.list.length,
                  separatorBuilder: (BuildContext context, int index) => Divider(),
                  itemBuilder: (BuildContext context, int index) {
                    return ListTile(
                        title: Text("${state.forecast.list[index].main.temp}", style:TextStyle(fontSize: 22)),
                        subtitle: Text("${state.forecast.list[index].dtTxt}")
                    );
                  }
              );

Everything works great. But I need to make sure that the very first element of the list is the one with the lowest temperature.

That is, by default, the list items are sorted by date. And I need them to be sorted by temperature. And I do not need a button for sorting. I need the user to see a list sorted by temperature.

Edit 1. This is the code related to this state.

class ForecastLoadSuccess extends WeatherState {
  final Forecast forecast;

  ForecastLoadSuccess({required this.forecast});
}

Edit 2. This is the bloc code.

on<ForecastRequest>((event, emit) async {
    emit(WeatherLoadInProgress());
    try {
      final forecastResponse =
      await _forecastRepository.getForecast(event.cityName);
      emit(ForecastLoadSuccess(forecast: forecastResponse));
    } catch (e) {
      print(e);
      emit(WeatherLoadFailure(error: e.toString()));
    }
  }
  );

2

Answers


  1. Change this:

      factory Forecast.fromJson(Map<String, dynamic> json) => Forecast(
        list: List<ListElement>.from(json["list"].map((x) => ListElement.fromJson(x))),
      );
    

    To:

      factory Forecast.fromJson(Map<String, dynamic> json) => Forecast(
        list: List<ListElement>.from(json["list"].map((x) => ListElement.fromJson(x)))..sort((a, b) => a.main.temp.compareTo(b.main.temp)),
      );
    

    Notice that you probably want to do the sorting when you assign your state, and not in the fromJson method (what happens if the data comes from a different source? You will have to duplicate the code) but you didn’t expose that part of the code.

    Edit

    By looking at your code, you can do something like this:

    final forecastResponse = await _forecastRepository.getForecast(event.cityName);
    forecastResponse.list.sort((a, b) => a.main.temp.compareTo(b.main.temp));
    emit(...)
    
    Login or Signup to reply.
  2. You can use it like this, It will apply to all scenario

    factory Forecast.fromJson(Map<String, dynamic> json) {
       final list = List<ListElement>.from(json["list"].map((x) => ListElement.fromJson(x)));
       list.sort((a,b)=> a.main.temp-b.main.temp);
       return Forecast(list: list);
    }
    

    or if you want to do it for a particular state, then pass that list to that state and sort it in that state class, for Example

    class SomeState extends MainState {
      final List<ListElement> listOfElement;
      SomeState(this.listOfElement){
        listOfElement.sort((a,b)=> a.main.temp-b.main.temp);
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search