Flutter, DateTime.now() is not working in my code - flutter

I've been developing an application for both iOS and Android.
The code below makes real-time screen which shows current time.
1.I confirmed that DateTime.now() is working on both OS.
2.Also i confirmed that it is working at the actual Android device and Android emulator.
But everytime when i am trying to test on iOS(both emulator and actual device), _timeString always get a null.
What is wrong with this code? I don't get it.
Here is my environment in advance for solving my question.
VMware workstation 15 Player, Xcode 10.3, Android Studio 3.4.2
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:intl/intl.dart';
class TableLayout extends StatefulWidget {
#override
_TableLayoutState createState() => _TableLayoutState();
}
class _TableLayoutState extends State<TableLayout> {
String _timeString;
String _formatDateTime(DateTime dateTime) {
return DateFormat('MM/dd/yyyy HH:mm:ss').format(dateTime);
}
#override
void initState() {
_timeString = _formatDateTime(DateTime.now());
Timer.periodic(Duration(milliseconds: 1000), (Timer t) => _getTime());
super.initState();
}
void _getTime() {
DateTime _now = DateTime.now();
final String formattedDateTime = _formatDateTime(_now);
if (this.mounted) {
setState(() {
_timeString = formattedDateTime;
});
}
}
#override
Widget build(BuildContext context) {
return
Scaffold(
body:
Container(
child:
Text("\n\n\n\n${_timeString}")
)
);
}
}

Try this by changing date format
To
MM/dd/yyyy hh:mm:ss

I ran your code without any change. (Added a entry point however)
and it works as expected.
Any additional information regarding the intl package will be helpful. Here is my entire app and the result of that below.
My dependency is intl: ^0.15.8.
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:intl/intl.dart';
void main()
{
runApp(SampleApp());
}
class SampleApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Sample App',
home: TableLayout(),
);
}
}
class TableLayout extends StatefulWidget {
#override
_TableLayoutState createState() => _TableLayoutState();
}
class _TableLayoutState extends State<TableLayout> {
String _timeString;
String _formatDateTime(DateTime dateTime) {
return DateFormat('MM/dd/yyyy HH:mm:ss').format(dateTime);
}
#override
void initState() {
_timeString = _formatDateTime(DateTime.now());
Timer.periodic(Duration(milliseconds: 1000), (Timer t) => _getTime());
super.initState();
}
void _getTime() {
DateTime _now = DateTime.now();
final String formattedDateTime = _formatDateTime(_now);
if (this.mounted) {
setState(() {
_timeString = formattedDateTime;
});
}
}
#override
Widget build(BuildContext context) {
return
Scaffold(
body:
Container(
child:
Text("\n\n\n\n${_timeString}")
)
);
}
}
App running on IOS simulator

Related

Flutter bloc state is not emitting or updating. Method mapEventToState is never called

The following code was working before null safety with flutter_bloc 4.0.1 but after null safety migration the state is not updating / emitting / broadcasting as expected with flutter_bloc 7.3.3.
The below _reactToState and mapEventToState methods are never called. How can I fix it?
Splash Screen
class SplashScreen extends StatefulWidget {
final Strapper strapper;
final Service? service;
SplashScreen(this.strapper, this.service);
#override
State<StatefulWidget> createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
SplashBloc? _splashBloc;
#override
void didChangeDependencies() {
super.didChangeDependencies();
if (_splashBloc == null) {
_splashBloc = SplashBloc(widget.strapper, widget.service);
_splashBloc!.stream.listen(_reactToState);
}
}
#override
dispose() {
_splashBloc?.close();
_splashBloc = null;
super.dispose();
}
#override
Widget build(BuildContext context) {
return BlocProvider<SplashBloc>(
create: (context) => _splashBloc!,
child: BlocBuilder<SplashBloc, SplashBlocState>(
builder: (context, state) => Container(
child: Stack(
children: <Widget>[
LogoPanel(
_showWidgetForState(state),
),
],
),
),
),
);
}
void _reactToState(SplashBlocState state) {
if (state is InitializingSplashBlocState) {
if (widget.logOut) {
_splashBloc!.add(LogoutSplashBlocEvent());
} else {
_splashBloc!.add(CInitializationSplashBlocEvent());
}
} else if (state is AuthSuccessSplashBlocState) {
App.navigateToSomewhere(context, state.isNewUser);
}
}
Widget _showWidgetForState(SplashBlocState state) {
if (state is InitializingSplashBlocState) {
return _getProgressIndicator();
} else if (state is ChooseSomethingSplashBlockState ) {
return _showSignInWidget();
}
}
}
Splash Bloc
class SplashBloc extends Bloc<SplashBlocEvent, SplashBlocState> {
final Strapper? strapper;
final Service? service;
SplashBloc(this.strapper, this.service) : super(InitializingSplashBlocState());
#override
Stream<SplashBlocState> mapEventToState(event) async* {
if (event is CInitializationSplashBlocEvent) {
await strapper!.run();
}
bool chooseSomething = !service!.hasSomeSelection;
if (chooseSomething) {
yield ChooseSomethingSplashBlockState();
} else if (event is RAuthSplashBlocEvent) {
yield AuthSplashBlocState();
var authState = await _run();
yield authState;
}
}
Future<SplashBlocState> _run() async {
// Do something
}
}
Splash Bloc Event
abstract class SplashBlocEvent extends Equatable {
const SplashBlocEvent();
#override
List<Object> get props => [];
}
class CInitializationSplashBlocEvent extends SplashBlocEvent {}
class RAuthSplashBlocEvent extends SplashBlocEvent {}
Splash Bloc State
abstract class SplashBlocState extends Equatable {
const SplashBlocState();
#override
List<Object> get props => [];
}
class InitializingSplashBlocState extends SplashBlocState {}
class AuthSplashBlocState extends SplashBlocState {}
class ChooseSomethingSplashBlockState extends SplashBlocState {}
class AuthSuccessSplashBlocState extends SplashBlocState {
final CurrentUser? user;
final bool isNewUser;
AuthSuccessSplashBlocState(this.user, this.isNewUser);
}
As per the documentation:
In v6.0.0, the above snippet does not output the initial state and only outputs subsequent state changes. The previous behavior can be achieved with the following:
final bloc = MyBloc();
print(bloc.state);
bloc.listen(print);
So I changed my code in the Splash screen as following:
#override
void didChangeDependencies() {
super.didChangeDependencies();
if (_splashBloc == null) {
_splashBloc = SplashBloc(widget.strapper, widget.service);
_reactToState(_splashBloc!.state); // Added this line
_splashBloc!.stream.listen(_reactToState);
}
}
And that's it. It worked!
_reactToState and mapEventToState are definitely being called.
when you use Streamcontrollers it greatly simplifies state. I build a bloc code to manage state. The materialapp child is the splashWidget whose job is to render the hour, minute, second from bloc code emitting Time state. If the user clicks the splash screen or 5 seconds elapses the splash screen will be replaced with the HomePageWidget. bloc code controls the starting and stopping of the timer using an timerState event.
'package:flutter/material.dart';
import 'bloc_splash.dart';
import 'main.dart';
class SplashWidget extends StatelessWidget {
const SplashWidget({Key? key}) : super(key: key);
_redirectToHome(BuildContext context)
{
Navigator.pushReplacement(context,MaterialPageRoute(builder:(_)=>MyHomePage(title:"helloWorld")));
}
String _displayClock(Time ? data)
{
String retVal="";
if (data!=null)
{
retVal="Time: ${data.hour} : ${data.minute} : ${data.second}";
}
return retVal;
}
#override
Widget build(BuildContext context) {
SplashBloc _bloc=SplashBloc();
_bloc.timerOnChange(StartTimer());
return Scaffold(
body:InkWell(
onTap: (){_bloc.timerOnChange(StopTimer());
_redirectToHome(context);
},
child:Container(
child:
StreamBuilder<TimeState>(
stream:_bloc.timeStream,
builder:(context,snapshot)
{
if(snapshot.hasData && (snapshot.data is RedirectState))
{
return MyHomePage(title:"helloWorld");
}
return Center(child:Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Splash Screen", style:TextStyle(fontSize: 24,fontWeight: FontWeight.bold)),
Text(_displayClock(snapshot.data?.time)),
]));
}
)
))
);
}
}
bloc code
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';
import 'dart:ui';
import 'dart:async';
abstract class TimerEvent extends Equatable{
const TimerEvent();
#override
List<Object>get props=>[];
}
class StartTimer extends TimerEvent{
const StartTimer();
}
class StopTimer extends TimerEvent{
const StopTimer();
}
class Time{
final int hour;
final int minute;
final int second;
Time(this.hour,this.minute,this.second);
}
class TimeState extends Equatable{
final Time time;
TimeState(this.time);
#override
List<Object> get props=>[time];
}
class RedirectState implements TimeState{
final Time time;
RedirectState(this.time);
#override
List<Object> get props=>[time];
#override
// TODO: implement stringify
bool? get stringify => throw UnimplementedError();
}
class TimerState extends Equatable{
final bool started;
const TimerState(this.started);
#override
List<Object> get props => [started];
}
class SplashBloc
{
SplashBloc();
Timer ?_timer;
var countDown=5;
Stream<TimeState> get timeStream=> _timeController.stream;
final _timeController =BehaviorSubject<TimeState>();
void dispose()
{
_timeController.close();
}
void _pushTimeOnTheStream(Timer timer)
{
DateTime now=DateTime.now();
_timeController.sink.add(TimeState(Time(now.hour,now.minute,now.second)));
this.countDown-=1;
if (this.countDown==0)
{
timerOnChange(StopTimer());
_timeController.sink.add(RedirectState(Time(0,0,0)));
}
}
void timerOnChange(TimerEvent event) {
if (event is StartTimer)
{
_timer=Timer.periodic(Duration(seconds: 1),_pushTimeOnTheStream);
}
else if(event is StopTimer){
//_timerController.sink.add(TimerState(false));
_timer?.cancel();
}
}
}
app
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const SplashWidget(),
);
}
}

How to close passCodeScreen after entered a correct password in flutter

I am want to close the passcode screen after I enter the correct password. Here is my code. I separated my code into 3 files.
this is my code in the passcode_bloc. This code I using for processing entered passcode
import 'dart:async';
class PasscodeScreenBloc {
String isValidPasscode = "123456";
final StreamController<bool> verificationNotifier =
StreamController<bool>.broadcast();
void onPasscodeEntered(String enteredPasscode) {
bool isValid;
isValid = isValidPasscode == enteredPasscode;
verificationNotifier.add(isValid);
}
#override
void dispose() {
verificationNotifier.close();
}
}
this is my code passcode_state.
import 'package:flutter/material.dart';
import 'package:passcode_screen/passcode_screen.dart';
import 'passcode_screen_bloc.dart';
class passcodeScreenPage extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return passcodeScreenPageState();
}
}
class passcodeScreenPageState extends State<passcodeScreenPage> {
String title = "Enter you pass word";
PasscodeScreenBloc passcodeScreenBloc = PasscodeScreenBloc();
#override
Widget build(BuildContext context) {
return PasscodeScreen(
title: Text("Enter you pass word"),
passwordEnteredCallback: passcodeScreenBloc.onPasscodeEntered,
cancelButton: Text("Cancel"),
deleteButton: Text("Delete"),
shouldTriggerVerification: passcodeScreenBloc.verificationNotifier.stream,
backgroundColor: Colors.white,
isValidCallback: () => {},
);
}
#override
void dispose() {
passcodeScreenBloc.verificationNotifier.close();
super.dispose();
}
}
I was trying to watch to example code in the link. Almost as the same. It run but not close.

How To Read ModalRoute.of(context).settings.arguments Properly?

I'm confused with flutter, when I want to read arguments from statefulwidget (initstate) and access it into widget build, the variable is still null. how to read it properly? my code is bellow :
import 'package:flutter/material.dart';
import 'package:caritokoonline_v2/components/ResultForm.dart';
import 'package:caritokoonline_v2/podo/SearchBarangRequest.dart';
class ResultBarangActivity extends StatefulWidget {
SearchBarangRequest searchBarangRequest;
#override
_ResultBarangActivityState createState() => _ResultBarangActivityState();
}
class _ResultBarangActivityState extends State<ResultBarangActivity> {
final _scaffoldKey = GlobalKey<ScaffoldState>();
#override
void initState(){
Future.delayed(Duration.zero,(){
setState(() {
widget.searchBarangRequest = ModalRoute.of(context).settings.arguments;
print(widget.searchBarangRequest.keyword);
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
if (widget.searchBarangRequest == null) return Scaffold(); //this line is always executed
return ResultForm(
scaffoldKey: _scaffoldKey,
title: widget.searchBarangRequest.keyword,
subTitle: widget.searchBarangRequest.hargaRange.toString(),);
}
}
Thank!
I know what the mistake,
so, I made global variable (title, subtitle) and assign value from searchBarangRequest like this following code :
String title = "";
String subtitle = "";
class _ResultBarangActivityState extends State<ResultBarangActivity> {
final _scaffoldKey = GlobalKey<ScaffoldState>();
#override
void initState(){
Future.delayed(Duration.zero,(){
setState(() {
widget.searchBarangRequest = ModalRoute.of(context).settings.arguments;
title = widget.searchBarangRequest.keyword;
subtitle = "${Utils().kondisiToString(widget.searchBarangRequest.kondisiBarang)} | ${widget.searchBarangRequest.hargaRange.toString()}";
// print(widget.searchBarangRequest.keyword);
getProducts(widget.searchBarangRequest);
});
});
super.initState();
}
}
and it works perfectly! thank.

How to periodically set state?

I am trying to build a countdown app for special days for example 11 d 2 h 30 m 23s to the new year but I can't reload my state every second so it just shows me the second that I loaded the page I don't know how to dynamically reload the page.
import 'package:flutter/material.dart';
class RopSayac extends StatefulWidget {
_RopSayacState createState() => _RopSayacState();
}
class _RopSayacState extends State<RopSayac> {
var now = DateTime.now().second.toString();
String asd(){
setState(() {
now = DateTime.now().second.toString();
});
return now;
}
#override
Widget build(BuildContext context) {
return Container(
child: new Text(asd()),
);
}
}
This is what I got and it doesn't reload time. I am pretty new on the flutter.
As pskink and Günter mentioned, use a Timer. You can even use the periodic constructor that would fit well your scenario.
Note you don't need the asd() function. When you call setState(), the build method will be called automatically passing the new now property value.
If you want, use initState to set an initial value and, as in this example, setup the Timer.
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(title: 'Timer Periodic Demo', home: RopSayac());
}
}
class RopSayac extends StatefulWidget {
_RopSayacState createState() => _RopSayacState();
}
class _RopSayacState extends State<RopSayac> {
String _now;
Timer _everySecond;
#override
void initState() {
super.initState();
// sets first value
_now = DateTime.now().second.toString();
// defines a timer
_everySecond = Timer.periodic(Duration(seconds: 1), (Timer t) {
setState(() {
_now = DateTime.now().second.toString();
});
});
}
#override
Widget build(BuildContext context) {
return Container(
child: Center(
child: new Text(_now),
),
);
}
}
This recursive method should be enough for what you want. The seconds set as 1 will keep triggering setState each second, thus refreshing your widget tree.
void _timer() {
Future.delayed(Duration(seconds: 1)).then((_) {
setState(() {
print("1 second closer to NYE!");
// Anything else you want
});
_timer();
});
}
There's this excellent library called timer_builder. I think it'll help you out.
Example from the pub page:
import 'package:timer_builder/timer_builder.dart';
class ClockWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return TimerBuilder.periodic(Duration(seconds: 1), //updates every second
builder: (context) {
return Text("${DateTime.now()}");
}
);
}
}
Here's what I do. In my case I'm polling a webservice in _liveUpdate()
void startUpdates(AppState appState) async {
await new Future.delayed(const Duration(milliseconds: 100));
while (true) {
_liveUpdate();
appState.setState(() {});
await new Future.delayed(const Duration(seconds : 15));
}

how to implement in app time out session in flutter

I want to log a user out after a specific amount time the user has not interacted with the app.
I've wrapped the whole child widget in GestureDetector().
Please suggest if this is the best optimised way of doing this.
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new GestureDetector(
onTap: () {
// duration reset's to a specific time
startTimeout([int milliseconds]) { return new Timer(duration, handleTimeout); }
},
child: new HomeWidget(),);
}
void handleTimeOut {
// Log User Out
}
}
You should cancel previous timers before initializing a new one
static Timer _sessionTimer;
#override
Widget build(BuildContext context) {
...
onTap: () {
_sessionTimer?.cancel();
// duration reset's to a specific time
_sessionTimer = new Timer(duration, handleTimeout);
},
If you need something for the web target then better setup a key-up and a mouse-click listener on your index.html's 'body' as follows.
...
<body id = 'myapp-main-content'>
...
Then implement the listeners, here is an example borrowed from Task Tracker (https://github.com/botorabi/TaskTracker/tree/master/src/flutter-app/TaskTracker/lib).
import 'dart:async';
import 'dart:html';
import 'package:TaskTracker/service/authstatus.dart';
import 'package:flutter/material.dart';
import 'config.dart';
import 'navigation.links.dart';
import 'service/service.login.dart';
/// Logout user after long inactivity period.
class SessionTimeoutHandler {
static const MAIN_CONTAINER_ID = 'myapp-main-content';
final GlobalKey<NavigatorState> _navigator;
Timer _sessionTimer;
int _timeoutInSeconds;
static DateTime _timeLeft;
SessionTimeoutHandler(this._navigator, this._timeoutInSeconds);
void installLogoutHandler() {
var body = document.getElementById(MAIN_CONTAINER_ID);
body.addEventListener("click", (event) => resetLogoutTimer());
body.addEventListener("keyup", (event) => resetLogoutTimer());
resetLogoutTimer();
}
/// Return the time left to logout in seconds.
/// If user is not authenticated then 0 is returned.
static int timeLeftInSeconds() {
if ((_timeLeft == null) || !Config.authStatus.authenticated) {
return 0;
}
return ((DateTime.now().millisecondsSinceEpoch - _timeLeft.millisecondsSinceEpoch) / 1000).floor();
}
void resetLogoutTimer() {
_timeLeft = DateTime.now();
_sessionTimer?.cancel();
_sessionTimer = Timer(Duration(seconds: _timeoutInSeconds), _logout);
}
void _logout() {
if (Config.authStatus.authenticated) {
ServiceLogin().logoutUser().then((result) {
Config.authStatus = AuthStatus();
_navigator.currentState.pushNamedAndRemoveUntil(
NavigationLinks.NAV_HOME, (Route<dynamic> route) => false);
});
}
}
}
Then use the SessionTimeoutHandler above in your main widget setup (see initState below).
class AppTaskTracker extends StatefulWidget {
#override
_AppTaskTrackerState createState() => _AppTaskTrackerState();
}
class _AppTaskTrackerState extends State<AppTaskTracker> {
final GlobalKey<NavigatorState> _navigator = GlobalKey<NavigatorState>();
#override
void initState() {
super.initState();
SessionTimeoutHandler(_navigator, Config.LOGOUT_TIMEOUT).installLogoutHandler();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
...
Take into account that SessionTimeoutHandler gets the navigator in order to redirect to home after automatic logout.