简体   繁体   中英

Remember screen state after closing and opening app

I have 4 pages in my registration and a homepage once the registration is complete. I need to keep track of the screens so that when a user leaves and comes back: he is taken to the page he was on when he left the app. I've seen a couple solutions using SharedPreferences but I'm using firebase/firestore and the Provider package , so I thought I might use that to hold state. My registration flow is pop/push. And my screens are Stateful Widgets . So I can use initState to hold state. Just not sure the best way to implement this...

I made a bloc that represents the states of registration pages, and the state stored in it can survive app restarts, all this and you have these juicy functional programming things like Unions to not ever forget about any case you have, now look at this code and try to compare it with the provider approach of saving progress(state) of user in your question,which one will be better creating change notifiers and filling them with booleans and strings spread all around or using data structures and unions to represent the state and make it imuutable?

btw the solution I used is made possible by freezed and hydrated_bloc packages.

Notes:

  1. I know you are most likely not gonna use this approach as I see from your comment, but anyway this answer is worth it because it can help others who sometimes find it difficult to choose their state management solution

    2.If you find somethings like unions scary, please don't,just see some tutorials like this and you are good to go

    3.Don't judge this appraoch before you know fully what is freezed package and what is bloc pattern and what are unions and how all these work

here is a sample of the solution(other parts of solution can be completed similarly):

registration_state.dart

//it contains the states as classes for each page,and each class holds the necessary fields to represent what's happening on that page

part of 'registration_bloc.dart';

@freezed
abstract class RegistrationState with _$RegistrationState {
  const factory RegistrationState.firstPage({
    //represents first page state
    @required String email,
    @required String password,
    @required String phoneNumber,
  }
      //...
      ) = _FirstPage;

  const factory RegistrationState.secondPage(//some params here
      ) = _SecondPage;

  //same for other pages...

  factory RegistrationState.initialState() => RegistrationState.firstPage(//consider initial state to be first page with empty strings
        email: '',
        password: '',
        phoneNumber: '',
      );
}

registraion_event.dart:

//represents all actions that might happen on each page and how you can update states accordingly

part of 'registration_bloc.dart';


@freezed
abstract class RegistrationEvent with _$RegistrationEvent {
  const factory RegistrationEvent.emailChangedOnFirstPage() = _EmailChangedOnFirstPage;
  const factory RegistrationEvent.passwordChangedOnFirstPage() = _PasswordChangedOnFirstPage;
  const factory RegistrationEvent.phoneChangedOnFirstPage() = _PhoneChangedOnFirstPage;
  const factory RegistrationEvent.submitPressedOnFirstPage() = _SubmitPressedOnFirstPage;
  const factory RegistrationEvent.somethingHappenedOnSecondPage() = _somethingHappenedOnSecondPage;
//...
}

registarion_bloc.dart:

//place where you save state if app restarts and you turn evvents into states when they are fired from the UI

import 'dart:async';

import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';

part 'registration_bloc.freezed.dart';
part 'registration_event.dart';
part 'registration_state.dart';

class RegistrationBloc
    extends HydratedBloc<RegistrationEvent, RegistrationState> {
  @override
  RegistrationState get initialState =>
      super.initialState ?? RegistrationState.initialState();

  @override
  Stream<RegistrationState> mapEventToState(
    RegistrationEvent event,
  ) async* {
    yield* event.map(emailChangedOnFirstPage: (event) async* {
      //TODO yield some state
    }, passwordChangedOnFirstPage: (event) async* {
      //TODO yield some state
    }, phoneChangedOnFirstPage: (event) async* {
      //TODO yield some state
    }, submitPressedOnFirstPage: (event) async* {
      //TODO yield some state
    }, somethingHappenedOnSecondPage: (event) async* {
      //TODO yield some state
    });
  }

  @override
  RegistrationState fromJson(Map<String, dynamic> json) {
    // TODO: get your state before app was killed last time
    return null;
  }

  @override
  Map<String, dynamic> toJson(RegistrationState state) {
    // TODO: save your state as json
    return null;
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM