flutter problem:how to reflect changes in another page when i search from another page in flutter
This is my "TabTop" search ui code. In this search page I have a search function which is stored data in "eventsSearchLists" and I have a one more variable "eventsListData" In this variable I have previus data when i search anything then data will changed in variable but its not reflecting another page.
When search data does come in "eventsListData" then data that time is not changing but when i use "ctrl+s" then data is reflecting
This is eventsListData my global variable
import 'dart:async';
import 'package:cwc/ApiManager/api_magager.dart';
import 'package:flutter/material.dart';
import 'constants.dart';
class TabTop extends StatefulWidget {
const TabTop({Key? key}) : super(key: key);
@override
State<TabTop> createState() => _TabTopState();
}
class _TabTopState extends State<TabTop> {
ApiManager apiManager = ApiManager();
@override
void initState() {
super.initState();
}
String query = '';
Timer? debouncer;
void dispose() {
debouncer?.cancel();
super.dispose();
}
void debounce(
VoidCallback callback, {
Duration duration = const Duration(milliseconds: 10),
}) {
if (debouncer != null) {
debouncer!.cancel();
}
debouncer = Timer(duration, callback);
}
Future searchEvent(String query) async => debounce(() async {
// final breanchesLists = await apiManager.topBrancesList(query);
final eventsLists = await apiManager.eventsSearch(query);
if (!mounted) return;
setState(() {
this.query = query;
eventsSearchLists = eventsLists;
print("eventsSearchLists $eventsSearchLists");
setState(() {
eventsListData =[eventsSearchLists];
print("eventsSearchLists111 $eventsListData");
});
});
});
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(vertical: 8),
height: 60,
child: TextField(
onChanged: searchEvent,
textAlignVertical: TextAlignVertical.center,
decoration: InputDecoration(
contentPadding: EdgeInsets.all(10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
borderSide: BorderSide.none,
),
filled: true,
fillColor: const Color(0xFFFFFFFF),
hintText: 'Search for Events',
suffixIcon: const Icon(
Icons.search_outlined,
color: Color(0xFF444444),
),
),
),
);
}
}
This is my another page where I called "TabTop" and another things.
// ignore_for_file: prefer_const_constructors
import 'package:cwc/constants/card_top.dart';
import 'package:cwc/constants/top_card.dart';
import 'package:cwc/ui/Event/components/activities.dart';
import 'package:cwc/ui/Event/components/event_page_changer.dart';
import 'package:cwc/ui/Event/components/event_tab_view.dart';
import 'package:cwc/ui/Home/components/search_components.dart';
import 'package:cwc/ui/Home/home_page.dart';
import 'package:cwc/ui/footer/bottom_nav_bar.dart';
import 'package:cwc/ui/footer/bottom_nav_bar_event.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
class Event extends StatefulWidget {
const Event({Key? key}) : super(key: key);
@override
_EventState createState() => _EventState();
}
class _EventState extends State<Event> {
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
// backgroundColor: Color(0xff80CAD7),
body: SafeArea(
child: Stack(
children: [
Container(
width: double.infinity,
height: 210,
decoration: const BoxDecoration(
color: Color(0xff80CAD7),
image: DecorationImage(
image: AssetImage('assets/bg_dummy.png'),
fit: BoxFit.cover,
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(18, 12, 0, 0),
child: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: const CircleAvatar(
radius: 25,
backgroundColor: Colors.white,
child: Icon(Icons.arrow_back_ios_new, color: Colors.black),
),
),
),
],
),
),
Padding(
padding: EdgeInsets.fromLTRB(18, 125, 18, 0),
child: TabTop(),
),
Padding(
padding: EdgeInsets.only(top: 190),
child: Container(
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topRight: Radius.circular(24.0),
topLeft: Radius.circular(24.0)),
),
child: Activities()), // here is my list of data in Activities page (Showing data in this page)
)
// EventPageChanger(),
// Expanded(child: Activities()),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => HomePage()));
},
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
child: Image.asset('assets/btnavico.png'),
elevation: 5.0,
highlightElevation: 10,
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: Container(
// height: MediaQuery.of(context).size.height * (10 / 100),
child: BottomNavBarEvent()),
);
}
}
The thing that’s happening here is that you are calling setState inside TabTop on loading new data that caused only TabTop to rebuild i.e. only the widget inside TabTop is rebuilt. But, the Activities() widget that shows the data is inside Event class which doesn’t get rebuilt.So we need a way to rebuild the entire Event class once the data is updated. You could achieve this by:
Define a callback function in TabTop class that can be called after data is updated as:
class TabTop extends StatefulWidget {
const TabTop({Key? key,required this.onDataUpdated}) : super(key: key);
final VoidCallback onDataUpdated;
@override
State<TabTop> createState() => _TabTopState();
}
And call this callback function once the data is updated as:
Future searchEvent(String query) async => debounce(() async {
// final breanchesLists = await apiManager.topBrancesList(query);
final eventsLists = await apiManager.eventsSearch(query);
if (!mounted) return;
///callback function has been called here
widget.onDataUpdated();
///avoid unnecessary setState
setState(() {
this.query = query;
eventsSearchLists = eventsLists;
eventsListData =[eventsSearchLists];
print("eventsSearchLists111 $eventsListData");
print("eventsSearchLists $eventsSearchLists”);
});
});
On Event class, while calling TabTop, send the callback function as a parameter as :
Padding(
padding: EdgeInsets.fromLTRB(18, 125, 18, 0),
child: TabTop(
onDataUpdated : () =>setState((){}),
),
),