skip to Main Content

I am developing a Flutter app with Getx State Management. I have Signin page and Dashboard page. I am maintaining all of my network url in another class. After 24 hours my token automatically expire and for this reason I am showing a dialog box that the token is expired and navigating user to login page.

After logging in with new credential I am getting new token and saving that token to my local storage. I am using Getx Storage package for local storage. But when I call the api from my desktop, in my log it is showing old token in my network request and token expired dialog is showing again and again.

If I do a full restart of my app then it is working fine.

This is my Sigin Controller method:

void signInApi() {
    if (!formKey.currentState!.validate()) {
      return;
    }
    formKey.currentState!.save();

    isLoading.value = true;
    Map data = {};
    data = {'office_email': officeEmail.value, 'password': password.value};

    _api.loginApi(data).then((value) {
      isLoading.value = false;
      if (value['error'] != null) {
        Utils.customDialog(title: 'Login', message: value['error'], onOkTap: () {Get.back();});
      } else {
        String token = value['token'];
        prefs.token.val = token;
        prefs.email.val = officeEmail.value;
        prefs.password.val = password.value;

        Get.offNamed(RoutesName.dashboardScreen);
      }
    });
  }

This is my SignIn repository:

class SignInRepository {
  final _apiService = NetworkApiServices();

  Future<dynamic> loginApi(var data) async {
    dynamic response = await _apiService.postApi(data, AppUrl.loginApi);
    return response;
  }
}

This is my Dashboard Controller method:

void getEmployeeInfo() {
    setRequestStatus(Status.loading);

    _api.employeeInfo().then((value) {
      if (value['error'] != null) {
        Utils.customDialog(
            title: 'Warning!',
            message: value['error'],
            isCancelable: false,
            onOkTap: () {
              Get.back();
              box.erase();
              Get.offAllNamed(RoutesName.loginView);
            });
      } else {
        if (value['show_profile_publicly'] == '1') {
          prefs.visibility.val = 'Public';
        } else {
          prefs.visibility.val = 'Private';
        }

        employeeInfo.value = UserProfile.fromJson(value['data']);
      }

    }).onError((error, stackTrace) {
      debugPrint('Error from $runtimeType: $error');
      setRequestStatus(Status.error);
      setError(error.toString());
    });
  }

This is my Dashboard repository:

class DashboardRepository {
  final _apiService = NetworkApiServices();

  Future<dynamic> employeeInfo() async {
    dynamic response = await _apiService.getApi(AppUrl.employeeInfoApi);
    return response;
  }

  Future<dynamic> ratingInfo() async {
    dynamic response = await _apiService.getApi(AppUrl.ratingInfoApi);
    return response;
  }

  Future<dynamic> notificationInfo() async {
    dynamic response = await _apiService.getApi(AppUrl.supportNotificationApi);
    return response;
  }
}

This is my AppUrl Class:

class AppUrl {
  static String token = Get.find<MyPrefs>().token.val;

  static const String baseUrl = 'https://api.something.ac';
  // Login api
  static const String loginApi = '$baseUrl/auth/login';
  // Dashboard
  static final String employeeInfoApi = '$baseUrl/profile?token=$token';
  static final String ratingInfoApi = '$baseUrl/profile-rating?token=$token';
  static final String supportNotificationApi = '$baseUrl/profile/ticket-assign-notification?token=$token';
}

This is my MyPrefs Class:

class MyPrefs extends GetxController {
  Future<void> initStorage() async {
    await GetStorage.init();
  }

  // App value
  final token = ''.val('token');
  final password = ''.val('password');
  final email = ''.val('email');
  final userId = 0.val('user_id');
  final name = ''.val('name');
  final photo = ''.val('photo');
  final tempId = 0.val('tempId');
  final visibility = ''.val('visibility');

  // Preferences
  final remember = false.val('remember_pass');
}

I have tried erasing GetStorage box but no result.
I manually deleted my all controller and single Dashboard controller but no result.
I have used Get.off to delete the controller automatically.

2

Answers


  1. Chosen as BEST ANSWER

    Finally I got the solution. In my AppUrl class I have the url declaration like below:

    static final String employeeInfoApi = '$baseUrl/profile?token=$token';
    

    The problem was final keyword. I have declared my url final for this reason it was storing my previous token. Althogh I updated token in sign in page controller but my updated token was not set because of final keyword. After updating my AppUrl class urls like below:

    static String employeeInfoApi = '$kBaseUrl/profile?token=$token';
    

    my updated token is working fine.


  2. Check this example, which do basically what you do with your token:

    class GetIt {
      static int _m = 0;
      
      static String method() => 'Hi: ${_m++}';
    }
    
    class AppClass {
      static String token = GetIt.method();
    }
    
    void main() {
      print(AppClass.token);
      print(AppClass.token);
      print(AppClass.token);
    }
    
    output:
        Hi: 0
        Hi: 0
        Hi: 0
    

    now make that token a getter or a method:

    class AppClass {
       static String get token => GetIt.method();
    }
        
    void main() {
       print(AppClass.token);
       print(AppClass.token);
       print(AppClass.token);
    }
    
    output:
        Hi: 0
        Hi: 1
        Hi: 2
    

    In the first example you are referencing a static variable, it calls your GetIt.find method once and never again, because its a variable, that value is stored there, by making it a getter or a method and calling it it will do all the logic inside again each time you call it, so if the token changed it will do that logic to get the new one

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search