Adam Theory
Adam Theory

Reputation: 123

ListView filter search with FutureBuilder in Flutter

i am a beginner of flutter programming. i got a problem for search feature of listview when i use future builder, when i type a letter it change the list for a second, but back to all list data after a second. i dont know what's the error, because there is no warning or errors only. i stack on this code, please helpppppppppppppppp......

this is my code, Default list data when i type letters, the list back again after a seconds

List mydata;
  List unfilterData;

  Future loadJsonData() async {
    List data = json.decode(await rootBundle.loadString('Json/indomodel.json'));
    setState(() {
      mydata = data;
      this.unfilterData = mydata;
    });
    return data;
  }

  Widget mylist() {
    return FutureBuilder(
      future: loadJsonData(),
      builder: (context, snapshot) {
        if (!snapshot.hasData)
          return Center(
              child: CircularProgressIndicator(
            valueColor: AlwaysStoppedAnimation(Colors.amber),
          ));
        else {
          return ListView.builder(
            itemCount: snapshot.data.length,
            itemBuilder: (BuildContext context, index) {
              return Card(
                elevation: 0.3,
                child: ListTile(
                  // leading: CircleAvatar(child: Icon(FontAwesomeIcons.adjust),),
                  title: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: <Widget>[
                          SelectableText(
                            mydata[index]['word'],
                            // data[index]['word'],
                            style: TextStyle(
                                fontSize: 16.0,
                                fontWeight: FontWeight.bold,
                                color: Colors.deepPurple.shade800),
                          ),
                          Text(
                            "My Kamus",
                            style: TextStyle(color: Colors.grey, fontSize: 10),
                          )
                        ],
                      ),
                      SizedBox(
                        height: 10.0,
                      ),
                      Text(
                        mydata[index]['trans'],
                        style: TextStyle(
                            color: Colors.grey.shade700, fontSize: 13.0),
                      )
                    ],
                  ),
                ),
              );
            },
          );
        }
      },
    );
  }

  searchData(str) {
    var strExist = str.length > 0 ? true : false;

    if (strExist) {
      var filterData = [];

      for (var i = 0; i < unfilterData.length; i++) {
        String word = unfilterData[i]['word'];
        if (word.contains(str)) {
          filterData.add(unfilterData[i]);
        }
      }

      setState(() {
        this.mydata = filterData;
      });
    } else {
      setState(() {
        //
        this.mydata = this.unfilterData;
      });
    }
  }

Upvotes: 2

Views: 7748

Answers (1)

Pablo Barrera
Pablo Barrera

Reputation: 10963

The problem in your code is that you are calling loadJsonData() in the FutureBuilder, so when you call setState() the loadJsonData() will be called again.

What you should do is to call loadJsonData() once, in the initState(), save the future into a variable and use that variable on the FutureBuilder, like this:

Future _future;

@override
void initState() {
  super.initState();
  _future = loadJsonData();
}

And in the FutureBuilder do this:

future: _future,

Note: since you need to filter the list it's okay to save the list to mydata and then use mydata in the ListView.builder(), just make sure to change this part to avoid confusion:

itemCount: snapshot.data.length,

should be:

itemCount: mydata.length,

Suggestions:

  • It's a good practice to specify the correct types for Future and List so you can access to the properties without warnings, in your case would be like this: Future<List<Map<String, dynamic>>> and List<Map<String, dynamic>>.
  • It's not good to call setState() from a future because the widget could be disposed and cause errors, you could set the list inside the FutureBuilder.

Upvotes: 18

Related Questions