Flutter Authentication and Data Persistence with Provider Architecture

272 views Asked by At

I come from a HTML/CSS/JQUERY for frontend background and mostly I have been a Nodejs backend developer. However a project I took over was based on HTML/CSS/JQuery and PHP and I am doing quite well in that until they needed a mobile application. So my choice was flutter since it was hot at that moment. I have mastered flutter basics and took provider as my state management and also incorporated logic inside it. However I have 2 issue that I am not being able to figure out.

  1. One is state persistence in provider even when app is forced closed.
  2. Maintain login persistence unless logged out and clear state if logged out.

For 1. I haven't been able to figure out a concrete solution except Application Storage but then I would have to write alot of code more to store all the data and class into it.

For 2. I have done some experimental method as below

runApp(
    ChangeNotifierProvider(
      create: (_) => UserRepository(), // Here is my auth state provider
      child: MyApp(),
    ),
  );

In UserRepository class user data like user id are stored in SharedPreferences which checks if there is userdata is stored or not hence Status becomes Authenticated or Uninitialized per condition.

Below is a Stateful widget that sets the status with respect to UserRepository

    class _MyAppState extends State<MyApp> {
      ProjectRepository projectRepository = ProjectRepository();
      UIKeypadRepository uiKeypadRepository = UIKeypadRepository();
      PODRepository podRepository = PODRepository();
      Status currentStatus;
      //Also there are more Change notifier class here that manages state of various features of the app
    
      void initProviders() {
        projectRepository = ProjectRepository();
        uiKeypadRepository = UIKeypadRepository();
        podRepository = PODRepository();

      }
    
      @override
      void initState() {
        currentStatus = Provider.of<UserRepository>(context, listen: false).status;
        //if not logged out current status is authenticated
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Consumer(builder: (context, UserRepository authStatus, child) {
          if (currentStatus != Status.Authenticated) {
            initProviders(); // this function is called and all changenotifier classes are reinitialized
          }
          return MultiProvider(
            providers: [
              ChangeNotifierProvider.value(value: projectRepository),
              ChangeNotifierProvider.value(value: uiKeypadRepository),
              ChangeNotifierProvider.value(value: podRepository),
            ],

            //instead of create I used value so if classes are initialized initial values are taken else existing values are made available to below the widget tree

            child: MaterialApp(
                home: GestureDetector(
                    behavior: HitTestBehavior.translucent,
                    onTap: () {
                      FocusScope.of(context).requestFocus(FocusNode());
                    },
                    child: LandingPage())),
          );
        });
      }
    }
1

There are 1 answers

3
Eka Setiawan Saputra On

You can use authStateChanges() and StreamBuilder to get the authentication status.

Reference