Токен доступа Flutter был назван нулевым в начале и нормально работал после второго

#flutter #dart #sharedpreferences #dio

#flutter #dart #sharedpreferences #dio

Вопрос:

Я пытаюсь передать токен в заголовок. я получаю доступ к токену из моего sharepreference. Данные были успешно сохранены в настройках. Но при сетевом вызове он передает нулевое значение при запуске, но отлично работает после возврата и повторного открытия страницы.

Моя ошибка:

 E/flutter (23190): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: NoSuchMethodError: The getter 'accessToken' was called on null.


  E/flutter (23190): Receiver: null
    E/flutter (23190): Tried calling: accessToken
    E/flutter (23190): #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
    E/flutter (23190): #1      NetworkUtil.get (package:example/apihandler/network/NetworkUtil.dart:55:52)
  

Мой сетевой класс

 class NetworkUtil {
  Dio _dio;
String token;
  LoginResponse loginResponse;




  NetworkUtil() {
    ///Create Dio Object using baseOptions set receiveTimeout,connectTimeout
    BaseOptions options = BaseOptions(receiveTimeout: 5000, connectTimeout: 5000);
    options.baseUrl = ApiConstants.BASE_URL;
    _dio = Dio(options);

      AppPrefernces.getLoginPref().then((data) {
        this.loginResponse = LoginResponse.fromJson(jsonDecode(data));
      });

      
    _dio.interceptors.add(LogInterceptor());

  }





  ///used for calling Get Request
  Future<Response> get(String url, Map<String, String> params) async {
    Response response = await _dio.get(url,
        queryParameters: params,
        options: Options(responseType: ResponseType.json,headers: {
          "Authorization": "Bearer ${loginResponse.accessToken==null?"":loginResponse.accessToken}"
        }));
    return response;
  }

  ///used for calling post Request
  Future<Response> post(String url, Map<String, dynamic> params) async {
    Response response = await _dio.post(url,
        data: params, options: Options(responseType: ResponseType.json));
    return response;
  }
}
  

Вот мой файл Sharedpreference:

 class AppPrefernces {
  static final String LOGIN_PREF = "login";

  static Future<String> getLoginPref() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    return prefs.get(LOGIN_PREF) ?? null;
  }



  static setLoginPref(String value) async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    return prefs.setString(LOGIN_PREF, value);
  }
}
  

Ответ №1:

В вашем конструкторе NetworkUtil() у вас есть асинхронная операция, прежде чем вы установите LoginResponse с помощью токена. И он не завершен, когда вы делаете выноску API. Вам следует изменить инициализацию NetworkUtil и добавить флаг, чтобы узнать, готов ли он к использованию.

Вы можете использовать git_it и создать асинхронный ленивый синглтон для вашего NetworkUtil.

Ответ №2:

При вызове get метода значение LoginResponse еще не присваивается.

 class NetworkUtil {
  Dio _dio;
  String token;
  LoginResponse loginResponse;

  NetworkUtil() {
    ///Create Dio Object using baseOptions set receiveTimeout,connectTimeout
    BaseOptions options = BaseOptions(receiveTimeout: 5000, connectTimeout: 5000);
    options.baseUrl = ApiConstants.BASE_URL;
    _dio = Dio(options);

    _dio.interceptors.add(LogInterceptor());
  }

  ///used for calling Get Request
  Future<Response> get(String url, Map<String, String> params) async {
    loginResponse ??= LoginResponse.fromJson(jsonDecode(await AppPrefernces.getLoginPref()));

    Response response = await _dio.get(url,
        queryParameters: params,
        options: Options(responseType: ResponseType.json, headers: {
          "Authorization": "Bearer ${loginResponse.accessToken == null ? "" : loginResponse.accessToken}"
        }));
    return response;
  }

  ///used for calling post Request
  Future<Response> post(String url, Map<String, dynamic> params) async {
    Response response = await _dio.post(url, data: params, options: Options(responseType: ResponseType.json));
    return response;
  }
}