my flutter default splash screen is taking time to load - flutter

My flutter app's default splash screen takes too much time when the app opens time,
And also added the flutter flavor's
screen record is
My folder is
my main_dev.dart code is
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await MobileAds.instance.initialize();
FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
_initConfig();
final fcmToken = await FirebaseMessaging.instance.getToken();
FirebaseMessaging.onMessageOpenedApp.listen(
(RemoteMessage message) => {print('onMessageOpenedApp $message')});
var configuredApp = AppConfig(
appDisplayName: "dev Config",
fcmToken: fcmToken!,
baseUrl: 'https://dev-services.ducoinsure.com/',
appInternalId: 1,
child: const MyHomepage(),
);
// HttpOverrides.global = MyHttpOverrides();
mainCommon();
runApp(configuredApp);
}
Future<void> _initConfig() async {
await _remoteConfig.setConfigSettings(RemoteConfigSettings(
fetchTimeout: const Duration(seconds: 1),
minimumFetchInterval: const Duration(seconds: 10),
));
_fetchConfig();
}
void _fetchConfig() async {
await _remoteConfig.fetchAndActivate();
}
my InheritedWidget is
import 'package:flutter/material.dart';
class AppConfig extends InheritedWidget {
const AppConfig(
{super.key,
required this.appDisplayName,
required this.appInternalId,
required Widget child,
required this.baseUrl,
required this.fcmToken})
: super(child: child);
final String appDisplayName, baseUrl, fcmToken;
final int appInternalId;
static AppConfig? of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<AppConfig>();
}
#override
bool updateShouldNotify(InheritedWidget oldWidget) => false;
}

Related

Get FCM registration token in Flutter

Hi all...
I have problem in getting token value
my code is
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage
message) async {
await Firebase.initializeApp();
print('A bg message just showed up : ${message.messageId}');
}
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
runApp(Application());
}
class Application extends StatefulWidget {
#override
State<StatefulWidget> createState() => _Application();
}
class _Application extends State<Application> {
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
String token = '';
#override
void initState() {
super.initState();
_firebaseMessaging.getToken().then((token) {
assert(token != null);
print("token is : " + token!);
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(child: Text('My Token is : $token')),),
);
}
}

Flutter: How to store the location data?

Errors:
The named parameter 'locationData' is required, but there's no
corresponding argument. Try adding the required argument.
Undefined name 'locationData'. Try correcting the name to one that is defined, or defining the name.
The location data in the main.dart file bring an error please help me solve it.
My code:
Below is the main.dart code that caused the error:
import 'package:firebase_core/firebase_core.dart';
import 'package:firstapp/screens/Login_screen.dart';
import 'package:firstapp/screens/authunication/phone_auth_screen.dart';
import 'package:firstapp/screens/home_screen.dart';
import 'package:firstapp/screens/location_screen.dart';
import 'package:firstapp/screens/splash_screen.dart';
import 'package:flutter/material.dart';
import 'package:location/location.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
// ignore: use_key_in_widget_constructors
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.cyan.shade900,
),
initialRoute: SplashScreen.id,
routes: {
SplashScreen.id: (context) => SplashScreen(),
LoginScreen.id: (context) => LoginScreen(),
PhoneAuthScreen.id: (context) => PhoneAuthScreen(),
LocationScreen.id: (context) => LocationScreen(),
HomeScreen.id: (context) => HomeScreen(locationData),
},
);`
Below is the code for the HomeScreen widget where I want location data:
import 'package:flutter/material.dart';
import 'package:location/location.dart';
class HomeScreen extends StatelessWidget {
static const String id = 'home-screen';
final LocationData locationData;
HomeScreen({
required this.locationData,
});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(locationData.latitude.toString()),
),
body: Center(
child: Text('Home screen'),
),
);
}
}
Here is the code for the LocationScreen widget in the app:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firstapp/screens/login_screen.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:location/location.dart';
class LocationScreen extends StatefulWidget {
static const String id = 'location-screen';
#override
State<LocationScreen> createState() => _LocationScreenState();
}
class _LocationScreenState extends State<LocationScreen> {
Location location = new Location();
late bool _serviceEnabled;
late PermissionStatus _permissionGranted;
late LocationData _locationData;
Future<LocationData?>getLocation() async {
_serviceEnabled = await location.serviceEnabled();
if (!_serviceEnabled) {
_serviceEnabled = await location.requestService();
if (!_serviceEnabled) {
return null;
}
}
_permissionGranted = await location.hasPermission();
if (_permissionGranted == PermissionStatus.denied) {
_permissionGranted = await location.requestPermission();
if (_permissionGranted != PermissionStatus.granted) {
return null;
}
}
_locationData = await location.getLocation();
return _locationData;
}
So,
The first error says that when you try to implement a HomeScreen widget, withoug giving the required parameter named locationData,to give the required parameted follow this code example:
HomeScreen(locationData: locationData)
The second error says that you are trying to use a variable that is not defined yet. In the page that you try to implement the HomeScreen widget, you should define a variable named locationData, to give it a value and then to try to use the HomeScreen widget. For instance:
class LocationScreen extends StatefulWidget {
const LocationScreen({Key? key}) : super(key: key);
#override
State<LocationScreen> createState() => _LocationScreenState();
}
class _LocationScreenState extends State<LocationScreen> {
LocationData locationData;
#override
Widget build(BuildContext context) {
//in case that you use the HomeScreen as a widget
return locationData == null ? Container() : HomeScreen(locationData: locationData);
//in case that you use the HomeScreen as Screen
return Container();
}
void getLocationData() async{
//in case that you use the HomeScreen as a widget
//this function will change the state after the locationData have been filled
locationData = await getLocation();
setState(() {
});
}
void navigateToHomeScreen() async{
//in case that you use the HomeScreen as a widget
//this function will change the state after the locationData have been filled
locationData = await getLocation();
Navigator.push(context, MaterialPageRoute(
builder: (context) => HomeScreen(locationData: locationData);
));
}
Future<LocationData?> getLocation() async {
_serviceEnabled = await location.serviceEnabled();
if (!_serviceEnabled) {
_serviceEnabled = await location.requestService();
if (!_serviceEnabled) {
return null;
}
}
_permissionGranted = await location.hasPermission();
if (_permissionGranted == PermissionStatus.denied) {
_permissionGranted = await location.requestPermission();
if (_permissionGranted != PermissionStatus.granted) {
return null;
}
}
_locationData = await location.getLocation();
return _locationData;
}
}
The third error says that don't use any Positional parameters in your HomeScreen class because you use named parameters, If you follow my code, it will be fixed as well
Hope I helped,
Enjoy flutter
On the HomeScreen, replace this line of code:
HomeScreen({required this.locationData,});
with
HomeScreen(this.locationData);
This should clear the error on main.dart

Get value from SharedPreferences without future builder

I need to get one stored value from shared preferences and put it into text widget. How can I do this without a future builder?
_currPage() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
int page = prefs.getInt('currPage') ?? 0;
return page;
}
class _AllTasksPageState extends State<AllTasksPage> {
#override
Widget build(BuildContext context) {
...
Text(_currPage()); //not working
...
}
}
int page = 0;
#override
void initState() {
super.initState();
readData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('$page'),
),
);
}
void readData() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
if (prefs.getInt('currPage') == null)
setState(() => page = 0);
else
setState(() => page = prefs.getInt('currPage')!);
}
create a helper class just for shared preferences
import 'package:shared_preferences/shared_preferences.dart';
class SPHelper {
SPHelper._();
static SPHelper sp = SPHelper._();
SharedPreferences? prefs;
Future<void> initSharedPreferences() async {
prefs = await SharedPreferences.getInstance();
}
Future<void> save(String name, String value) async {
await prefs!.setString(name, value);
}
String? get(String key) {
return prefs!.getString(key);
}
Future<bool> delete(String key) async {
return await prefs!.remove(key);
}
}
in your main function add
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await SPHelper.sp.initSharedPreferences();
...
runApp(MyApp());
...
}
then to get your data just write
SPHelper.sp.get("YOUR_KEY")
and to store your data just write
SPHelper.sp.save("YOUR_KEY","YOUR_VALUE")
This is the best way to use shared preference.
I hope that's will help you in your problem.
The simplest method is using a SharedPreferences provider:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(
MultiProvider(
providers: [
Provider.value(value: await SharedPreferences.getInstance()),
],
child: MaterialApp(
home: AllTasksPage(),
),
),
);
}
class AllTasksPage extends StatelessWidget {
const AllTasksPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final page = context.read<SharedPreferences>().getInt('currPage') ?? 0;
return Scaffold(body: Text('$page'));
}
}
If you don't want to use a future builder, the other solution is if you have a variable that tells you that are you still waiting/loading data and if yes, show a waiting screen:
class _AllTasksPageState extends State<AllTasksPage> {
bool _loading = true;
String? textValue; // String textValue = "";
#override
initState() {
super.initState();
setTextValue();
}
setTextValue() {
SharedPreferences prefs = await SharedPreferences.getInstance();
int page = prefs.getInt('currPage') ?? 0;
setState(() {
textValue = "$page";
_loading = false;
});
}
// then in the build method
#override
Widget build(BuildContext context) {
return _loading ? CircularProgressIndicator() : actualScreen();
}
}

Riverpod Alternative To SetUpLocator

I want to call my Remote Config Instance on Flutter App StartUp
I have set up Riverpod as follows
class ConfigService {
// Will Initialise here
final RemoteConfig _remoteConfig;
ConfigService(this._remoteConfig);
Future<void> initialise() async {
...// Will fetchAndActivate
}
final remoteConfigProvider = Provider<RemoteConfig>((ref) {
return RemoteConfig.instance;
});
final configProvider = Provider<ConfigService>((ref) {
final _config = ref.read(remoteConfigProvider);
return ConfigService(_config);
});
I would want to call it in the main after
...
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
... here
But this can't be done because one needs a Reader and the ProviderScope is below this level
How do I call this provider in my main ?
The short answer is you can't. What you should do is call the Provider within the ProviderScope.
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(
ProviderScope(
child: MyApp(),
),
);
}
class MyApp extends ConsumerWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context, ScopedReader watch) {
final config = watch(configProvider);
return Container();
}
}

Return async value to initState()

I've the below code that is working fine, reading the csv data from url and printing the output:
import 'package:flutter/material.dart';
import 'dart:convert';
import 'dart:io';
import 'dart:async';
import 'package:csv/csv.dart';
void fetchUserData() async {
final request = await HttpClient().getUrl(Uri.parse(
'https://docs.google.com/spreadsheets/d/e/2PACX-1vQvf9tp4-fETDJbC-HRmRKvVFAXEAGO4lrYPpVeiYkB6nqqXdSs3CjX0eBMvjIoEeX9_qU6K2RWmzVk/pub?gid=0&single=true&output=csv'));
final response = await request.close();
List<List<dynamic>> rowsAsListOfValues;
await for (final csvString in response.transform(const Utf8Decoder())) {
rowsAsListOfValues =
const CsvToListConverter().convert(csvString);
}
print(rowsAsListOfValues);
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
super.initState();
fetchUserData();
}
#override
Widget build(BuildContext context) { // ... // }
}
Instead of getting the output printed, I need it to be returned into a variable, which I can display in y widget, I tried to do it as below:
Future<List<List<dynamic>>> fetchUserData() async { /// change
final request = await HttpClient().getUrl(Uri.parse(
'https://docs.google.com/spreadsheets/d/e/2PACX-1vQvf9tp4-fETDJbC-HRmRKvVFAXEAGO4lrYPpVeiYkB6nqqXdSs3CjX0eBMvjIoEeX9_qU6K2RWmzVk/pub?gid=0&single=true&output=csv'));
final response = await request.close();
List<List<dynamic>> rowsAsListOfValues;
await for (final csvString in response.transform(const Utf8Decoder())) {
rowsAsListOfValues =
const CsvToListConverter().convert(csvString);
}
return rowsAsListOfValues; /// change
}
class _MyHomePageState extends State<MyHomePage> {
var rowsAsListOfValues; /// new
#override
void initState() {
super.initState();
rowsAsListOfValues = fetchUserData(); /// new
print(rowsAsListOfValues); /// new
}
#override
Widget build(BuildContext context) { // ... // }
}
But I got the output as I/flutter ( 7505): Instance of 'Future<List<List<dynamic>>>'
How can I fix it?
You need to switch from initState to didChangeDependency in this case. Because you need to await some process and you cant wait in initState. However you can wait like this
#override
void didChangeDependencies() async {
super.didChangeDependencies();
rowsAsListOfValues = await fetchUserData();
super.setState(() {}); // to update widget data
/// new
print(rowsAsListOfValues);
}
And this is the result
I/flutter (24313): [[vranches], [Dammam, 2], [Khobar, 3]]
You can wrap your code with Future.delayed() as given below.
#override
void initState() {
super.initState();
Future.delayed(Duration.zero,()async{
rowsAsListOfValues =await fetchUserData();
setState(() {});
print(rowsAsListOfValues); // this return correct value
});
print(rowsAsListOfValues); // this return null
}
Full Code
import 'package:flutter/material.dart';
import 'dart:convert';
import 'dart:io';
import 'dart:async';
import 'package:csv/csv.dart';
void main() {
runApp(App());
}
class App extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: HomePage(title: 'Flutter Demo Home Page'),
);
}
}
class HomePage extends StatefulWidget {
HomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_AppState createState() => _AppState();
}
Future<List<List<dynamic>>> fetchUserData() async {
final request = await HttpClient().getUrl(Uri.parse(
'https://docs.google.com/spreadsheets/d/e/2PACX-1vQvf9tp4-fETDJbC-HRmRKvVFAXEAGO4lrYPpVeiYkB6nqqXdSs3CjX0eBMvjIoEeX9_qU6K2RWmzVk/pub?gid=0&single=true&output=csv'));
final response = await request.close();
List<List<dynamic>> rowsAsListOfValues;
await for (final csvString in response.transform(const Utf8Decoder())) {
rowsAsListOfValues =
const CsvToListConverter().convert(csvString);
}
return rowsAsListOfValues;
}
class _AppState extends State<HomePage> {
var rowsAsListOfValues;
#override
void initState() {
super.initState();
Future.delayed(Duration.zero, () async {
rowsAsListOfValues = await fetchUserData();
setState(() {});
print(rowsAsListOfValues);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'$rowsAsListOfValues',
),
],
),
),
);
}
}
The initState method is synchronous, and does not support async. I recommend the use of FutureBuilder, but you can also move the code to an async function.
FutureBuilder
import 'package:flutter/material.dart' show
Widget, FutureBuilder, AsyncSnapshot
;
class _MyHomePageState extends State<MyHomePage> {
static Future<void> fetchUserData() {
return Future().delayed(
Duration(seconds: 10),
() => 'loaded'
);
}
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: Future.wait([
fetchUserData()
]),
builder: (
BuildContext context,
AsyncSnapshot snapshot
) {
if (snapshot.hasData) {
return Text(snapshot.data);
}
return Text('loading...');
}
);
}
}
Async function
#override
void initState () {
super.initState();
(() async {
rowsAsListOfValues = await fetchUserData();
print(rowsAsListOfValues);
})();
}
OR
#override
void initState() {
super.initState();
initLoad();
}
void initLoad() async {
rowsAsListOfValues = await fetchUserData();
print(rowsAsListOfValues);
}
I feel more relaxed when using then() with async functions. You can try this:
fetchUserData().then((value) {
setState(() {
rowsAsListOfValues = value;
});
});
Or you can use await like this.
#override
void initState() async {
super.initState();
rowsAsListOfValues = await fetchUserData();
print(rowsAsListOfValues);
}