Flutter run async operation on object creation - api

I'm new to flutter and I know it's a very basic question but I've been stuck on this one for three days. I just want to fetch data from an API on object creation. When you run the code it throws an exception But when you Hot Reload it, the async operation starts to work fine. Kindly tell me where I'm wrong. I myself have made extra classes although one should avoid to code with that approach.
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'dart:convert';
void main(){
runApp(
MaterialApp(
title : "Quake",
home : HomePage()
)
);
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
void initState() {
super.initState();
dataRepository.init();
}
#override
Widget build(BuildContext context) {
return Reading();
}
}
class Reading extends StatefulWidget {
#override
_ReadingState createState() => _ReadingState();
}
class _ReadingState extends State<Reading> {
Map _data = Map();
List _features = List();
#override
void initState() {
super.initState();
_data = dataRepository.getReading();
_features = _data['features'];
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Quake"),
centerTitle: true,
backgroundColor: Colors.black,
),
body : Center(
child : ListView.builder(
itemCount: _features.length,
padding: const EdgeInsets.all(14.5),
itemBuilder: (BuildContext context, int position){
var format = DateFormat.yMMMd("en_US").add_jm();
var _date = format.format( DateTime.fromMicrosecondsSinceEpoch(_features[position]['properties']['time']*1000, isUtc: true));
return Column(
children: <Widget>[
Divider(height : 5.5),
ListTile(
title: Text("$_date",
style: TextStyle(fontSize: 16.0)),
subtitle: Text("${_features[position]['properties']['place']}",
style: TextStyle(fontSize: 13.0)),
leading: CircleAvatar(
backgroundColor : Colors.black,
child : Text("${_features[position]['properties']['mag']}", style: TextStyle( color: Colors.white))
),
onTap: () => _windowOnTapping(context, _features[position]['properties']['title']),
)],);},)));}}
Future _windowOnTapping(BuildContext context, String message){
var alert = AlertDialog(
title: Text("Quakes"),
content: Text(message),
actions: <Widget>[
FlatButton ( child: Text("OK"), onPressed: (){ Navigator.pop(context);})
],
);
showDialog( context: context, builder: (context)=> alert);
}
final DataRepository dataRepository = DataRepository._private();
class DataRepository{
DataRepository._private();
Map _data;
void init() async{
String apiUrl = 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson';
http.Response response = await http.get(apiUrl);
_data = json.decode(response.body);
}
Map getReading(){
return _data;
}
}

Use a FutureBuilder to read the Future and only render the component after it returns, something like this:
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'dart:convert';
void main() {
runApp(MaterialApp(title: "Quake", home: HomePage()));
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Reading();
}
}
class Reading extends StatefulWidget {
#override
_ReadingState createState() => _ReadingState();
}
class _ReadingState extends State<Reading> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Quake"),
centerTitle: true,
backgroundColor: Colors.black,
),
body: FutureBuilder<Map>(
future: dataRepository.getReading(),
builder: (context, snapshot) {
if (snapshot.hasData) {
var features = snapshot.data['features'];
return Center(
child: ListView.builder(
itemCount: features.length,
padding: const EdgeInsets.all(14.5),
itemBuilder: (BuildContext context, int position) {
var format = DateFormat.yMMMd("en_US").add_jm();
var _date = format.format(
DateTime.fromMicrosecondsSinceEpoch(
features[position]['properties']['time'] * 1000,
isUtc: true));
return Column(
children: <Widget>[
Divider(height: 5.5),
ListTile(
title:
Text("$_date", style: TextStyle(fontSize: 16.0)),
subtitle: Text(
"${features[position]['properties']['place']}",
style: TextStyle(fontSize: 13.0)),
leading: CircleAvatar(
backgroundColor: Colors.black,
child: Text(
"${features[position]['properties']['mag']}",
style: TextStyle(color: Colors.white))),
onTap: () => _windowOnTapping(context,
features[position]['properties']['title']),
)
],
);
},
));
} else {
return Text("Loading");
}
}));
}
}
Future _windowOnTapping(BuildContext context, String message) {
var alert = AlertDialog(
title: Text("Quakes"),
content: Text(message),
actions: <Widget>[
FlatButton(
child: Text("OK"),
onPressed: () {
Navigator.pop(context);
})
],
);
showDialog(context: context, builder: (context) => alert);
}
final DataRepository dataRepository = DataRepository._private();
class DataRepository {
DataRepository._private();
Future<Map> getReading() async {
String apiUrl =
'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson';
http.Response response = await http.get(apiUrl);
var data = json.decode(response.body);
print(data);
return data;
}
}

Related

Snapshot.data is null . The method[] was called on null

I am new to flutter and I am trying to call api data in listview builder inside future builder. But I am getting null data in snapshot.
My code is below:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
String token;
SharedPreferences sharedPreferences;
class ContinueW extends StatefulWidget {
#override
_ContinueWState createState() => _ContinueWState();
}
class _ContinueWState extends State<ContinueW> {
Future getTokenValue() async {
SharedPreferences espf = await SharedPreferences.getInstance();
token = espf.getString('tokenvalue');
return token;
}
Future createUser() async {
String url ='http://3.137.182.252:8000/continue-watching';
print('token');
Map<String, String> headers = {
'token': token,
};
await http.get(url, headers: headers).then((response){
print('Entered');
//print(response.body);
var jre= jsonDecode(response.body);
return jre;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FutureBuilder(
future: getTokenValue(),
builder: (BuildContext context,snapshot){
if(snapshot.hasData){
return cbuild();
} else{
return CircularProgressIndicator();
}
},
),
),
);
}
Widget cbuild(){
return new FutureBuilder(
future: createUser(),
builder: (BuildContext context,snapshot) {
if(snapshot.hasData) {
return ListView.builder(
itemBuilder: (context, index) {
return ListTile(
leading: CircleAvatar(
backgroundImage: snapshot.data['thumburl'] != null
? NetworkImage(snapshot.data['thumburl'])
: Container(),),
title: Text(snapshot.data[index]['name']),
subtitle: Text(snapshot.data[index]['description']),
);
},
);
}
else{
return CircularProgressIndicator();
}
}
);
}
}
ListTile(
leading: CircleAvatar(
backgroundImage: snapshot.data[index]['thumburl'] != null
? NetworkImage(snapshot.data[index]['thumburl'])
: Container(),),
title: Text(snapshot.data[index]['name']),
subtitle: Text(snapshot.data[index]['description']),
);
as according to details provided by you. you may be missing [index]with ['thumburl'],
if it's still not working then you need to provide JSON formated data

How do I return a Future<double> in a ListView with Provider?

I am trying to get a Future into a listview using the Provider package, but have been unsuccessful. Can anyone give me some advice or a link that explains how to implement notifylisteners() on a Future that returns a double?
Here is the Future of getPrice():
import 'dart:collection';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:stock_watchlist/stock_service.dart';
class StockData extends ChangeNotifier {
List<Stock> _stocks = [
Stock(symbol: 'AAPL'),
Stock(symbol: 'AMD'),
Stock(symbol: 'TSLA')
];
UnmodifiableListView<Stock> get stocks {
return UnmodifiableListView(_stocks);
}
int get stockCount {
return _stocks.length;
}
void addStock(String symbol, double price, double eps) {
final stock = Stock(symbol: symbol);
_stocks.add(stock);
notifyListeners();
}
void deleteStock(Stock stock) {
_stocks.remove(stock);
notifyListeners();
}
Future<double> getPrice(String symbol) async {
String url =
"https://sandbox.iexapis.com/stable/stock/$symbol/quote/latestPrice?token=Tsk_38ddda0b877a4510b42a37ae713cdc96";
http.Response response = await http.get(url);
double price = double.tryParse(response.body);
return price;
}
Future<double> getEps(String symbol) async {
String url =
"https://sandbox.iexapis.com/stable/stock/$symbol/stats/ttmEPS?token=Tsk_38ddda0b877a4510b42a37ae713cdc96";
http.Response response = await http.get(url);
double eps = double.tryParse(response.body);
return eps;
}
}
Here is where I am trying to input the value of getPrice() into a text widget but it is giving me "Instance of 'Future' instead of the value.
I cannot embed pictures yet
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:stock_watchlist/constants.dart';
import 'package:stock_watchlist/stock_model.dart';
class StockList extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Consumer<StockData>(
builder: (context, stockData, child) {
return ListView.builder(
itemCount: stockData.stockCount,
itemBuilder: (context, index) {
//
final stockIndex = stockData.stocks[index];
//
return ListTile(
title: Text(
stockIndex.symbol,
style: TextStyle(
color: kTextColor,
),
),
subtitle: Text(
stockIndex.price.toString(),
style: TextStyle(
color: kTextColor,
),
),
);
},
);
},
);
}
}
Thank you, I think I figured it out with FutureBuilder. Here is the code I used.
class StockList extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Consumer<StockData>(
builder: (context, stockData, child) {
return ListView.builder(
itemCount: stockData.stockCount,
itemBuilder: (context, index) {
//
final stockIndex = stockData.stocks[index];
//
return ListTile(
title: Text(
stockIndex.symbol,
style: TextStyle(
color: kTextColor,
),
),
subtitle: FutureBuilder(
future: stockData.getPrice(stockIndex.symbol),
builder: (context, snapshot) => Text(
snapshot.data.toString(),
style: TextStyle(
color: kTextColor,
),
),
),
);
},
);
},
);
}
}

How to wait for variable to not equal to null in a future builder (Flutter/Dart)?

I have a simple app with two dart files: main.dart and bukalapak.dart
For demonstration purposes the app only has two Future Text() widgets. Basically one Text widget gets the name of a certain html, the other widget gets the total of the same html. Don't ask why but the future builder for "name" has to be in a separate stateful widget in bukalapak.dart. My question is how can I wait until the html is not null then display the total Text widget, because I can easily just call the url again but that would be doing twice the work. I only want to have to call the http.get once.
Here is the code for main.dart:
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
Bukalapak bukalapak = Bukalapak();
return Scaffold(
appBar: AppBar(
title: Text('data'),
),
body: Container(
child: Column(
children: <Widget>[
RandomWidget(
bukalapak: bukalapak,
),
FutureBuilder(
builder: (context, snapshot) {
return Container(
color: Colors.grey,
height: 28.0,
padding: EdgeInsets.only(left: 20.0),
child: Align(
alignment: Alignment.centerLeft,
child: Text('Total results: ${snapshot.data}')),
);
},
future: bukalapak.getTotal(),
)
],
),
),
);
}
}
The code for bukalapak.dart:
class Bukalapak {
var html;
Future<dynamic> getTotal() async {
// wait until html != null, then perform this
var a = html.querySelectorAll(
'#display_product_search > div.product-pagination-wrapper > div.pagination > span.last-page');
dynamic total = int.parse(a[0].text) * 50;
total = '$total'.replaceAllMapped(
new RegExp(r'(\d{1,3})(?=(\d{3})+(?!\d))'), (Match m) => '${m[1]},');
return total;
}
Future<dynamic> getName() async {
http.Response response = await http.get(
'https://www.bukalapak.com/products/s?from=omnisearch&from_keyword_history=false&page=0&search%5Bkeywords%5D=paper&search_source=omnisearch_organic&source=navbar&utf8=✓');
if (response.statusCode == 200) {
String data = response.body;
html = parse(data);
var nameElement = html.querySelector(
'li.col-12--2 > div.product-card > article > div.product-media > a');
String title = nameElement.attributes['title'];
return title;
} else {
throw Exception('Bukalapak error: statusCode= ${response.statusCode}');
}
}
}
class RandomWidget extends StatefulWidget {
RandomWidget({this.bukalapak});
final Bukalapak bukalapak;
#override
_TextState createState() => _TextState();
}
class _TextState extends State<RandomWidget> {
#override
Widget build(BuildContext context) {
return FutureBuilder(
builder: (context, snapshot) {
return Container(
color: Colors.grey,
height: 28.0,
padding: EdgeInsets.only(left: 20.0),
child: Align(
alignment: Alignment.centerLeft,
child: Text('Name results: ${snapshot.data}')),
);
},
future: widget.bukalapak.getName(),
);
}
}
you can pass any function which notify parent widget to build future.
Following code will help you more:
class DeleteWidget extends StatefulWidget {
#override
_DeleteWidgetState createState() => _DeleteWidgetState();
}
class _DeleteWidgetState extends State<DeleteWidget> {
Bukalapak bukalapak = Bukalapak();
Widget first;
bool isBuild = false;
nowbuildtotal() async {
await Future.delayed(Duration(microseconds: 1));
setState(() {
isBuild = true;
});
}
#override
void initState() {
super.initState();
first = RandomWidget(
bukalapak: bukalapak,
buildnow: nowbuildtotal,
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('data'),
),
body: Container(
child: Column(
children: <Widget>[
first,
isBuild
? FutureBuilder(
builder: (context, snapshot) {
return Container(
color: Colors.grey,
height: 28.0,
padding: EdgeInsets.only(left: 20.0),
child: Align(
alignment: Alignment.centerLeft,
child: Text('Total results: ${snapshot.data}')),
);
},
future: bukalapak.getTotal(),
)
: Container()
],
),
),
);
}
}
class RandomWidget extends StatefulWidget {
RandomWidget({this.bukalapak, this.buildnow});
final Bukalapak bukalapak;
final Function buildnow;
#override
_TextState createState() => _TextState();
}
class _TextState extends State<RandomWidget> {
#override
Widget build(BuildContext context) {
return FutureBuilder(
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
widget.buildnow();
}
return Container(
color: Colors.grey,
height: 28.0,
padding: EdgeInsets.only(left: 20.0),
child: Align(
alignment: Alignment.centerLeft,
child: Text('Name results: ${snapshot.data}')),
);
},
future: widget.bukalapak.getName(),
);
}
}
class Bukalapak {
var html;
Future<dynamic> getTotal() async {
// wait until html != null, then perform this
var a = await html.querySelectorAll(
'#display_product_search > div.product-pagination-wrapper > div.pagination > span.last-page');
dynamic total = int.parse(a[0].text) * 50;
total = '$total'.replaceAllMapped(
new RegExp(r'(\d{1,3})(?=(\d{3})+(?!\d))'), (Match m) => '${m[1]},');
return total;
}
Future<dynamic> getName() async {
print("object");
http.Response response = await http.get(
'https://www.bukalapak.com/products/s?from=omnisearch&from_keyword_history=false&page=0&search%5Bkeywords%5D=paper&search_source=omnisearch_organic&source=navbar&utf8=✓');
if (response.statusCode == 200) {
String data = response.body;
html = parse(data);
var nameElement = html.querySelector(
'li.col-12--2 > div.product-card > article > div.product-media > a');
String title = nameElement.attributes['title'];
return title;
} else {
throw Exception('Bukalapak error: statusCode= ${response.statusCode}');
}
}
}

Can I get the same effect in flutter as the <TouchableOpacity /> in React Native?

I found that in React Native, when using component, pressing the corresponding area can have a opacity effect.
In flutter, we sure can use InkWell widget, but i don't want a rectangle or square. Can we implement the same result using flutter. Cheers!
Use the code below:
import 'package:flutter/material.dart';
class TouchableOpacity extends StatefulWidget {
final Widget child;
final Function onTap;
final Duration duration = const Duration(milliseconds: 50);
final double opacity = 0.5;
TouchableOpacity({#required this.child, this.onTap});
#override
_TouchableOpacityState createState() => _TouchableOpacityState();
}
class _TouchableOpacityState extends State<TouchableOpacity> {
bool isDown;
#override
void initState() {
super.initState();
setState(() => isDown = false);
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTapDown: (_) => setState(() => isDown = true),
onTapUp: (_) => setState(() => isDown = false),
onTapCancel: () => setState(() => isDown = false),
onTap: widget.onTap,
child: AnimatedOpacity(
child: widget.child,
duration: widget.duration,
opacity: isDown ? widget.opacity : 1,
),
);
}
}
Usage:
TouchableOpacity(
child: ....
onTap: () {....}
)
#Shan Liu you are correct that InkWell has its own "splash" effect which makes the rectangle or square you mentioned.
If you don't want that splash effect, use GestureDetector.
In below example, I put a Text inside a GestureDetector, but you can put your widget there instead:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final title = 'InkWell Demo';
return MaterialApp(
title: title,
home: MyHomePage(title: title),
);
}
}
class MyHomePage extends StatelessWidget {
final String title;
MyHomePage({Key key, this.title}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(child: MyButton()),
);
}
}
class MyButton extends StatefulWidget {
#override
MyButtonState createState() {
return MyButtonState();
}
}
class MyButtonState extends State<MyButton> {
bool isTappedDown = false;
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
},
onTapDown: (tapDownDetails) {
setState(() {
isTappedDown = true;
});
},
onTapUp: (tapUpDetails) {
setState(() {
isTappedDown = false;
});
},
child: Text(
'Flat Button',
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
color: isTappedDown ? Colors.black.withOpacity(0.5) : Colors.black),
),
);
}
}
I think you'll need to combine a gesture detector and an opacity animation. I couldn't find a ready to use example. But here is the example for opacity animation.
Flutter opacity animation
Here's a touchable class I created. (You could easily add transparency here)
class Touchable extends StatelessWidget {
final Widget child;
final Function() onPress;
final double borderRadius;
final double padding;
const Touchable(
{Key key, this.child, this.onPress, this.borderRadius, this.padding})
: super(key: key);
#override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: BorderRadius.circular(borderRadius),
child: Material(
color: Colors.transparent,
child: InkWell(
child: Padding(
padding: EdgeInsets.all(padding),
child: child,
),
onTap: this.onPress),
),
);
}
}

how to save and load shared preference towards an other page in flutter

I tried to Save and share a variable Phone number string from a tabbar page to homepage. Currently my variable is display only after reload. I tried to display variable just after saved it.
my code :
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _variable;
#override
void initState() {
super.initState();
_loadvariable();
}
_loadvariable() async { // load variable
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
_variable = (prefs.getString('variable'));
}
);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
bottomNavigationBar: BottomAppBar(
color: Colors.blue,
elevation: 20.0,
child: ButtonBar(
alignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(Icons.phone),
color: Colors.white,
onPressed: () {
Navigator.push(
context,
new MaterialPageRoute(builder: (context) => new Phone_Page()),
);
},
),
],
),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
'$_variable',
style: Theme.of(context).textTheme.display1,
),
],
),
),
);
}
}
here is my seconde page class, I can clic on the phone icon to show a dialog box, and I can write on the text field. After clic on save button my textfield is save, the dialog box is close and my variable is display on the card. But after return on the Homepage my variable isn't display. I need to reload the app to display it :(
class Phone_Page extends StatefulWidget {
#override
Phone_PageState createState() => Phone_PageState();
}
class Phone_PageState extends State<Phone_Page> {
final TextEditingController controller = new TextEditingController();
String _variable;
_loadvariable() async { // load variable
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
_variable = (prefs.getString('variable'))?? "";
});
}
_savevariable() async { // save variable
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
prefs.setString('variable', controller.text);
});
}
_deletevariable() async { //delete variable
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
prefs.remove('variable');
});
}
#override
void initState() {
super.initState();
_loadvariable()?? "";
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Phone"),
),
body: new Center(
child: new ListView(
children: <Widget>[
new Card(
child: new Container(
padding: const EdgeInsets.all(20.0),
child: new Row(
children: [
new Expanded(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
new Text(
'$_variable',
style: new TextStyle(
color: Colors.grey[500],
),
),
],
),
),
new IconButton(
icon: new Icon(Icons.add_call),
onPressed: ()
{
_showDialog();
}
),
new IconButton(
icon: new Icon(Icons.delete),
onPressed: () { setState(() {
_deletevariable();
_savevariable();
_loadvariable();
}
);
},
),
],
),
),
),
]
)
)
);
}
_showDialog() async {
await showDialog<String>(
context: context,
child: new AlertDialog(
// contentPadding: const EdgeInsets.all(16.0),
content: new Row(
children: <Widget>[
new Expanded(
child: new TextField(
controller: controller,
autofocus: true,
decoration: new InputDecoration(
labelText: 'number', hintText: '06 - - - - - - - -'),
// keyboardType: TextInputType.number,
),
)
],
),
actions: <Widget>[
new FlatButton(
child: const Text('save'),
onPressed: (){
setState(() { {
_savevariable();
Navigator.pop(context);
}
}
);
}
)
],
),
);
}
}
To achieve what you want, you need to call _loadvariable() function of class MyHomePage from PhonePage class. To do that:
Refactor and remove _ from _loadvariable() and _MyHomePageState so that it won't be private anymore.
Pass MyHomePageState class instance to PhonePage as follows:
Navigator.push(
context,
new MaterialPageRoute(builder: (context) => new PhonePage(
myHomePageState: this,
)),
);
Call loadvariable() in _savevariable() like
_savevariable() async {
// save variable
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
prefs.setString('variable', controller.text);
});
widget.myHomePageState.loadvariable();
}
Make sure the myHomePageState type is var so that you won't get type error:
class PhonePage extends StatefulWidget {
var myHomePageState;
PhonePage({this.myHomePageState});
#override
PhonPageState createState() => PhonPageState();
}