I am calling an API on button click but when I click on the button nothing happens. also I want to show a linear progress bar when the user clicks on the button uless/until data gets loaded but it is not working the way I expect it to work. Here is my code. I am a newbie. I am stuck on this problem please someone corrects my code so that it will work the way I expect.
class _MyHomePageState extends State<MyHomePage> {
getFokatKiAdvice() async {
final response =
await http.get(Uri.parse("https://api.adviceslip.com/advice"));
var resp = json.decode(response.body);
print(resp);
return resp['slip']['advice'];
}
@override
void initState() {
super.initState();
getFokatKiAdvice();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
children: [
const Card(
child: ListTile(
title: Text(
"Advice for you !",
textAlign: TextAlign.center,
),
),
),
Card(
child: Column(
children: [
ListTile(
title: FutureBuilder(
future: getFokatKiAdvice(),
builder:
(BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return Text(
snapshot.data,
textAlign: TextAlign.center,
);
} else if (snapshot.hasError) {
return const Text(
"Oye !! Thare pass Internet naahi hn !!");
} else {
return const LinearProgressIndicator();
}
},
),
),
const SizedBox(
height: 5.00,
),
ElevatedButton(
onPressed: () {
getFokatKiAdvice();
// setState(() {});
},
child: const Text("Ghe Advice !"),
),
const SizedBox(
height: 10,
),
],
),
),
],
),
),
),
);
}
}
CodePudding user response:
You just need to make bool
if its loading and getting data, the indicator shows up.
class MyHomePage extends StatefulWidget {
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String data;
bool _isLoading;
getFokatKiAdvice() async {
final response =
await http.get(Uri.parse("https://api.adviceslip.com/advice"));
var resp = json.decode(response.body);
if (response.statusCode != 200) {
data = "Oye !! Thare pass Internet naahi hn !!";
}
print(resp);
setState(() {
data = resp['slip']['advice'];
_isLoading = false;
});
}
@override
void initState() {
_isLoading = true;
getFokatKiAdvice();
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Material App',
home: Scaffold(
body: Center(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
children: [
const Card(
child: ListTile(
title: Text(
"Advice for you !",
textAlign: TextAlign.center,
),
),
),
Card(
child: Column(
children: [
ListTile(
title: _isLoading
? const LinearProgressIndicator()
: Text(
data,
textAlign: TextAlign.center,
)),
const SizedBox(
height: 5.00,
),
ElevatedButton(
onPressed: () {
setState(() {
_isLoading = true;
data = '';
});
getFokatKiAdvice();
},
child: const Text("Ghe Advice !"),
),
const SizedBox(
height: 10,
),
],
),
),
],
),
),
),
),
);
}
}
here is my solution without futureB
here is result
CodePudding user response:
you can make a lazyload
class _MyHomePageState extends State<MyHomePage> {
bool _isLoading= false;
getFokatKiAdvice() async {
setState ({
_isLoading = true;
});
try{
final response =
await http.get(Uri.parse("https://api.adviceslip.com/advice"));
var resp = json.decode(response.body);
print(resp);
return resp['slip']['advice'];
setState ({
_isLoading = false;
)};
} catch (e){
print(e);
setState ({
_isLoading = false;
)};
}
}
.......
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
// create condition when loading show indicator progress, else show content
body: _isLoading ? Center (child: CircularProgressIndicator())
: Center(
child: Padding(
.......
// other code no change needed
CodePudding user response:
Calling this API with small difference of time, provide same result sometimes. Could be issue on caching, but don't know for sure. Adding little delay works find. or checking the current data with previous also make sure not to get duplicate data.
Also use a future variable instead of calling directly inside future.
String? _currentData, newData;
Future<String?> getFokatKiAdvice() async {
do {
await Future.delayed(const Duration(
milliseconds:
100)); // have more loading you can ignore this, but it will call multiple times
newData = await fetchFromApi();
} while (newData == _currentData);
_currentData = newData;
return newData;
}
And on
title: FutureBuilder(
future: _future,
Now to recall the api
ElevatedButton(
onPressed: () {
setState(() {
_future = getFokatKiAdvice();
});
},