flutterflutter-providerflutter-sharedpreference

whenver i try to login in my app it shows login screen then goes to HomeScreen in flutter?


auth_service.dart

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:zomato_clone/common/widgets/bottom_bar.dart';
import 'package:zomato_clone/constants/error_handling.dart';
import 'package:zomato_clone/constants/global_variables.dart';
import 'package:zomato_clone/constants/utils.dart';
import 'package:zomato_clone/features/admin/screens/admin_screen.dart';
import 'package:zomato_clone/models/user.dart';
import 'package:zomato_clone/providers/user_provider.dart';

class AuthService {
  // sign up user
  void signUpUser({
    required BuildContext context,
    required String email,
    required String password,
    required String name,
  }) async {
    try {
      User user = User(
        id: '',
        name: name,
        password: password,
        email: email,
        address: '',
        type: '',
        token: '',
        cart: [],
      );

      http.Response res = await http.post(
        Uri.parse('$uri/api/signup'),
        body: user.toJson(),
        headers: <String, String>{
          'Content-Type': 'application/json; charset=UTF-8',
        },
      );

      httpErrorHandling(
        response: res,
        context: context,
        onSuccess: () {
          showSnackBar(
            context,
            'Account created! Login with the same credentials!',
          );
        },
      );
    } catch (e) {
      showSnackBar(context, e.toString());
    }
  }

  // sign in user
  void signInUser({
    required BuildContext context,
    required String email,
    required String password,
  }) async {
    try {
      http.Response res = await http.post(
        Uri.parse('$uri/api/signin'),
        body: jsonEncode({
          'email': email,
          'password': password,
        }),
        headers: <String, String>{
          'Content-Type': 'application/json; charset=UTF-8',
        },
      );
      httpErrorHandling(
          response: res,
          context: context,
          onSuccess: () async {
            SharedPreferences prefs = await SharedPreferences.getInstance();
            Provider.of<UserProvider>(context, listen: false).setUser(res.body);
            await prefs.setString(
                'x-auth-token', jsonDecode(res.body)['token']);
            Navigator.pushNamedAndRemoveUntil(
                context,
                Provider.of<UserProvider>(context, listen: false).user.type ==
                        'user'
                    ? BottomBar.routeName
                    : AdminScreen.routeName,
                (route) => false);
          });
    } catch (e) {
      showSnackBar(context, e.toString());
    }
  }

  // get user data
  void getUserData(
    BuildContext context,
  ) async {
    try {
      var userProvider = Provider.of<UserProvider>(context, listen: false);
      SharedPreferences prefs = await SharedPreferences.getInstance();
      String? token = prefs.getString('x-auth-token');

      if (token == null) {
        prefs.setString('x-auth-token', '');
      }

      var tokenRes = await http.post(
        Uri.parse('$uri/tokenIsValid'),
        headers: <String, String>{
          'Content-Type': 'application/json; charset=UTF-8',
          'x-auth-token': token!
        },
      );

      var response = jsonDecode(tokenRes.body);

      if (response == true) {
        http.Response userRes = await http.get(
          Uri.parse('$uri/'),
          headers: <String, String>{
            'Content-Type': 'application/json; charset=UTF-8',
            'x-auth-token': token
          },
        );

        userProvider.setUser(userRes.body);
      }
    } catch (e) {
      showSnackBar(context, e.toString());
    }
  }
}

main.dart

import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:provider/provider.dart';
import 'package:zomato_clone/common/widgets/bottom_bar.dart';
import 'package:zomato_clone/features/admin/screens/admin_screen.dart';
import 'package:zomato_clone/features/auth/screens/auth_screen.dart';
import 'package:zomato_clone/features/auth/services/auth_service.dart';
import 'package:zomato_clone/providers/user_provider.dart';
import 'package:zomato_clone/router.dart';
import 'package:zomato_clone/splash_screen.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  MobileAds.instance.initialize();
  runApp(MultiProvider(providers: [
    ChangeNotifierProvider(
      create: (context) => UserProvider(),
    )
  ], child: MyApp()));
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final AuthService authService = AuthService();

  @override
  void initState() {
    super.initState();
    authService.getUserData(context);
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Flutter Demo',
        theme: ThemeData(
          useMaterial3: true,
          primarySwatch: Colors.blue,
        ),
        onGenerateRoute: (settings) => generateRoute(settings),
        home: Provider.of<UserProvider>(context).user.email.isNotEmpty
            ? Provider.of<UserProvider>(context).user.type == 'user'
                ? const BottomBar()
                : AdminScreen()
            : const AuthScreen());
  }

}

when i restart my app in flutter i first land on login page then go back to home page please tell me how to solve this problem. when i tried a splashscreen it solve th problem when network is slow it goes back to loginpage then redirect to homePage help me solve this problem.


Solution

  • you should make getUserData to be Future and make a separate function to get the user date and make a local variable to handle loading state while fetching the data from the server and then use this variable later in home attribute

    bool _loading = true ;
    void prepareData()async{
     await authService.getUserData(context);
     _loading =false;
     setState(() {});
    }
    @override
     void initState() {
     super.initState();
     prepareData();
    }
    home: _loading?Center(child:CircularProgressIndicator()):Provider.of<UserProvider>(context).user.email.isNotEmpty
            ? Provider.of<UserProvider>(context).user.type == 'user'
                ? const BottomBar()
                : AdminScreen()
            : const AuthScreen());