How to hit an API when time is 00:00 in Flutter? - flutter

I am working on my first Flutter App. There is an Activity/Screen which is showing a countdown time. I want, when time is 00:00 then hit an API.
I tried and search on it but i didn't find anything best about this problem.
Please tell me how to resolve this ?
Thank you.
String get timerString {
Duration duration = controller.duration * controller.value;
return '${duration.inMinutes}:${(duration.inSeconds % 60).toString().padLeft(2, '0')}';
}
String time;
String topicName;
Future<String> getTime() async{
final response = await http.post(Constant.TestTime,
body: {
"topic_id" : widget.valueTopicId,
});
Map<String,dynamic> respons = jsonDecode(response.body);
setState(() {
time=respons['test_time'];
topicName=respons['topic_name'];
controller = AnimationController(
vsync: this,
duration: Duration(minutes:int.parse(time) ,seconds: 00),
);
if (controller.isAnimating)
controller.stop();
else {
controller.reverse(
from: controller.value == 0.0
? 1.0
: controller.value);
}
});
print(respons.toString());
setState(() {
isLoading=false;
});
}
Widget _buildAppBar (BuildContext context){
return PreferredSize (preferredSize: Size.fromHeight(MediaQuery.of(context).size.height * 0.085),
child: AppBar(
backgroundColor: Colors.blue,
title: Text("Questions"),
centerTitle: true,
iconTheme: IconThemeData(
color: Colors.white
),
actions: <Widget>[
new Container(
margin: const EdgeInsets.only(top: 25.0, left: 25.0),
child: new Text(topicName,
style: TextStyle(color: Colors.white, fontSize: 26,
fontWeight: FontWeight.bold),),
),
SizedBox(width: 20),
new Padding(padding: EdgeInsets.all(20.0)),
new Padding(padding: EdgeInsets.only(bottom: 40, top: 50)),
Expanded(
flex: 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Align(
alignment: FractionalOffset.center,
child: AspectRatio(aspectRatio: 1.0,
child: Stack(
children: <Widget>[
Positioned.fill(child:
AnimatedBuilder(
animation: controller,
builder: (BuildContext context,
Widget child) {
return Padding(
padding: const EdgeInsets.all(5.0),
child: CustomPaint(
painter: TimerPainter(
animation: controller,
backgroundColor: Colors.white,
color: Colors.blue,
),
),
);
},
),
),
Align(
alignment: FractionalOffset.center,
child: Column(
mainAxisAlignment: MainAxisAlignment
.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment
.center,
children: <Widget>[
AnimatedBuilder(
animation: controller,
builder: (BuildContext context,
Widget child) {
return Text(
timerString, style: TextStyle(
color: Colors.white),
);
}
)
],
),
)
],
),
)
),
),
],
)
)
],
) ,);
}
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: onBackPressed,
child: isLoading
? Center(child: CircularProgressIndicator(),)
:MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
resizeToAvoidBottomPadding: false,
appBar: _buildAppBar(context),
body: Questions(widget.valueTopicId,widget.noOfQuestions,widget.difficulty,time),
)
),
);
}
}
Here i posted my code and an API getTime() is hitting on initState(). So, when my time is 00:00 then an another API should hit. I tried with FutureBuilder but it did not work. May be I did something wrong but so confusing in this.

You can user Timer, you need to import dart:async
Timer(Duration(seconds: 5), () {
getTime();
});

You, need to register your timer in initState.
Timer.periodic() will be executed at a particular duration after specified time.
Timer _timer;
#override
void initState()
{
_timer = Timer.periodic(
const Duration(seconds: 1), (Timer t) => handleAPICall(),
);
super.initState();
}
#override
void dispose()
{
_timer?.cancel();
super.dispose();
}
void handleAPICall()
{
// here you need to check if its time to make the API call.
// I am assuming that you will have some datetime that will tell you
// if duration time is 00:00
if(duration_time == 00:00) // you need to write your correct logic
{
// then, make the HTTP Call.
}
}

Related

Audio composing dashboard with flutter

I m trying to create the following view on my app, other area are done but now comes to the core feature of the app, which allows people to record the audio and stack other audio on top of the one that has been recorded, before going on the hard parts of recording and margin or trim the audios, I am stuck on the view, plz anyone who can shade a light on this will be appreciated. spare the bottom navigation bar, that one has no issue, only the timeline board.
here the view that I just prototyped.
Here some code that I've tried to play with but failed.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class Studio extends StatefulWidget {
const Studio({Key? key}) : super(key: key);
#override
_Studio createState() => _Studio();
}
class _Studio extends State<Studio> with SingleTickerProviderStateMixin {
late AnimationController _controller;
double _time = 0.0, _scale = 1.0;
int _minutes = 0;
int _seconds = 0;
#override
void initState() {
super.initState();
_controller =
AnimationController(vsync: this, duration: Duration(seconds: 60));
_controller.addListener(() {
setState(() {
_time = _controller.value;
_minutes = (_time * 60).floor();
_seconds = ((_time * 60) % 1 * 60).floor();
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Timeline'),
),
body: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 12,
itemBuilder: (context, index) {
return Container(
width: 50,
height: 50,
margin: EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(8),
),
child: Center(
child: Text('$index'),
),
);
},
),
),
Container(
padding: EdgeInsets.all(8),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('$_minutes'),
Text(':'),
Text('$_seconds'),
],
),
),
ElevatedButton(
onPressed: () {
if (_controller.isAnimating) {
_controller.stop();
} else {
_controller.forward();
}
},
child: Text(_controller.isAnimating ? 'Stop' : 'Start'),
),
],
),
);
}
void _onScaleStart(ScaleStartDetails details) {
print(details);
setState(() {
//_scale = details.focalPoint;
});
}
void _onScaleUpdate(ScaleUpdateDetails details) {
setState(() {
_scale = details.scale;
});
}
Widget _buildTimeline() {
return Container(
height: 40,
child: Row(
children: <Widget>[
_buildTimelineMinute(0),
_buildTimelineMinute(5),
_buildTimelineMinute(10),
],
),
);
}
Widget _buildTimelineHour(int hour) {
return Container(
width: 10,
color: Colors.green,
child: Center(
child: Text(
"$hour:00",
style: TextStyle(color: Colors.black, fontSize: 12),
),
),
);
}
Widget _buildTimelineMinute(int minute) {
return Container(
width: 10,
color: Colors.green,
child: Center(
child: Text(
"$minute",
style: TextStyle(color: Colors.black, fontSize: 12),
),
),
);
}
}
Thank you

await http.get(url) does not work even in StatefulWidget

2 days ago, I asked the solution of my problem in this post and got answer to make another statefulwidget and use http codes. So my code became :
class _post_openState extends State<post_open> {
void initState() {
super.initState();
// Enable virtual display.
if (Platform.isAndroid) WebView.platform = AndroidWebView();
// else if(Platform.isIOS)WebView.platform =
}
#override
Future <String> _scrap_title(url_received) async
{
var elements;
url_received = url_received.split(' ')[-1];
if (url_received.split(':')[0] !='https')
url_received = 'https://' + url_received;
print('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%');
print(url_received);
bool suc = false;
// Future.delayed(Duration.zero,() async {
print('response init');
if (url_received == '' || url_received == ' ') return 'No reference';
final url = Uri.parse(url_received);
print('response parsed');
final resp = await http.get(url);
print('response on');
print(resp.statusCode);
if (resp.statusCode == 200) {
dom.Document doc = parser.parse(resp.body);
elements = doc.querySelector('title');
suc = true;
}
//}
//);
return Future.value(elements!.text);
}
Widget build(BuildContext context){
String reference = widget.data_received[5];
bool leftright = widget.data_received[0];
String content = widget.data_received[1];
String writer = widget.data_received[2];
int like = widget.data_received[3];
int shared = widget.data_received[4];
print(widget.data_received);
print('**************************************');
void Function()? _showWeb(String title, String url)
{
showDialog(
context: context,
builder: (context) {
return Container(
height: MediaQuery.of(context).size.height*0.9,
width: MediaQuery.of(context).size.width*0.95,
padding: EdgeInsets.symmetric(horizontal: 3),
//
child:
Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)
), //this right here
child:
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(padding: EdgeInsets.symmetric(vertical: 10)),
Text(title),
Padding(padding: EdgeInsets.symmetric(vertical: 3)),
Container(height:2,color:Colors.brown),
Container(
height: MediaQuery.of(context).size.height*0.7,
width: MediaQuery.of(context).size.width*0.9,
padding: EdgeInsets.symmetric(horizontal: 5),
child:
Expanded(
child:WebView(
initialUrl: url,
javascriptMode: JavascriptMode.unrestricted,
),
),
),
Container(height:2,color:Colors.brown),
Padding(padding: EdgeInsets.symmetric(vertical: 3)),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
TextButton.icon(onPressed: (){
setState(){
};
}, icon:Icon(Icons.thumb_up_alt_outlined),label: Text('like'),style: TextButton.styleFrom(primary: Colors.brown)),
GestureDetector(
onTap: (){
Navigator.pop(context);
},
child:Container
(
width: MediaQuery.of(context).size.width*0.4,
height: 30,
color:Colors.amber,
child:Text('Back',style: TextStyle(fontSize:20,color: Colors.white),
textAlign: TextAlign.center,)
),
),
TextButton(onPressed: (){
setState(){
};
}, child: Icon(Icons.share),style: TextButton.styleFrom(primary: Colors.brown)),
],
),
],
)
)
);
});
}
return
Scaffold(
resizeToAvoidBottomInset: true,
appBar: AppBar(
backgroundColor: Colors.white,
toolbarHeight: 1.0,
),
body:
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Align(
alignment: Alignment.topLeft,
child: SizedBox(
height: 40,
width: 40,
child:
TextButton(onPressed: () {
Navigator.pop(context);
},
style: TextButton.styleFrom(primary: Colors.brown,),
child: Icon(Icons.arrow_back)
),
),
),
Padding(padding: EdgeInsets.symmetric(vertical: 5)),
FutureBuilder<String>(
future: _scrap_title(reference),
builder: (BuildContext context, AsyncSnapshot snapshot){
print('snapshot status'+ snapshot.hasData.toString());
if (snapshot.hasData == false) {
return CircularProgressIndicator();
}
else
return GestureDetector(onTap: (){
_showWeb(writer, reference);
},
child:Text(snapshot.data,style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),),
);
}),
Padding(padding: EdgeInsets.symmetric(vertical: 5)),
Container(
height:1,
color: Colors.brown,
),
Padding(padding: EdgeInsets.symmetric(vertical: 5)),
Text(content,style: TextStyle(color:Colors.black87,fontSize: 15)),
]
)
);
}
}
But strangely, testing by print told me that this class does not even call _scrap_title.
I am having confusion of understanding lifecysle of widget/future/async and so on. Why do I keep failing to scrap html title of a web ? PLEASE somebody give me solution. Thank you so much.
Can you try replacing #override
///#override remove it
Future <String> _scrap_title(url_received) async
{....}
#override //add it here
Widget build(BuildContext context){
also better practice put variable outside the build method, you can use initState or use late
late String reference = widget.data_received[5];
late bool leftright = widget.data_received[0];
....
#override
Widget build(BuildContext context){
More about StatefulWidget

Future Builder not building

I'm trying to include FutureBuilder but it goes into the CircularProgressIndicator() and doesn't load the actual screen code after the value of 'time' is populated by calling from SharedPreferences and the ConnectionState is done. It just gets stuck in the CircularProgressIndicator().
What am I missing here?
Future<int> getTime() async {
await MySharedPreferences.instance.getIntValue("time_key").then((value) =>
setState(() {
time= value;
}));
return time;
#override
void initState() {
super.initState();
MySharedPreferences.instance
.getStringValue("title_key")
.then((value) => setState(() {
title = value;
}));
controller =
AnimationController(vsync: this,
duration: Duration(
seconds: time));
controller2 =
AnimationController(vsync: this,
duration: Duration(
seconds: time));
controller3 =
AnimationController(vsync: this,
duration: Duration(
seconds: 1));
....}
#override
Widget build(BuildContext context){
return WillPopScope(
onWillPop: () async => false,
child: Scaffold(
backgroundColor: Colors.black,
body: FutureBuilder<int>
(
future: getTime(),
builder: ( BuildContext context, AsyncSnapshot<int> snapshot) {
print(snapshot);
print(time);
if (snapshot.connectionState == ConnectionState.done) {
print(time);
return SafeArea(
minimum: const EdgeInsets.all(20.0),
child: Stack(
children: <Widget>[
Container(
child:
Align(
alignment: FractionalOffset.topCenter,
child: AspectRatio(
aspectRatio: 1.0,
child: Container(
height: MediaQuery
.of(context)
.size
.height / 2,
width: MediaQuery
.of(context)
.size
.height / 2,
decoration: BoxDecoration(
//shape: BoxShape.rectangle,
color: Colors.black,
image: DecorationImage(
image: AssetImage(
"assets/images/moon.png"),
fit: BoxFit.fill,
)
),
),
),
),
),
build_animation(),
],
),
);
}
else {
return CircularProgressIndicator();
}
}
),
),
);
}
build_animation() {
return AnimatedBuilder(
animation: controller,
builder: (context, child) {
return Stack(
children: <Widget>[
Padding(
padding: EdgeInsets.all(0.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(
child: Align(
alignment: FractionalOffset.bottomCenter,
child: AspectRatio(
aspectRatio: 1.0,
child: Stack(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top:MediaQuery.of(context).size.height / 6),
child: Column(
children: <Widget>[
Text(
title.toString(),
style: TextStyle(
fontSize: 20.0,
color: Colors.black,fontWeight: FontWeight.bold,),
),
new Container(
child: new Center(
child: new Countdown(
animation: new StepTween(
begin: time,
end: 0,
).animate(controller),
.....
For starters, you do not need to setState for the result of the Future you use with a FutureBuilder. The whole point of the FutureBuilder class is to handle that for you. Also, it's best to not mix .then() and await until you have more experience. They work well together, but concentrate at one concept at a time while you are still learning.
This is your method after it's trimmed down (your choice if that's still worth a method, or if your want to put that code into iniState directly):
Future<int> getTime() async {
final value = await MySharedPreferences.instance.getIntValue("time_key");
return value;
}
You should not give that method to your FutureBuilder, otherwise you will start it anew every time build is called for any reason.
So you initState should look like this:
Future<int> futureIntFromPreferences;
#override
void initState() {
super.initState();
futureIntFromPreferences = getTime();
}
Then you can use that in your FutureBuilder:
body: FutureBuilder<int>(
future: futureIntFromPreferences,
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
For a detailed explanation, read What is a Future and how do I use it?

Flutter - The method '|' was called on null. After hot reload it is working

I am pretty new in flutter. I don't know what happening in background because after hot reload its work fine. On another dart files that happens, firebase dont provide me data on initialization just after hot reload.
class CityServices {
getCites() {
return Firestore.instance.collection('cities').getDocuments();
}
}
class _HomeScreenState extends State<HomeScreen> {
bool citiesFlag = false;
var cities;
int citiesCount;
String actualCity;
Maybe mistake is here.
#override
void initState() {
super.initState();
CityServices().getCites().then((QuerySnapshot) {
if (QuerySnapshot.documents.isNotEmpty) {
citiesFlag = true;
cities = QuerySnapshot.documents;
citiesCount = QuerySnapshot.documents.length;
}
});
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: MyColors.vintageGreen,
appBar: AppBar(
backgroundColor: MyColors.background,
title: Center(
child: Text(
'Válasszon települést...',
style: GoogleFonts.barlowCondensed(
color: MyColors.appbarText,
fontSize: 26.0,
fontWeight: FontWeight.w500),
),
),
),
body: Center(
child: Container(
child: GridView.count(
crossAxisCount: 2,
children: List.generate(citiesCount, (index) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
),
child: InkWell(
onTap: () {
actualCity = cities[index]['city_name'];
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
CityView(cityName: actualCity)),
);
},
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
title: Center(
child: Text(
cities[index]['city_name'],
style: TextStyle(
fontWeight: FontWeight.w500, fontSize: 18.0),
)),
subtitle: Center(child: Text('22 bejegyzés')),
),
Flexible(
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(5)),
child: Padding(
padding: EdgeInsets.only(bottom: 15.0),
child: Image(
image: AssetImage(
cities[index]['img_path'],
),
),
),
),
)
],
),
),
color: MyColors.background,
);
}),
),
),
),
),
);
}
}
Maybe here is the mistake? Should it be on top of dart file?
class HomeScreen extends StatefulWidget {
static const String id = 'home';
#override
_HomeScreenState createState() => new _HomeScreenState();
}
Let me explain the issue and why it is happening, then propose few solutions.
inside initState you are calling CityServices().getCites().then... which is an async method.
However, when your widget is built for the first time, the data you expect from Firestore is not ready yet, thus you get null for both cities and citiesCount.
Short term solution:
make sure there is null check, display indicator while waiting for the data.
body: Center(
child: (cities == null) ?
CircularProgressIndicator()
: Container(...
Additionally, you can also refactor your initState to something like this
void getCities() async {
var snapshot CityServices().getCites();
setState(() {
citiesFlag = true;
cities = snapshot.documents;
citiesCount = snapshot.documents.length;
});
}
#override
void initState() {
getCities();
super.initState();
}
Long term solution:
use BLoC pattern and make data loading decoupled from UI.
see flutter_bloc for how to implement it.

AppBar in flutter

I have designed a news application in flutter where I have an app bar with tabs following it. In the tabbarview I have a list of news. on click of the news, it will show details description and image of the news(as shown in the image). When I try to put the app bar in that file. Two app bar appears. What would the possible way sort it out?
Here is the code:
appBar: AppBar(
title: Text(""),
backgroundColor: Color(0xFF125688), //#125688 //FFFF1744
actions: <Widget>[
Container(
alignment: Alignment.topRight,
child: FlatButton(
onPressed: () {},
padding: EdgeInsets.fromLTRB(0, 10.0, 8.0, 0),
child: Text(
date,
style: TextStyle(
color: Colors.white,
),
)),
)
],
bottom: TabBar(
tabs: <Widget>[
Tab(text: "TOP-HEADLINES"),
Tab(text: "LATEST-NEWS"),
Tab(text: "SPORTS"),
Tab(text: "CRIME-NEWS"),
],
isScrollable: true,
),
),
body: TabBarView(children: [
TopHeadlines(),
LatestNews(),
Sports(),
CrimeNews(),
],
),
CODE FOR TOPHEADLINES()
class TopHeadlines extends StatefulWidget {
int index;
String value_image,value_description,value_title;
TopHeadlines({Key key,this.value_image,this.value_description,this.value_title,this.index}) : super(key:key);
#override
_topHeadlines createState() => _topHeadlines();
}
class _topHeadlines extends State<TopHeadlines> {
List<News> dataList = List();
bool _isLoading = false;
BuildContext context1;
Future<String> loadFromAssets() async {
DateTime oops = DateTime.now();
String d_date = DateFormat('ddMMyyyy').format(oops);
var url = 'https://www.example.com/json-12.json';
print(url);
var response = await http
.get('$url', headers: {"charset": "utf-8", "Accept-Charset": "utf-8"});
String utfDecode = utf8.decode(response.bodyBytes);
return utfDecode;
}
Future loadyourData() async {
setState(() {
_isLoading = true;
});
String jsonString = await loadFromAssets();
String newStr = jsonString.substring(1, jsonString.length - 1);
print(newStr);
Map newStringMap = json.decode(newStr);
var list = new List();
newStringMap.forEach((key, value) {
list.add(value);
});
for (var newsList in list) {
var news = News.fromJson(newsList);
dataList.add(news);
}
print('This is the length' + dataList.length.toString());
print(dataList[0].title);
setState(() {
_isLoading = false;
});
}
#override
void initState() {
super.initState();
loadyourData();
}
#override
Widget build(BuildContext context) {
DateTime oops = DateTime.now();
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Container(
child: _isLoading ? Center(
child: CircularProgressIndicator(),) :
ListView.builder(
itemCount: dataList.length, itemBuilder: (context, index) {
return SizedBox(
height: 130.0,
child: Card(
color: Colors.white,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
InkWell(
onTap: (){
// dataList;
Navigator.push(context, MaterialPageRoute(builder: (context) {
print(index);
return Newsdetail(value_image: dataList[index].image,value_description: dataList[index].description,value_title: dataList[index].title, );
}));
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Expanded(
child: Image.network(
dataList[index].image,
height: 92.5,
width: 75.0,
)),
Expanded(
child: Text(
dataList[index].title,
style: TextStyle(
//title
fontSize: 15.0, color: Colors.grey,
),
),
)
],
),
),
),
],
),
),
);
},
),
));
}
}
Remove the appBars from these views:
TopHeadlines(),
LatestNews(),
Sports(),
CrimeNews(),
Only return the Content you want to display by return a Container or the widget you want to display