Laddybug Little
Laddybug Little

Reputation: 61

Flutter (Error): Looking up a deactivated widget's ancestor is unsafe

This error apears when I try to change tab from search screen fron another screen on bottomNavigationBar.

Error hint says: To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.

But I don't know how to include those on my code.

Can you help me?

Here is my search screen

class Test extends StatefulWidget {
  const Test({Key? key}) : super(key: key);

  @override
  _TestState createState() => _TestState();
}

class _TestState extends State<Test> {
  static const historyLenght = 5;
  final List<String> _searchHistory = ['test1', 'test2'];

  late List<String> filteredSearchHistory;

  String? selectedTerm;

  List<String> filterSearchTerms({
    @required String? filter,
  }) {
    if (filter != null && filter.isNotEmpty) {
      return _searchHistory.reversed
          .where((term) => term.startsWith(filter))
          .toList();
    } else {
      return _searchHistory.reversed.toList();
    }
  }

  void addSearchTerm(String term) {
    if (_searchHistory.contains(term)) {
      putSearchTermFirst(term);
      return;
    }
    _searchHistory.add(term);
    if (_searchHistory.length > historyLenght) {
      _searchHistory.removeRange(0, _searchHistory.length - historyLenght);
    }
    filteredSearchHistory = filterSearchTerms(filter: null);
  }

  void deleteSearchTerm(String term) {
    _searchHistory.removeWhere((element) => element == term);
    filteredSearchHistory = filterSearchTerms(filter: null);
  }

  void putSearchTermFirst(String term) {
    deleteSearchTerm(term);
    addSearchTerm(term);
  }

  late FloatingSearchBarController controller;

  @override
  void initState() {
    super.initState();
    controller = FloatingSearchBarController();
    filteredSearchHistory = filterSearchTerms(filter: null);
  }

  @override
  void dispose() {
    super.dispose();
    controller.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: FloatingSearchBar(
        controller: controller,
        body: FloatingSearchBarScrollNotifier(
          child: SearchResultListView(searchTerm: selectedTerm),
        ),
        transition: CircularFloatingSearchBarTransition(),
        physics: const BouncingScrollPhysics(),
        title: Text(selectedTerm ?? "Search"),
        hint: 'Search ... ',
        actions: [
          FloatingSearchBarAction.searchToClear(size: 20),
        ],
        onQueryChanged: (query) {
          setState(() {
            filteredSearchHistory = filterSearchTerms(filter: query);
          });
        },
        onSubmitted: (query) {
          setState(() {
            addSearchTerm(query);
            selectedTerm = query;
          });
          controller.close();
        },
        builder: (context, transition) {
          return ClipRRect(
            borderRadius: BorderRadius.circular(8),
            child: Material(
                color: Colors.white,
                elevation: 4,
                child: Builder(builder: ((context) {
                  if (filteredSearchHistory.isEmpty &&
                      controller.query.isEmpty) {
                    return Container(
                        height: 56,
                        width: double.infinity,
                        alignment: Alignment.center,
                        child: const Text(
                          'Start searching',
                          maxLines: 1,
                          overflow: TextOverflow.ellipsis,
                        ));
                  } else if (filteredSearchHistory.isEmpty) {
                    return ListTile(
                      title: Text(controller.query),
                      leading: const Icon(Icons.search),
                      onTap: () {
                        setState(() {
                          addSearchTerm(controller.query);
                          selectedTerm = controller.query;
                        });
                        controller.close();
                      },
                    );
                  } else {
                    return Column(
                        mainAxisSize: MainAxisSize.min,
                        children: filteredSearchHistory
                            .map(
                              (e) => ListTile(
                                title: Text(e,
                                    maxLines: 1,
                                    overflow: TextOverflow.ellipsis),
                                leading: const Icon(Icons.history),
                                trailing: IconButton(
                                  icon: const Icon(Icons.clear),
                                  onPressed: () {
                                    setState(() {
                                      deleteSearchTerm(e);
                                    });
                                  },
                                ),
                                onTap: () {
                                  setState(() {
                                    putSearchTermFirst(e);
                                    selectedTerm = e;
                                  });
                                  controller.close();
                                },
                              ),
                            )
                            .toList());
                  }
                }))),
          );
        },
      ),
    );
  }
}

class SearchResultListView extends StatelessWidget {
  final String? searchTerm;

  const SearchResultListView({
    Key? key,
    required this.searchTerm,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final UserProvider userProvider = Provider.of<UserProvider>(context);
    final sBar = FloatingSearchBar.of(context);
    if (searchTerm == null) {
      return const Center(child: Text('Search'));
    }

    return FutureBuilder(
        future: userProvider.searchResult(searchTerm),
        builder: (context, AsyncSnapshot<List<UserData>> snapshot) {
          if (!snapshot.hasData) {
            return const Center(
              child: CircularProgressIndicator(),
            );
          }

          return ListView.separated(
            padding: EdgeInsets.only(
                top: sBar!.style.height + sBar.style.margins.vertical + 20),
            itemCount: snapshot.data!.length,
            separatorBuilder: (BuildContext context, int index) {
              return const Divider(
                color: Colors.grey,
              );
            },
            itemBuilder: (context, index) {
              String _titleName = snapshot.data![index].name +
                  ' ' +
                  snapshot.data![index].lastName;

              return ListTile(
                leading: Column(children: [
                  Container(
                      height: 55,
                      width: 55,
                      decoration: const BoxDecoration(
                          shape: BoxShape.circle,
                          image: DecorationImage(
                            fit: BoxFit.cover,
                            image: AssetImage('assets/images/boy.jpg'),
                          )))
                ]),
                title: Text(
                  _titleName,
                  style: const TextStyle(
                      fontWeight: FontWeight.bold, fontSize: 18),
                ),
                subtitle: Column(children: <Widget>[
                  Row(children: [
                    Text(_subtitle,
                        style: const TextStyle(fontWeight: FontWeight.bold))
                  ]),
                  Row(children: [
                    Text('De ' + snapshot.data![index].location.nameL + ' a '),
                    Text(Haversine.distance(
                                userProvider.getUser.location.latitude,
                                userProvider.getUser.location.longitude,
                                snapshot.data![index].location.latitude,
                                snapshot.data![index].location.longitude)
                            .toString() +
                        ' km')
                  ])
                ]),
                onTap: () => Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => ProfilePage(
                      uid: snapshot.data![index].uid,
                    ),
                  ),
                ),
              );
            },
          );
        });
  }
}

Upvotes: 0

Views: 227

Answers (1)

Yuya
Yuya

Reputation: 26

I had the same error, and the error log pointed at the "FloatingSearchBar" widget. Upgrading FloatingSearchBar to 0.3.7(latest as of Apr 12) fixed the issue for me. Hope this works for you too..

Upvotes: 1

Related Questions