Splash screen appears with delay - flutter

I'm trying to implement the flutter Getx plugin and made some splash screen like this one:
class SplashScreen extends StatelessWidget {
const SplashScreen({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return GetBuilder(
init: SplashController(),
builder: (_) => Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
)
);
}
}
Then I wrote a splashcontroller like this one:
class SplashController extends GetxController {
#override
void onReady() {
// TODO: implement onReady
super.onReady();
myFunctionCalculations();
final Controller _controller = Get.put(controller());
List items = _controller.items;
if (items > 0) {
Get.off(OnePlayerScreen());
}
}
}
Now from my HomeScreen I tap a button to navigate to this splash screen. It does nothing more only
onPressed: () {
Get.to(SplashScreen());
}
The thing is that I want to show the circular indicator while my function is running and when it populates the List items to go to the Items Screen, but when I tap the button to get the splash screen it gets a while until the splash screen appear and then immediately goes to the Items screen, because meanwhile it populated the List. When I don't initialize the function it get immediately to the splash screen and I see the indicator.
Why I get this functionality? I thought it's supposed to show the loading indicator and meanwhile populate the List. But it seems when I tap the button from HomeScreen the function is initialized and when its donde the splashcreen appears.
What am I doing wrong?

Didn't you forget to call update() in your calculation function?
And it seems that your function is async, so you should await it before populating the list

Related

Where to put Flutter AJAX?

I come from the web dev world. I have designed a Flutter app that needs to grab some JSON from the web very early on. I want my first screen to show up, and while it is being drawn, behind the scenes I want the JSON fetch to happen. There is a start button on Page 1 that will be disabled until the JSON is fetched. (But Page 1 will have some text info to keep the reader engaged until the fetch happens.)
Where would I stick the JSON fetch? Can I put it in initState of Page 1? Or can I initiate a call at the very start of main at the root of the app? Or somewhere else?
FWIW I use Provider for state management, if that helps?
Thanks a ton!
Calling it in the initState is best since your widgets still build. Since there will be a state change, make sure you use a stateful widget. Also, don't forget to call setState to re-enable the button. Example code:
class FirstPage extends StatefulWidget {
const FirstPage({Key? key}) : super(key: key);
#override
State<FirstPage> createState() => _FirstPageState();
}
class _FirstPageState extends State<FirstPage> {
#override
void initState() {
super.initState();
jsonFetch();
}
void jsonFetch() {
// your functionality here
// on complete call:
/*
setState(() {
isJsonFetched = true;
});
*/
}
void doSomethingOnPressed(){
// Your functionality here
}
bool isJsonFetched = false;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: ElevatedButton(
onPressed: (){
isJsonFetched
? doSomethingOnPressed()
:null;
},
child: Text('Press Me')
)
)
);
}
}

Flutter - Refresh home page on item tap in drawer

I'm trying to refresh home page when an item in drawer is tapped.
HomeView is a stateful widget which returns a Scaffold with a drawer like this:
Scaffold(
drawer: const ProfileDrawer(), ....
I made a function which just calls setState in home like this:
void refreshPage() {
setState(() {});
}
Drawer has a listview which returns GestureDetector widgets as below:
GestureDetector(
onTap: () {
profileNotifier(false).setActiveProfile = index;
HomeView().refreshPage();
Navigator.pop(context);
},
child: ....
);
But on drawer class I'm getting error The method 'refreshPage' isn't defined for the type 'HomeView'. So I searched about it and learnt that method inside state cannot be called from elsewhere. But then when I moved the refreshPage function to class definition so that it can be called, now I can't setState.
I just want home to be refreshed when I tap on the drawer item. Any way to do this will work for a very grateful me.
Have been using this trick since then.
In your case, the page HomeView should be statefulWidget:
Hope you can adapt this code to your needs.
creating a GlobalKey for you HomeView like bellow
class HomeView extends StatefulWidget {
//remove the const and add customKey
HomeView({Key? key}) : super(key: GlobalKey<_HomeViewState>());
#override
State<HomeView> createState() => _HomeViewState();
//this is used to call the refreshPage method of your State
void refreshPage() {
print("call the state-method");
(key as GlobalKey<_HomeViewState>).currentState?.refreshPage();
}
}
class _HomeViewState extends State<HomeView> {
void refreshPage() {
setState(() {
print("method called");
});
}
#override
Widget build(BuildContext context) {
return Container();
}
}
create an instance of HomeView outside the GestureDetector
eg:
import 'package:flutter/material.dart';
//you can create the instance here (it depends on your use cases)
HomeView homeView = HomeView();
class A extends StatefulWidget{
...
}
class _AState extends State<A>{
...
return Scaffold(
drawer: ProfileDrawer(homeViewRef:homeView), //your drawer must have reference of your homeView instance
);
}
Drawer eg:
class ProfileDrawer{
...
final HomeView homeViewRef;
ProfileDrawer({required this.homeViewRef}){
...
}
//where this must be
GestureDetector(){
...
homeViewRef.refreshPage();
...
}
}
you should change this line: HomeView().refreshPage(); with homeViewRef.refreshPage(); because you are trying to call refreshPage() of new instance of HomeView (so then avoid).

Im trying to create a splash screen on flutter. Its showing error like these

lib/Splash.dart:36:28: Error: Type 'DiagnosticPropertiesBuilder' not found.
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
^^^^^^^^^^^^^^^^^^^^^^^^^^^
lib/Splash.dart:36:28: Error: 'DiagnosticPropertiesBuilder' isn't a type.
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
^^^^^^^^^^^^^^^^^^^^^^^^^^^
lib/Splash.dart:38:20: Error: The method 'DiagnosticsProperty' isn't defined for the class '_SplashState'.
'_SplashState' is from 'package:g1/Splash.dart' ('lib/Splash.dart').
Try correcting the name to the name of an existing method, or defining a method named 'DiagnosticsProperty'.
properties.add(DiagnosticsProperty('initState', initState));
^^^^^^^^^^^^^^^^^^^
Try this packages flutter_native_splash , animated_splash_screen or splashscreen
Flutter actually gives a simpler way to add Splash Screen to our application. We first need to design a basic page as we design other app screens. You need to make it a StatefulWidget since the state of this will change in a few seconds.
import 'dart:async';
import 'package:flutter/material.dart';
import 'home.dart';
class SplashScreen extends StatefulWidget {
#override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
#override
void initState() {
super.initState();
Timer(
Duration(seconds: 3),
() => Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (BuildContext context) => HomeScreen())));
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Image.asset('assets/splash.png'),
),
);
}
}
Logic Inside the initState(), call a Timer() with the duration, as you wish, I made it 3 seconds, once done push the navigator to Home Screen of our application.
Note: The application should show the splash screen only once, the user should not go back to it again on back button press. For this, we use Navigator.pushReplacement(), It will move to a new screen and remove the previous screen from the navigation history stack.

How to display popup after navigating back to previous screen in flutter?

I have a scenario where i have one popup in screen A .It will be triggerd from initstate() . User can navigate to screen B after clicking on button inside the popup . How can i show the popup if user come back to screen 1 by clicking on arrow back button ?
You can achieve with the help of .then() : https://api.flutter.dev/flutter/dart-async/Future/then.html
Navigator.of(context)
.push(CupertinoPageRoute<Screen1>(
builder: (context) => Screen2(
))).then((value) {
//ShowPopUpMenu() <-- Your PopUpMenu.
});
Add a boolean parameter to your screen if you want the popup:
class PopScreen extends StatefulWidget {
PopScreen (this.displayPopup);
final bool displayPopup;
#override
_PopScreenState createState() => _PopScreenState();
}
class _PopScreenState extends State<PopScreen> {
#override
void initState() {
super.initState();
if(widget.displayPopup){
// display your popup here
}
}
}
call to the navigator:
Navigator.pushNamed(context, '/yourscreen', arguments: true);

How can I execute a function when a user hits the back button or swipes to close a screen in flutter?

I want to always execute a function when a screen is closed, either when a user presses the back button or does a swipe to close the page.
What I have tried is to use WillPopScope
return WillPopScope(
onWillPop: _onWillPop,
child: CupertinoScaffold( ... the rest of my tree
Future<bool> _onWillPop() async {
myFunction();
return true;
}
While this does successfully execute my function whenever the page is closed via the back button, it seems to have disabled being able to swipe to go back on iOS. Swipe to go back on android still seems to function.
Is there another way of doing this so I can retain the swipe to go back functionality on iOS?
edit:
Just incase it matters, myFunction() involves a provider and context and throws an error when I try to call it from dispose.
In actuality myFunction() is:
context.read(myVisibilityProvider).changeVisibility(false);
I successfully managed to run a function calling it from dispose retaining the iOS swipe to back gesture.
class ScrondScreen extends StatefulWidget {
const ScrondScreen({Key? key}) : super(key: key);
#override
_ScrondScreenState createState() => _ScrondScreenState();
}
class _ScrondScreenState extends State<ScrondScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
);
}
void myFunction() {
print('I run');
}
#override
void dispose() {
myFunction();
super.dispose();
}
}
console:
flutter: I run