当我尝试连接到我在GCP上部署的后端API时,出现以下错误。
延迟初始化错误:字段'apiURL'尚未初始化
跟踪显示以下内容:
I/flutter (20883): LateInitializationError: Field 'apiURL' has not been initialized.
I/flutter (20883): #0 AuthApiService.apiURL (package:Myapp/services/auth_api.dart)
I/flutter (20883): #1 AuthApiService.loginWithCredentials (package:Myapp/services/auth_api.dart:335:41)
I/flutter (20883): #2 UserService.loginWithCredentials (package:Myapp/services/user.dart:338:53)
I/flutter (20883): #3 KNAuthLoginPageState._login (package:Myapp/pages/auth/login.dart:145:26)
I/flutter (20883): #4 KNAuthLoginPageState._submitForm (package:Myapp/pages/auth/login.dart:136:13)
I/flutter (20883): #5 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:253:24)
I/flutter (20883): #6 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:627:11)
I/flutter (20883): #7 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:306:5)
I/flutter (20883): #8 BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:239:7)
I/flutter (20883): #9 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:615:9)
I/flutter (20883): #10 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:98:12)
I/flutter (20883): #11 PointerRouter._dispatchEventToRoutes
I/flutter (20883): In dev mode. Not sending report to Sentry.io.
我的验证API日期(_A):
import 'dart:io';
import 'package:Myapp/models/language.dart';
import 'package:Myapp/services/httpie.dart';
import 'package:Myapp/services/string_template.dart';
import 'package:meta/meta.dart';
class AuthApiService {
late HttpieService _httpService;
late StringTemplateService _stringTemplateService;
late String apiURL;
static const CHECK_USERNAME_PATH = 'api/auth/username-check/';
static const CHECK_EMAIL_PATH = 'api/auth/email-check/';
static const UPDATE_EMAIL_PATH = 'api/auth/user/settings/';
static const VERIFY_EMAIL_TOKEN = 'api/auth/email/verify/';
static const ACCEPT_GUIDELINES = 'api/auth/user/accept-guidelines/';
static const SET_NEW_LANGUAGE = 'api/auth/user/languages/';
static const GET_NEW_LANGUAGE = 'api/auth/user/languages/';
static const UPDATE_PASSWORD_PATH = 'api/auth/user/settings/';
static const CREATE_ACCOUNT_PATH = 'api/auth/register/';
static const VERIFY_REGISTER_TOKEN = 'api/auth/register/verify-token/';
static const DELETE_ACCOUNT_PATH = 'api/auth/user/delete/';
static const GET_AUTHENTICATED_USER_PATH = 'api/auth/user/';
static const UPDATE_AUTHENTICATED_USER_PATH = 'api/auth/user/';
static const GET_USERS_PATH = 'api/auth/users/';
static const REPORT_USER_PATH = 'api/auth/users/{userUsername}/report/';
static const GET_LINKED_USERS_PATH = 'api/auth/linked-users/';
static const SEARCH_LINKED_USERS_PATH = 'api/auth/linked-users/search/';
static const GET_BLOCKED_USERS_PATH = 'api/auth/blocked-users/';
static const SEARCH_BLOCKED_USERS_PATH = 'api/auth/blocked-users/search/';
static const ENABLE_NEW_POST_NOTIFICATIONS_FOR_USER_PATH =
'api/auth/users/{userUsername}/notifications/subscribe/new-post/';
static const BLOCK_USER_PATH = 'api/auth/users/{userUsername}/block/';
static const UNBLOCK_USER_PATH = 'api/auth/users/{userUsername}/unblock/';
static const GET_FOLLOWERS_PATH = 'api/auth/followers/';
static const SEARCH_FOLLOWERS_PATH = 'api/auth/followers/search/';
static const GET_FOLLOWINGS_PATH = 'api/auth/followings/';
static const SEARCH_FOLLOWINGS_PATH = 'api/auth/followings/search/';
static const LOGIN_PATH = 'api/auth/login/';
static const REQUEST_RESET_PASSWORD_PATH = 'api/auth/password/reset/';
static const VERIFY_RESET_PASSWORD_PATH = 'api/auth/password/verify/';
static const AUTHENTICATED_USER_NOTIFICATIONS_SETTINGS_PATH =
'api/auth/user/notifications-settings/';
void setHttpService(HttpieService httpService) {
_httpService = httpService;
}
void setStringTemplateService(StringTemplateService stringTemplateService) {
_stringTemplateService = stringTemplateService;
}
void setApiURL(String newApiURL) {
apiURL = newApiURL;
}
Future<HttpieResponse> deleteUser({required String password}) {
Map<String, dynamic> body = {'password': password};
return _httpService.post('$apiURL$DELETE_ACCOUNT_PATH',
body: body, appendAuthorizationToken: true);
}
Future<HttpieResponse> checkUsernameIsAvailable({required String username}) {
return _httpService
.postJSON('$apiURL$CHECK_USERNAME_PATH', body: {'username': username});
}
Future<HttpieResponse> checkEmailIsAvailable({required String email}) {
return _httpService
.postJSON('$apiURL$CHECK_EMAIL_PATH', body: {'email': email});
}
Future<HttpieStreamedResponse> updateUserEmail({required String email}) {
Map<String, dynamic> body = {};
body['email'] = email;
return _httpService.patchMultiform('$apiURL$UPDATE_EMAIL_PATH',
body: body, appendAuthorizationToken: true);
}
Future<HttpieStreamedResponse> updateUserPassword(
{required String currentPassword, required String newPassword}) {
Map<String, dynamic> body = {};
body['current_password'] = currentPassword;
body['new_password'] = newPassword;
return _httpService.patchMultiform('$apiURL$UPDATE_PASSWORD_PATH',
body: body, appendAuthorizationToken: true);
}
Future<HttpieResponse> verifyEmailWithToken(String token) {
Map<String, dynamic> body = {'token': token};
return _httpService.postJSON('$apiURL$VERIFY_EMAIL_TOKEN',
body: body, appendAuthorizationToken: true);
}
Future<HttpieStreamedResponse> updateUser({
dynamic avatar,
dynamic cover,
String? name,
String? username,
String? url,
bool? followersCountVisible,
bool? communityPostsVisible,
String? bio,
String? location,
String? visibility,
}) {
Map<String, dynamic> body = {};
if (avatar is File) {
body['avatar'] = avatar;
} else if (avatar is String && avatar.isEmpty) {
// This is what deletes the avatar. Ugly af.
body['avatar'] = avatar;
}
if (cover is File) {
body['cover'] = cover;
} else if (cover is String && cover.isEmpty) {
// This is what deletes the cover. Ugly af.
body['cover'] = cover;
}
if (name != null) body['name'] = name;
if (username != null) body['username'] = username;
if (url != null) body['url'] = url;
if (bio != null) body['bio'] = bio;
if (visibility != null) body['visibility'] = visibility;
if (followersCountVisible != null)
body['followers_count_visible'] = followersCountVisible;
if (communityPostsVisible != null)
body['community_posts_visible'] = communityPostsVisible;
if (location != null) body['location'] = location;
return _httpService.patchMultiform('$apiURL$UPDATE_AUTHENTICATED_USER_PATH',
body: body, appendAuthorizationToken: true);
}
Future<HttpieStreamedResponse> createUser(
{required String email,
required String token,
required String name,
required String username,
required bool isOfLegalAge,
required bool areGuidelinesAccepted,
required String password,
File? avatar}) {
Map<String, dynamic> body = {
'email': email,
'token': token,
'name': name,
'username': username,
'is_of_legal_age': isOfLegalAge,
'are_guidelines_accepted': areGuidelinesAccepted,
'password': password
};
if (avatar != null) {
body['avatar'] = avatar;
}
return _httpService.postMultiform('$apiURL$CREATE_ACCOUNT_PATH',
body: body);
}
Future<HttpieResponse> verifyRegisterToken({required String token}) {
Map<String, dynamic> body = {'token': token};
return _httpService.post('$apiURL$VERIFY_REGISTER_TOKEN', body: body);
}
Future<HttpieResponse> getUserWithAuthToken(String authToken) {
Map<String, String> headers = {'Authorization': 'Token $authToken'};
return _httpService.get('$apiURL$GET_AUTHENTICATED_USER_PATH',
headers: headers);
}
Future<HttpieResponse> getUserWithUsername(String username,
{bool authenticatedRequest = true}) {
return _httpService.get('$apiURL$GET_USERS_PATH$username/',
appendAuthorizationToken: authenticatedRequest);
}
Future<HttpieResponse> getPostsCountForUserWithName(String username,
{bool authenticatedRequest = true}) {
return _httpService.get('$apiURL$GET_USERS_PATH$username/posts/count/',
appendAuthorizationToken: authenticatedRequest);
}
Future<HttpieResponse> getUsersWithQuery(String query,
{bool authenticatedRequest = true}) {
return _httpService.get('$apiURL$GET_USERS_PATH',
queryParameters: {'query': query},
appendAuthorizationToken: authenticatedRequest);
}
Future<HttpieResponse> searchLinkedUsers(
{required String query, int? count, String? withCommunity}) {
Map<String, dynamic> queryParams = {'query': query};
if (count != null) queryParams['count'] = count;
if (withCommunity != null) queryParams['with_community'] = withCommunity;
return _httpService.get('$apiURL$SEARCH_LINKED_USERS_PATH',
queryParameters: queryParams, appendAuthorizationToken: true);
}
Future<HttpieResponse> getLinkedUsers(
{bool authenticatedRequest = true,
int? maxId,
int? count,
String? withCommunity}) {
Map<String, dynamic> queryParams = {};
if (count != null) queryParams['count'] = count;
if (maxId != null) queryParams['max_id'] = maxId;
if (withCommunity != null) queryParams['with_community'] = withCommunity;
return _httpService.get('$apiURL$GET_LINKED_USERS_PATH',
queryParameters: queryParams,
appendAuthorizationToken: authenticatedRequest);
}
Future<HttpieResponse> searchBlockedUsers(
{required String query, int? count}) {
Map<String, dynamic> queryParams = {'query': query};
if (count != null) queryParams['count'] = count;
return _httpService.get('$apiURL$SEARCH_BLOCKED_USERS_PATH',
queryParameters: queryParams, appendAuthorizationToken: true);
}
Future<HttpieResponse> getBlockedUsers({
bool authenticatedRequest = true,
int? maxId,
int? count,
}) {
Map<String, dynamic> queryParams = {};
if (count != null) queryParams['count'] = count;
if (maxId != null) queryParams['max_id'] = maxId;
return _httpService.get('$apiURL$GET_BLOCKED_USERS_PATH',
queryParameters: queryParams,
appendAuthorizationToken: authenticatedRequest);
}
Future<HttpieResponse> blockUserWithUsername(String userUsername) {
String path = _makeBlockUserWithUsernamePath(userUsername);
return _httpService.post(_makeApiUrl(path), appendAuthorizationToken: true);
}
Future<HttpieResponse> unblockUserWithUsername(String userUsername) {
String path = _makeUnblockUserWithUsernamePath(userUsername);
return _httpService.post(_makeApiUrl(path), appendAuthorizationToken: true);
}
Future<HttpieResponse> enableNewPostNotificationsForUserWithUsername(
String userUsername) {
String path =
_makeEnableNewPostNotificationsForUserWithUsernamePath(userUsername);
return _httpService.putJSON(_makeApiUrl(path),
appendAuthorizationToken: true);
}
Future<HttpieResponse> disableNewPostNotificationsForUserWithUsername(
String userUsername) {
String path =
_makeEnableNewPostNotificationsForUserWithUsernamePath(userUsername);
return _httpService.delete(_makeApiUrl(path),
appendAuthorizationToken: true);
}
Future<HttpieResponse> searchFollowers({required String query, int? count}) {
Map<String, dynamic> queryParams = {'query': query};
if (count != null) queryParams['count'] = count;
return _httpService.get('$apiURL$SEARCH_FOLLOWERS_PATH',
queryParameters: queryParams, appendAuthorizationToken: true);
}
Future<HttpieResponse> getFollowers(
{bool authenticatedRequest = true, int? maxId, int? count}) {
Map<String, dynamic> queryParams = {};
if (count != null) queryParams['count'] = count;
if (maxId != null) queryParams['max_id'] = maxId;
return _httpService.get('$apiURL$GET_FOLLOWERS_PATH',
queryParameters: queryParams,
appendAuthorizationToken: authenticatedRequest);
}
Future<HttpieResponse> searchFollowings({required String query, int? count}) {
Map<String, dynamic> queryParams = {'query': query};
if (count != null) queryParams['count'] = count;
return _httpService.get('$apiURL$SEARCH_FOLLOWINGS_PATH',
queryParameters: queryParams, appendAuthorizationToken: true);
}
Future<HttpieResponse> getFollowings({
bool authenticatedRequest = true,
int? maxId,
int? count,
}) {
Map<String, dynamic> queryParams = {};
if (count != null) queryParams['count'] = count;
if (maxId != null) queryParams['max_id'] = maxId;
return _httpService.get('$apiURL$GET_FOLLOWINGS_PATH',
queryParameters: queryParams,
appendAuthorizationToken: authenticatedRequest);
}
Future<HttpieResponse> loginWithCredentials(
{required String username, required String password}) {
return this._httpService.postJSON('$apiURL$LOGIN_PATH',
body: {'username': username, 'password': password});
}
Future<HttpieResponse> requestPasswordReset({required String email}) {
var body = {};
if (email != null && email != '') {
body['email'] = email;
}
return this
._httpService
.postJSON('$apiURL$REQUEST_RESET_PASSWORD_PATH', body: body);
}
Future<HttpieResponse> verifyPasswordReset(
{String? newPassword, String? passwordResetToken}) {
return this._httpService.postJSON('$apiURL$VERIFY_RESET_PASSWORD_PATH',
body: {'new_password': newPassword, 'token': passwordResetToken});
}
Future<HttpieResponse> getAuthenticatedUserNotificationsSettings() {
return this._httpService.get(
'$apiURL$AUTHENTICATED_USER_NOTIFICATIONS_SETTINGS_PATH',
appendAuthorizationToken: true);
}
Future<HttpieResponse> updateAuthenticatedUserNotificationsSettings({
bool? postCommentNotifications,
bool? postCommentReplyNotifications,
bool? postCommentReactionNotifications,
bool? postCommentUserMentionNotifications,
bool? postUserMentionNotifications,
bool? postReactionNotifications,
bool? followNotifications,
bool? followRequestNotifications,
bool? followRequestApprovedNotifications,
bool? connectionRequestNotifications,
bool? connectionConfirmedNotifications,
bool? communityInviteNotifications,
bool? communityNewPostNotifications,
bool? userNewPostNotifications,
}) {
Map<String, dynamic> body = {};
if (postCommentNotifications != null)
body['post_comment_notifications'] = postCommentNotifications;
if (postCommentReplyNotifications != null)
body['post_comment_reply_notifications'] = postCommentReplyNotifications;
if (postCommentUserMentionNotifications != null)
body['post_comment_user_mention_notifications'] =
postCommentUserMentionNotifications;
if (postUserMentionNotifications != null)
body['post_user_mention_notifications'] = postUserMentionNotifications;
if (postCommentReactionNotifications != null)
body['post_comment_reaction_notifications'] =
postCommentReactionNotifications;
if (postReactionNotifications != null)
body['post_reaction_notifications'] = postReactionNotifications;
if (followNotifications != null)
body['follow_notifications'] = followNotifications;
if (followRequestNotifications != null)
body['follow_request_notifications'] = followRequestNotifications;
if (followRequestApprovedNotifications != null)
body['follow_request_approved_notifications'] =
followRequestApprovedNotifications;
if (connectionRequestNotifications != null)
body['connection_request_notifications'] = connectionRequestNotifications;
if (communityInviteNotifications != null)
body['community_invite_notifications'] = communityInviteNotifications;
if (communityNewPostNotifications != null)
body['community_new_post_notifications'] = communityNewPostNotifications;
if (userNewPostNotifications != null)
body['user_new_post_notifications'] = userNewPostNotifications;
if (connectionConfirmedNotifications != null)
body['connection_confirmed_notifications'] =
connectionConfirmedNotifications;
return _httpService.patchJSON(
'$apiURL$AUTHENTICATED_USER_NOTIFICATIONS_SETTINGS_PATH',
body: body,
appendAuthorizationToken: true);
}
Future<HttpieResponse> acceptGuidelines() {
return this
._httpService
.post('$apiURL$ACCEPT_GUIDELINES', appendAuthorizationToken: true);
}
Future<HttpieResponse> getAllLanguages() {
String url = _makeApiUrl(GET_NEW_LANGUAGE);
return _httpService.get(url, appendAuthorizationToken: true);
}
Future<HttpieResponse> setNewLanguage(Language language) {
Map<String, String> body = {'language_id': language.id.toString()};
return this._httpService.post('$apiURL$SET_NEW_LANGUAGE',
body: body, appendAuthorizationToken: true);
}
Future<HttpieResponse> reportUserWithUsername(
{required String userUsername,
required int moderationCategoryId,
String? description}) {
String path = _makeReportUserPath(username: userUsername);
Map<String, String> body = {'category_id': moderationCategoryId.toString()};
if (description != null && description.isNotEmpty) {
body['description'] = description;
}
return _httpService.post(_makeApiUrl(path),
body: body, appendAuthorizationToken: true);
}
String _makeBlockUserWithUsernamePath(String username) {
return _stringTemplateService
.parse(BLOCK_USER_PATH, {'userUsername': username});
}
String _makeUnblockUserWithUsernamePath(String username) {
return _stringTemplateService
.parse(UNBLOCK_USER_PATH, {'userUsername': username});
}
String _makeEnableNewPostNotificationsForUserWithUsernamePath(
String username) {
return _stringTemplateService.parse(
ENABLE_NEW_POST_NOTIFICATIONS_FOR_USER_PATH,
{'userUsername': username});
}
String _makeReportUserPath({required username}) {
return _stringTemplateService
.parse(REPORT_USER_PATH, {'userUsername': username});
}
String _makeApiUrl(String string) {
return '$apiURL$string';
}
}
setApiURL用于以下provider.dart中:
authApiService.setApiURL(environment.apiUrl);
postsApiService.setApiURL(environment.apiUrl);
emojisApiService.setApiURL(environment.apiUrl);
userInvitesApiService.setApiURL(environment.apiUrl);
followsApiService.setApiURL(environment.apiUrl);
moderationApiService.setApiURL(environment.apiUrl);
connectionsApiService.setApiURL(environment.apiUrl);
connectionsCirclesApiService.setApiURL(environment.apiUrl);
followsListsApiService.setApiURL(environment.apiUrl);
communitiesApiService.setApiURL(environment.apiUrl);
hashtagsApiService.setApiURL(environment.apiUrl);
categoriesApiService.setApiURL(environment.apiUrl);
notificationsApiService.setApiURL(environment.apiUrl);
devicesApiService.setApiURL(environment.apiUrl);
waitlistApiService
.setMyAppApiURL(environment.MyAppApiUrl);
编辑:我按照评论中的建议做了以下修改。在provider.dart中,setApiURL被调用:
authApiService.apiURL = ''; // Initialized apiURl(auth_api.dart) as empty String & Called authApiService(auth_api.dart) which contains the function setapiUrl
if (authApiService.apiURL.isEmpty) { authApiService.setApiURL(environment.apiUrl)};//Set a condition before using the apiUrl.
The above has no effect.
然后,我尝试了以下方法:
auth_api.dart
String? apiURL;
void setApiURL(String newApiURL) { if (apiURL == null) { apiURL = newApiURL; } }
The error now changes to Invalid argument(s): No host specified in URI nullapi/auth/login/
I reverted to original keeping only
String? apiURL;
and change the following in provider.dart
if (authApiService.apiURL == null) { authApiService.setApiURL(environment.apiUrl)}.
The error remians to to Invalid argument(s): No host specified in URI nullapi/auth/login/
根据Mohan的要求,我更新了以下内容:
user_invite.dart
static const INVITE_LINK = '{apiURL}api/auth/invite?token={token}';
user_invite_detail.dart
String inviteLink = _stringTemplateService.parse(UserInvite.INVITE_LINK, {'token': token, 'apiURL': apiURL});
List<Widget> _buildActionsList() {
if (widget.userInvite.createdUser != null) {
return [const SizedBox()];
}
return [
ListTile(
leading: const KNIcon(KNIcons.chat),
title: KNText(_localizationService.user__invites_share_yourself),
subtitle: KNSecondaryText(
_localizationService.user__invites_share_yourself_desc,
),
onTap: () {
String? apiURL = _userInvitesApiService.apiURL;
String token = widget.userInvite.token!;
Share.share(getShareMessageForInviteWithToken(token, apiURL));
},
),
ListTile(
leading: const KNIcon(KNIcons.email),
title: KNText(_localizationService.user__invites_share_email),
subtitle: KNSecondaryText(
_localizationService.user__invites_share_email_desc,
),
onTap: () async {
await _modalService.openSendUserInviteEmail(
context: context, userInvite: widget.userInvite);
Navigator.of(context).pop();
},
)
];
}
There are other files with this format like in connection_dart below:
String?apiURL;
void setApiURL(String newApiURL) {
apiURL = newApiURL;
}
Future<HttpieResponse> connectWithUserWithUsername(String username,
{List<int>? circlesIds}) {
Map<String, dynamic> body = {'username': username};
if (circlesIds != null) body['circles_ids'] = circlesIds;
return _httpService.postJSON('$apiURL$CONNECT_WITH_USER_PATH',
body: body, appendAuthorizationToken: true);
}
Future<HttpieResponse> confirmConnectionWithUserWithUsername(String username,
{List<int>? circlesIds}) {
Map<String, dynamic> body = {'username': username};
if (circlesIds != null) body['circles_ids'] = circlesIds;
return _httpService.postJSON('$apiURL$CONFIRM_CONNECTION_PATH',
body: body, appendAuthorizationToken: true);
}
Future<HttpieResponse> disconnectFromUserWithUsername(String username) {
return _httpService.postJSON('$apiURL$DISCONNECT_FROM_USER_PATH',
body: {'username': username}, appendAuthorizationToken: true);
}
Future<HttpieResponse> updateConnectionWithUsername(String username,
{List<int>? circlesIds}) {
Map<String, dynamic> body = {'username': username};
if (circlesIds != null) body['circles_ids'] = circlesIds;
return _httpService.postJSON('$apiURL$UPDATE_CONNECTION_PATH',
body: body, appendAuthorizationToken: true);
}
}
1条答案
按热度按时间wlp8pajw1#
LateInitializationError: Field 'apiURL' has not been initialized
这意味着
apiURL
在使用时尚未启动。因此,请确保在使用
apiURL
之前对其进行初始化,或者如果不确定,则将late String apiURL;
更改为String? apiURL;
,并在使用时添加空值检查。通过使
apiURL
可空,我们告诉编译器它可以是空值。