Dart- Exception after run my flutter search app - flutter

My question about how can i handle this exception error that appear on my mobile when i execute it with red screen
i'm new with flutter and I have wrote simple search bar widget. After executing it got exception:
ErrorSummary('MediaQuery.of() called with a context that does not contain a MediaQuery.'),
ErrorDescription(
'No MediaQuery ancestor could be found starting from the context that was passed '
'to MediaQuery.of(). This can happen because you do not have a WidgetsApp or '
'MaterialApp widget (those widgets introduce a MediaQuery), or it can happen '
'if the context you use comes from a widget above those widgets.'
This is main.dart for searchbar:
import 'package:flutter/material.dart';
void main() {
runApp(MyFirstApp());
}
class MyFirstApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Search..."),
actions: <Widget>[
IconButton(
icon: Icon(Icons.search),
onPressed: () {
showSearch(context: context, delegate: DataSearch());
})
],
),
drawer: Drawer(),
);
}
}
class DataSearch extends SearchDelegate<String> {
final data1 = ["Amr", "Amir", "Moatasem", "Gamal", "Tasneem"];
final data2 = ["Amr", "Amir"];
#override
List<Widget> buildActions(BuildContext context) {
return <Widget>[
IconButton(
icon: Icon(Icons.clear),
onPressed: () {
query = " ";
})
];
}
#override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: AnimatedIcon(
icon: AnimatedIcons.menu_arrow,
progress: transitionAnimation,
),
onPressed: () {
close(context, null);
});
}
#override
Widget buildResults(BuildContext context) {
return Container(
child: Center(
child: Text(query),
),
);
}
#override
Widget buildSuggestions(BuildContext context) {
final suggestion = query.isEmpty
? data2
: data1.where((p) => p.startsWith(query)).toList();
return ListView.builder(
itemBuilder: (context, index) => ListTile(
onTap: () {
showResults(context);
},
leading: Icon(Icons.question_answer),
title: RichText(
text: TextSpan(
text: suggestion[index].substring(0, query.length),
style:
TextStyle(color: Colors.black, fontStyle: FontStyle.italic),
children: [
TextSpan(
text: suggestion[index].substring(query.length),
style: TextStyle(color: Colors.red))
]),
),
),
itemCount: suggestion.length,
);
}
}
This is Widget test.dart
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:testtest/main.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(MyFirstApp());
// Verify that our counter starts at 0.
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
// Tap the '+' icon and trigger a frame.
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
// Verify that our counter has incremented.
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
});
}
I have found MediaQuery.of but don't understand how can it be used with existing widget? It accept BuildContext as parameter.
static MediaQueryData of(BuildContext context, { bool nullOk = false }) {
assert(context != null);
assert(nullOk != null);
final MediaQuery query = context.dependOnInheritedWidgetOfExactType<MediaQuery>();
if (query != null)
return query.data;

Your application lacks a MaterialApp Widget which is a required at top level. That's causing this error .
The bellow code will solve this issue:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyFirstApp(),
);
}
}
class MyFirstApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Search..."),
actions: <Widget>[
IconButton(
icon: Icon(Icons.search),
onPressed: () {
showSearch(context: context, delegate: DataSearch());
})
],
),
drawer: Drawer(),
);
}
}
class DataSearch extends SearchDelegate<String> {
final data1 = ["Amr", "Amir", "Moatasem", "Gamal", "Tasneem"];
final data2 = ["Amr", "Amir"];
#override
List<Widget> buildActions(BuildContext context) {
return <Widget>[
IconButton(
icon: Icon(Icons.clear),
onPressed: () {
query = " ";
})
];
}
#override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: AnimatedIcon(
icon: AnimatedIcons.menu_arrow,
progress: transitionAnimation,
),
onPressed: () {
close(context, null);
});
}
#override
Widget buildResults(BuildContext context) {
return Container(
child: Center(
child: Text(query),
),
);
}
#override
Widget buildSuggestions(BuildContext context) {
final suggestion = query.isEmpty
? data2
: data1.where((p) => p.startsWith(query)).toList();
return ListView.builder(
itemBuilder: (context, index) => ListTile(
onTap: () {
showResults(context);
},
leading: Icon(Icons.question_answer),
title: RichText(
text: TextSpan(
text: suggestion[index].substring(0, query.length),
style:
TextStyle(color: Colors.black, fontStyle: FontStyle.italic),
children: [
TextSpan(
text: suggestion[index].substring(query.length),
style: TextStyle(color: Colors.red))
]),
),
),
itemCount: suggestion.length,
);
}
}

Related

How to use FormState in Form's parent widget?

To validate the whole Form in flutter, a GloabalKey<FormState> must be provided. It looks fine when buttons for interaction with the form contained inside of form, but when, for example, form is a child of AlertDialog, the key has to be passed from the dialog widget, and it doesn't look good. Is there any better solution for obtaining FormState from a parent widget?
Here's the example:
main
void main() {
runApp(
const MaterialApp(
home: InitialScreen(),
),
);
}
Initial Screen
class InitialScreen extends StatelessWidget {
const InitialScreen({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
showDialog<void>(
context: context,
builder: (BuildContext context) {
return FormDialog();
},
);
},
),
);
}
}
Form Dialog
class FormDialog extends StatelessWidget {
FormDialog({super.key});
GlobalKey<FormState> myFormState = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return AlertDialog(
title: const Text('Create new item'),
content: MyForm(
formCurrentState: myFormState,
),
actions: <Widget>[
TextButton(
style: TextButton.styleFrom(
textStyle: Theme.of(context).textTheme.labelLarge,
),
child: const Text('Add'),
onPressed: () {
if (myFormState.currentState!.validate()) {
print("All fine");
Navigator.of(context).pop();
} else {
print("Error");
}
},
),
TextButton(
style: TextButton.styleFrom(
textStyle: Theme.of(context).textTheme.labelLarge,
),
child: const Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
}
}
My Form
class MyForm extends StatefulWidget {
const MyForm({super.key, required this.formCurrentState});
final GlobalKey<FormState> formCurrentState;
#override
State<MyForm> createState() => _MyFormState();
}
class _MyFormState extends State<MyForm> {
GlobalKey<FormState>? formCurrentState;
#override
void initState() {
super.initState();
formCurrentState = widget.formCurrentState;
}
#override
Widget build(BuildContext context) {
return Form(
key: formCurrentState,
child: TextFormField(
validator: (value) {
if (value == "") {
return "Please, enter some text";
} else {
return null;
}
},
),
);
}
}
I think there is no better solution to get FormState from parent widget.
If you don't want to make another widget (MyForm), try this code:
class FormDialog extends StatelessWidget {
FormDialog({super.key});
GlobalKey<FormState> myFormState = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return AlertDialog(
title: const Text('Create new item'),
content: Form(
key: formCurrentState,
child: TextFormField(
validator: (value) {
if (value == "") {
return "Please, enter some text";
} else {
return null;
}
},
),
),
actions: <Widget>[
TextButton(
style: TextButton.styleFrom(
textStyle: Theme.of(context).textTheme.labelLarge,
),
child: const Text('Add'),
onPressed: () {
if (myFormState.currentState!.validate()) {
print("All fine");
Navigator.of(context).pop();
} else {
print("Error");
}
},
),
TextButton(
style: TextButton.styleFrom(
textStyle: Theme.of(context).textTheme.labelLarge,
),
child: const Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
}
}

Call Function From Another Flutter Class

I would like to call function between another clas. So when the menu tapped from grabDrawer it will change the currentIndex at Main() class. Do you know how to do that? Here is so far I have tried.
main.dart
class _MainState extends State<Main> {
int currentIndex = 0;
Map<String,dynamic> searchParameter = {};
List screens = [
Home(),
Search({}),
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
actions: [
Builder(builder: (context){
return IconButton(
onPressed: (){
Scaffold.of(context).openEndDrawer();
},
icon: const Icon(Icons.menu),
);
}),
],
),
endDrawer: const Drawer(
child:DrawerObject(),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.arrow_upward),
onPressed: () async{
await Future.delayed(Duration(milliseconds: 100),(){
globals.scrollController.animateTo(0, duration: Duration(milliseconds: 500), curve: Curves.fastOutSlowIn);
});
},
),
body: screens[currentIndex],
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentIndex,
onTap: (index) => setState(() {
if (index == 1) {
getSearchForm(context);
} else {
currentIndex = index;
searchParameter = {};
}
}),
selectedItemColor: Colors.white,
unselectedItemColor: Colors.grey[100],
type: BottomNavigationBarType.shifting,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
backgroundColor: Colors.blue[500],
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
label: 'Pencarian',
backgroundColor: Colors.orange[500],
),
],
),
);
}
//main function ===> NEED TO CALL THIS FUNCTION INSIDE grabDrawer.dart
Future UpdateIndex({int Index = 0}) async{
setState(() {
currentIndex = Index;
});
}
Future getSearchForm(BuildContext context) async {
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => SearchForm(parameter:searchParameter)),
);
setState(() {
if (result != null) {
currentIndex = 1;
if(result!=searchParameter){
searchParameter = result;
screens[1] = CallLoading(show: ''); //set default to load
//set to new parameter (rebuilding widget)
Future.delayed(Duration(milliseconds: 500),(){
setState(() {
screens[1] = Search(searchParameter);
});
});
}
}
else{
}
});
}
}
Under this file, I need to call function from Main.UpdateIndex.
grabDrawer.dart
class DrawerObject extends StatelessWidget {
const DrawerObject({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
child: ListView(
children: [
ListTile(
leading: Icon(Icons.home),
title: Text('Cari Properti?'),
onTap: (){
===> CALL IT HERE
}
),
],
),
);
}
}
I really appreciate any answers. Thank you.
Change your grabDrawer.dart like this
class DrawerObject extends StatelessWidget {
void Function()? UpdateIndex;
DrawerObject({
this.UpdateIndex,
});
#override
Widget build(BuildContext context) {
return Container(
child: ListView(
children: [
ListTile(
leading: Icon(Icons.home),
title: Text('Cari Properti?'),
onTap: (){
UpdateIndex!();
}
),
],
),
);
}
}
And in your main.dart, call Drawer class like this
endDrawer: const Drawer(
child:DrawerObject(
UpdateIndex: UpdateIndex,
);
),
Hope this works for you.
Here is the clear way to pass data between one class to another class
void main() {
runApp(MaterialApp(
home: Modalbtn(),
));
}
class Modalbtn extends StatefulWidget {
#override
_ModalbtnState createState() => _ModalbtnState();
}
class _ModalbtnState extends State<Modalbtn> {
String value = "0";
// Pass this method to the child page.
void _update(String newValue) {
setState(() => value = newValue);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: [
IconButton(
onPressed: () {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
height: 200,
child: Column(
children: [StatefulModalbtn(update: _update)],
),
);
});
},
icon: Icon(Icons.add),
iconSize: 20,
),
Text(
value,
style: TextStyle(fontSize: 40),
),
],
),
),
);
}
}
import 'package:flutter/material.dart';
class StatefulModalbtn extends StatelessWidget {
final ValueChanged<String> update;
StatefulModalbtn({required this.update});
#override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => update("100"), // Passing value to the parent widget.
child: Text('Update (in child)'),
);
}
}

type 'String' is not a subtype of type 'Description'

Hello everyone i am new in flutter. I am trying to take data from API. When i try to take, i can get the body but i cannot get the datas from into it. I get an error like "I/flutter ( 8981): type 'String' is not a subtype of type 'Description'". Here is a screenshot for from my console when i run the code: Console output
and here is my code:
import 'dart:convert';
import 'dart:ffi';
import 'package:feedme_start/main.dart';
import 'package:feedme_start/model/AnaEkran_modeli.dart';
import 'package:feedme_start/model/branch_list.dart';
import 'package:feedme_start/model/restourantList.dart';
import 'package:feedme_start/widgets/Navigation_Drawer_Widget.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
class restaurantPage extends StatefulWidget {
const restaurantPage({Key? key}) : super(key: key);
#override
_restaurantPageState createState() => _restaurantPageState();
}
final datas = [];
final datas_oneri = [];
class _restaurantPageState extends State<restaurantPage> {
int counter = 0;
var personalResult;
Future getapidata() async {
//orjinal api denemesi
String url =
"https://www.mobilonsoft.com/fpsapi/default.aspx?op=branch_list&firmuid=feedmekktc&device_id=web_20210813180900001&device_platform=4&lang=en";
try {
Response responsee = await get(Uri.parse(url)); //yanıtı alır
if (responsee.statusCode == 200) {
// yanıt onaylanırsa
Map sonuc = jsonDecode(responsee.body); //içeriği alır
print("apideki veriler ;");
print(sonuc);
**Branchlist liste = Branchlist.fromJson(sonuc);**
print(liste.result.branchList.toString());
} else {}
} catch (e) {
print(e.toString());
print("verileri çekerken hata oluştu");
}
}
#override
void initState() {
getapidata();
}
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
elevation: 0,
leading: IconButton(
onPressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => MyApp()));
},
icon: Icon(Icons.arrow_back)),
backgroundColor: Colors.red,
actions: <Widget>[
IconButton(
onPressed: () {
showSearch(context: context, delegate: dataSearch());
},
icon: Icon(Icons.search)),
],
),
backgroundColor: Colors.white,
body: Center(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: ListView.builder(
itemCount: counter,
itemBuilder: (context, index) {
return ListTile(
title: Text(personalResult.data[index].firstName +
" " +
personalResult.data[index].lastName),
subtitle: Text(personalResult.data[index].email),
leading: CircleAvatar(
backgroundImage:
NetworkImage(personalResult.data[index].avatar),
),
);
}),
),
),
),
);
}
}
class dataSearch extends SearchDelegate<String> {
#override
List<Widget> buildActions(BuildContext context) {
// actions for appbar
return [
IconButton(
onPressed: () {
query = "";
},
icon: Icon(Icons.clear))
];
}
#override
Widget buildLeading(BuildContext context) {
// leading icon on the left of the app bar
return IconButton(
icon: AnimatedIcon(
icon: AnimatedIcons.menu_arrow, progress: transitionAnimation),
onPressed: () {
close(context, query);
},
);
}
#override
Widget buildResults(BuildContext context) {
// show some result based on the selection
return Container(
color: Colors.red,
child: Card(),
);
throw UnimplementedError();
}
#override
Widget buildSuggestions(BuildContext context) {
// show when someone searches for something
final datasOnerisi = query.isEmpty
? datas_oneri
: datas.where((p) => p.startsWith(query)).toList();
return ListView.builder(
itemBuilder: (context, index) => ListTile(
onTap: () {
showResults(context);
},
leading: Icon(Icons.search),
title: RichText(
text: TextSpan(
text: datasOnerisi[index].substring(0, query.length),
style:
TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
children: [
TextSpan(
text: datasOnerisi[index].substring(query.length),
style: TextStyle(color: Colors.grey))
]),
),
),
itemCount: datasOnerisi.length,
);
throw UnimplementedError();
}
}
I have solved the issue by changing my Model class... There were some mistakes about that. A 'string' was saved as'description' thats why it was giving this error. So i changed it with string and it solved. It was an little easy but sneaky mistake

Implementation of basic flutter search bar failed

So I followed a tutorial on how to implement a basic Flutter search bar with search Delegation. You can find the tutorial on this link: https://www.youtube.com/watch?v=FPcl1tu0gDs
class DataSearch extends SearchDelegate<String>{
final wordssuggest=["Word1","Word2"];
final recentwords=["Word1"];
#override
List<Widget> buildActions(BuildContext context){
return [
IconButton(onPressed: (){
query=" ";
}, icon: Icon(Icons.clear))
];
//actions for appbar
}
#override
Widget buildLeading(BuildContext context){
return IconButton(onPressed: (){
close(context, null);
}, icon: Icon(Icons.search));
//leasding icon on the left of the app bar
}
#override
Widget buildResults(BuildContext context){
//show some result
return Container(
color: Colors.grey,
height: 200,
width: 200,
child: Center(child: Text(query),)
);
}
#override
Widget buildSuggestions(BuildContext context){
//show suggestions
final suggestionList =query.isEmpty?
recentwords:wordssuggest.where((p)=>p.startsWith(query)).toList();
return ListView.builder(itemBuilder: (context, index)=>ListTile(
onTap:(){
showResults(context);
} ,
leading: Icon(Icons.work_rounded),
title: RichText(text: TextSpan(text: suggestionList[index].substring(0, query.length),
style: TextStyle(color:Colors.blue, fontWeight: FontWeight.bold),
children: [TextSpan(
text:suggestionList[index].substring(query.length),
style:TextStyle(color:Colors.grey)
)]),
)
),
itemCount: suggestionList.length,);
}
}
However, what is not working for me:
For SearchDelegate method in the DataSearch class:
'Methods must have an explicit list of parameters.Try adding a parameter list.dart(missing_method_parameters)'
For buildActions, buildLeading, builduggestions and buildResults Widgets:
'The declaration 'buildActions' isn't referenced.'
Inside buildSuggestions:
The method 'showResults' isn't defined for the type '_MainPageState'.
Inside buildLeading:
The method 'close' isn't defined for the type '_MainPageState'.
Please help
Maybe your problem is occur because of calling the search delegate class.
this code solve your problem!
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Secondpage(title: 'Flutter Demo Home Page'),
);
}
}
class Secondpage extends StatelessWidget {
final String title;
Secondpage({required this.title});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
actions: [
IconButton(icon: Icon(Icons.add), onPressed: () async {
await showSearch<String>(
context: context,
delegate: DataSearch(),
);
},
)
],
));
}
}
Search Delegate
class DataSearch extends SearchDelegate<String>{
final wordSuggest=["Word1","Word2","Word3","Word4", "Word5","Word6", ];
final recentWords=["Word1"];
#override
List<Widget> buildActions(BuildContext context) {
return [
IconButton(
icon: Icon(Icons.clear),
onPressed: () {
query = "";
// showSuggestions(context);
},
),
];
}
#override
Widget buildLeading(BuildContext context) {
return IconButton(
onPressed: () {
close(context, 'null');
},
icon: AnimatedIcon(
icon: AnimatedIcons.menu_arrow,
progress: transitionAnimation,
),
);
}
#override
Widget buildResults(BuildContext context){
//show some result
return Container(
color: Colors.grey,
height: 200,
width: 200,
child: Center(child: Text(query),)
);
}
#override
Widget buildSuggestions(BuildContext context){
//show suggestions
final suggestionList =query.isEmpty?
recentWords:wordSuggest.where((p)=>p.startsWith(query)).toList();
return ListView.builder(itemBuilder: (context, index)=>ListTile(
onTap:(){
showResults(context);
} ,
leading: Icon(Icons.work_rounded),
title: RichText(text: TextSpan(text: suggestionList[index].substring(0, query.length),
style: TextStyle(color:Colors.blue, fontWeight: FontWeight.bold),
children: [TextSpan(
text:suggestionList[index].substring(query.length),
style:TextStyle(color:Colors.grey)
)]),
)
),
itemCount: suggestionList.length,);
}
}

how to refresh Old screen when update second using inherited widget in flutter

I have created a simple app using InheritedWidget, just a counter app...
I have just four files:
main.dart.
CommonScreenProvider.dart.
first_screen.dart.
second_screen.dart.
the problem here when I am trying to use the counter function in in the second_screen and go back to the first_screen I can not find any updates till I use the counter but while I use counter in first screen I found the updated value in the second screen without problem, I think there's missing a refresh function or something?
Here's the code implementation...
CommonScreenProvider
import 'package:flutter/material.dart';
class CommonScreenProvider extends InheritedWidget {
num counter = 0;
Widget child;
CommonScreenProvider({#required this.child});
#override
bool updateShouldNotify(covariant CommonScreenProvider oldWidget) {
return oldWidget.counter != counter;
}
static CommonScreenProvider of(BuildContext ctx) =>
ctx.dependOnInheritedWidgetOfExactType();
}
first_screen
import 'package:flutter/material.dart';
import 'package:statemanagementtest/second_screen.dart';
import 'commom_screen_provider.dart';
class FirstScreen extends StatelessWidget {
#override
Widget build(BuildContext ctx) {
var provider = CommonScreenProvider.of(ctx);
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: Icon(Icons.send_to_mobile),
onPressed: () {
Navigator.of(ctx).push(
MaterialPageRoute(
builder: (ctx) => SecondScreen(),
),
);
},
),
],
title: Text('My Counter App'),
),
body: Center(
child: StatefulBuilder(builder: (ctx, StateSetter setState) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
IconButton(
icon: Icon(Icons.remove),
iconSize: 50,
onPressed: () {
setState(() {
provider.counter--;
});
},
),
Text(
'${provider.counter}',
style: Theme.of(ctx).textTheme.display1,
),
IconButton(
icon: Icon(Icons.add),
iconSize: 50,
onPressed: () {
setState(() {
provider.counter++;
});
},
),
],
);
}),
),
);
}
}
second_screen
import 'package:flutter/material.dart';
import 'commom_screen_provider.dart';
class SecondScreen extends StatelessWidget {
#override
Widget build(BuildContext ctx) {
var pSecond = CommonScreenProvider.of(ctx);
return Scaffold(
appBar: AppBar(
title: Text('My Counter App'),
),
body: Center(
child: StatefulBuilder(builder: (ctx, StateSetter setState) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
IconButton(
icon: Icon(Icons.remove),
iconSize: 50,
onPressed: () {
setState(() {
pSecond.counter--;
});
},
),
Text(
'${pSecond.counter}',
style: Theme.of(ctx).textTheme.display1,
),
IconButton(
icon: Icon(Icons.add),
iconSize: 50,
onPressed: () {
setState(() {
pSecond.counter++;
});
},
),
],
);
}),
),
);
}
}
main.dart
import 'package:flutter/material.dart';
import 'package:statemanagementtest/commom_screen_provider.dart';
import 'package:statemanagementtest/first_screen.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext ctx) {
return CommonScreenProvider(
child: MaterialApp(
home: FirstScreen(),
),
);
}
}
You can copy paste run full code below
Quick fix is move StatefulBuilder up and await Navigator.of(ctx).push then call setState
code snippet
class FirstScreen extends StatelessWidget {
#override
Widget build(BuildContext ctx) {
var provider = CommonScreenProvider.of(ctx);
return StatefulBuilder(builder: (ctx, StateSetter setState) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: Icon(Icons.send_to_mobile),
onPressed: () async {
await Navigator.of(ctx).push(
MaterialPageRoute(
builder: (ctx) => SecondScreen(),
),
);
setState(() {});
working demo
full code
import 'package:flutter/material.dart';
class CommonScreenProvider extends InheritedWidget {
num counter = 0;
Widget child;
CommonScreenProvider({#required this.child});
#override
bool updateShouldNotify(covariant CommonScreenProvider oldWidget) {
return oldWidget.counter != counter;
}
static CommonScreenProvider of(BuildContext ctx) =>
ctx.dependOnInheritedWidgetOfExactType();
}
class FirstScreen extends StatelessWidget {
#override
Widget build(BuildContext ctx) {
var provider = CommonScreenProvider.of(ctx);
return StatefulBuilder(builder: (ctx, StateSetter setState) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: Icon(Icons.send_to_mobile),
onPressed: () async {
await Navigator.of(ctx).push(
MaterialPageRoute(
builder: (ctx) => SecondScreen(),
),
);
setState(() {});
},
),
],
title: Text('My Counter App'),
),
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
IconButton(
icon: Icon(Icons.remove),
iconSize: 50,
onPressed: () {
setState(() {
provider.counter--;
});
},
),
Text(
'${provider.counter}',
style: Theme.of(ctx).textTheme.display1,
),
IconButton(
icon: Icon(Icons.add),
iconSize: 50,
onPressed: () {
setState(() {
provider.counter++;
});
},
),
],
)),
);
});
}
}
class SecondScreen extends StatelessWidget {
#override
Widget build(BuildContext ctx) {
var pSecond = CommonScreenProvider.of(ctx);
return Scaffold(
appBar: AppBar(
title: Text('My Counter App'),
),
body: Center(
child: StatefulBuilder(builder: (ctx, StateSetter setState) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
IconButton(
icon: Icon(Icons.remove),
iconSize: 50,
onPressed: () {
setState(() {
pSecond.counter--;
});
},
),
Text(
'${pSecond.counter}',
style: Theme.of(ctx).textTheme.display1,
),
IconButton(
icon: Icon(Icons.add),
iconSize: 50,
onPressed: () {
setState(() {
pSecond.counter++;
});
},
),
],
);
}),
),
);
}
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext ctx) {
return CommonScreenProvider(
child: MaterialApp(
home: FirstScreen(),
),
);
}
}