Search code examples
flutterpull-to-refresh

Using RefreshIndicator to refresh listview from web service


I am not understanding the use of RefreshIndicator in Flutter. I have a listview of patients from a clinic. The list of patients may change once it is shown in the app, other app users may add new patients or delete existing patients.

What I need is to implement a way to refresh the list of patients when needed.

Here you have the piece of code where I am showing the list items:

//LISTA DE PACIENTES
            Expanded(
              child: Consumer(
                builder: (context, watch, child) {
                  var value = watch(clinicaIdStateProvider).state;

                  return Container(
                    child: FutureBuilder(
                      future: fetchPacientes(value),
                      builder: (context, snapshot) {

                        if (snapshot.hasData) {
                          var filteredList = snapshot.data;
                          print("a minusculas:"+_controller.text.toLowerCase());
                          filteredList = filteredList.where((element) => (
                              element.nombre_completo.toLowerCase().contains(_controller.text.toLowerCase()) ||
                                  element.NHC.toLowerCase().contains(_controller.text.toLowerCase()) ||
                                  element.apellidos.toLowerCase().contains(_controller.text.toLowerCase())
                          )).toList();

                          print("texto filtrado="+_controller.text.toLowerCase());


                          return ListView.builder(
                            itemCount: filteredList.length,
                            shrinkWrap: true,
                            itemBuilder: (BuildContext context, index) {
                              Paciente paciente = filteredList[index];
                              return new GestureDetector(
                                onTap: () {
                                  print("paciente seleccionada nbre: " +
                                      '${paciente.nombre_completo}');
                                },
                                child: new Card(

                                  elevation: 6,
                                  child: new Container(

                                    child: Column(
                                      children: [
                                        Padding(
                                          padding: const EdgeInsets.all(4.0),
                                          child: Row(
                                            mainAxisAlignment:
                                                MainAxisAlignment.spaceBetween,
                                            children: [
                                              Padding(
                                                padding:
                                                    const EdgeInsets.all(4.0),
                                                child: Text(
                                                  "${paciente.apellidos}" +
                                                      ", " +
                                                      "${paciente.nombre_completo}",
                                                  style:
                                                      TextStyle(fontSize: 18),
                                                ),
                                              ),
                                              Column(
                                                children: [
                                                  Container(
                                                    decoration: BoxDecoration(
                                                        color:
                                                            AppColors.azulCapenergy,
                                                        border: Border.all(
                                                          color: AppColors
                                                              .azulCapenergy,
                                                        ),
                                                        borderRadius:
                                                            BorderRadius.all(
                                                                Radius.circular(
                                                                    12))),
                                                    child: Padding(
                                                      padding:
                                                          const EdgeInsets.all(4.0),
                                                      child: Text(
                                                        "NHC: ${paciente.NHC}",
                                                        style: TextStyle(
                                                            color: AppColors
                                                                .blancoCapenergy,
                                                            fontSize: 16),
                                                      ),
                                                    ),

                                                  ),
                                                  SizedBox(height: 3,),
                                                  FlatButton(
                                                    onPressed: (){
                                                      print("boton agenda pulsado de ${paciente.nombre_completo}");
                                                    },
                                                    child: Container(
                                                      decoration: BoxDecoration(
                                                          color:
                                                          Colors.transparent,
                                                          border: Border.all(
                                                            color: AppColors
                                                                .azulCapenergy,
                                                          ),
                                                          borderRadius:
                                                          BorderRadius.all(
                                                              Radius.circular(
                                                                  15))),
                                                      child: Padding(
                                                        padding:
                                                        const EdgeInsets.all(8.0),
                                                        child: Image.network(
                                                          'https://.../agenda.png',
                                                          height: 25,
                                                        ),
                                                      ),

                                                    ),
                                                  ),
                                                ],
                                              ),
                                            ],
                                          ),
                                        ),

                                      ],
                                    ),
                                  ),
                                ),
                              );
                            },
                          );
                        }

                        return Image.asset(
                          "assets/images/vacio.png",
                          fit: BoxFit.contain,
                        );
                      },
                    ),
                  );
                },
              ),
            ),

Inside the FutureBuilder child I am calling the method that populates the listview:

fetchPacientes(value)

Which is the best way to implement RefreshIndicator in my current app?


Solution

  • This is how I'm doing it..

    You'll have to create a seperate StatefulWidget for your ListView.Builder

    class XYZ extends StatefulWidget {
      final filteredList;
    
      const XYZ(this.filteredList);
      @override
      _XYZState createState() => _XYZState();
    }
    
    class _XYZState extends State<XYZ> {
      var refreshfilteredList;
    
      @override
      Widget build(BuildContext context) {
        var filteredList = refreshfilteredList ?? widget.filteredList;
    
        return RefreshIndicator(
            onRefresh: () async {
              refreshfilteredList = await fetchPacientes(value);
    
              refreshfilteredList = refreshfilteredList
                  .where((element) => (element.nombre_completo
                          .toLowerCase()
                          .contains(_controller.text.toLowerCase()) ||
                      element.NHC
                          .toLowerCase()
                          .contains(_controller.text.toLowerCase()) ||
                      element.apellidos
                          .toLowerCase()
                          .contains(_controller.text.toLowerCase())))
                  .toList();
              setState(() {});
            },
            child: ListView.builder());
      }
    }
    

    To implement

     Expanded(
                  child: Consumer(
                    builder: (context, watch, child) {
                      var value = watch(clinicaIdStateProvider).state;
    
                      return Container(
                        child: FutureBuilder(
                          future: fetchPacientes(value),
                          builder: (context, snapshot) {
    
                            if (snapshot.hasData) {
                              var filteredList = snapshot.data;
                              print("a minusculas:"+_controller.text.toLowerCase());
                              filteredList = filteredList.where((element) => (
                                  element.nombre_completo.toLowerCase().contains(_controller.text.toLowerCase()) ||
                                      element.NHC.toLowerCase().contains(_controller.text.toLowerCase()) ||
                                      element.apellidos.toLowerCase().contains(_controller.text.toLowerCase())
                              )).toList();
    
                              print("texto filtrado="+_controller.text.toLowerCase());
    
    
                              return XYZ(filteredList)