Reputation: 644
I basically need to call a function from another page. This is my navigation structure: 1st Screen > 2nd Screen > 3rd Screen.
I have read many topics about my problem already but I can't get the perfect answer yet. I have tried using ScopedModel
and InheritedWidgets
but it requires a Widget on the tree just to pass data.
I am using the Navigator's named routes with pushNamed()
function to push these pages.
Let's say my 1st screen has a listview and a function to refresh it: void refresh()
. How can I call the refresh()
function directly from the 3rd Screen?
Upvotes: 0
Views: 2342
Reputation: 644
I have found the perfect solution already. I have to use the scoped_model package, create a model to be used as the data source for my ListView and it should be automatically updated anywhere in my app if I try to change the values of my model. And a static way of doing it without using a ScopedModelDescendant Widget is by calling this ScopedModel.of<MyModel>(context, rebuildOnChange: true).refresh();
model.dart file
class DataModel extends Model {
bool _loading = false;
String _data = "";
bool get loading => _loading;
String get data => _data;
void refresh() {
this._loading = true;
print("loading...");
notifyListeners();
String url = "https://reqres.in/api/users/2?delay=1";
http.get(url).then((response) {
_loading = false;
print("refreshed data: ${response.body}");
this._data = response.body;
notifyListeners();
});
}
static DataModel of(BuildContext context) =>
ScopedModel.of<DataModel>(context);
}
main.dart file
void main() => runApp(MyApp(model: DataModel()));
class MyApp extends StatelessWidget {
final DataModel model;
const MyApp({Key key, @required this.model}) : super(key: key);
@override
Widget build(BuildContext context) {
return ScopedModel<DataModel>(
model: model,
child: MaterialApp(
title: 'ScopedModel Demo',
routes: {
'/': (_) => MyHomePage(title: 'Home Page'),
'/settings': (_) => SettingsPage(),
},
),
);
}
}
home.dart file
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
// I can fetch new data here statically without the use of the ScopedModelDescendant in the widget tree.
DataModel.of(context).refresh();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: ScopedModelDescendant<DataModel>(
builder: (context, child, model) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(model.loading ? "LOADING..." : ""),
Text("data: ${model.data}"),
// Statically reading the value from the model
RaisedButton(child: Text("Read value statically"), onPressed: () {
String value = DataModel.of(context).data;
print("$value");
},),
RaisedButton(child: Text("Settings"), onPressed: () {
Navigator.pushNamed(context, "/settings");
},)
],
),
);
},
),
floatingActionButton: ScopedModelDescendant<DataModel>(
builder: (context, child, model) {
return FloatingActionButton(
child: Icon(Icons.refresh),
onPressed: () {
// here is the ScopedModelDescendant version of refreshing data
model.refresh();
},
);
},
),
);
}
}
Upvotes: 0
Reputation: 189
You can do this multiple ways Some of the common ways are
Upvotes: 1