Flutter运行报错:type 'Null' is not a subtype of type 'String' in type cast
Flutter运行报错:
type 'Null' is not a subtype of type 'String' in type cast 报错信息
I/flutter ( 8093): type 'Null' is not a subtype of type 'String' in type cast I/flutter ( 8093): #0 new Future.value (dart:async/future.dart:349:59) I/flutter ( 8093): #1 ProxySettings.findProxy (package:Myapp/plugins/proxy_settings.dart:14:21) I/flutter ( 8093): #2 MyAppProviderState.initAsyncState (package:Myapp/provider.dart:215:39) I/flutter ( 8093): <asynchronous suspension> I/flutter ( 8093): In dev mode. Not sending report to Sentry.io. I/flutter ( 8093): Clearing prompted user for permission
相关代码及配置
provider.dart(第215行对应报错位置)
void initAsyncState() async { Environment environment = await EnvironmentLoader(environmentPath: ".env.json").load(); httpService.setMagicHeader( environment.magicHeaderName, environment.magicHeaderValue); httpService .setProxy(await ProxySettings.findProxy(Uri.parse(environment.apiUrl))); }
environment_loader.dart
import 'dart:async' show Future; import 'dart:convert' show json; import 'package:flutter/services.dart' show rootBundle; class EnvironmentLoader { final String? environmentPath; EnvironmentLoader({this.environmentPath}); Future<Environment> load() { return rootBundle.loadStructuredData<Environment>(this.environmentPath!, (jsonStr) async { final environmentLoader = Environment.fromJson(json.decode(jsonStr)); return environmentLoader; }); } } class Environment { final String apiUrl; final String magicHeaderName; final String magicHeaderValue; final String sentryDsn; final String myappapiurl; final String linkPreviewsTrustedProxyUrl; const Environment( { this.sentryDsn = '', this.myappapiurl = '', this.apiUrl = '', this.magicHeaderName = '', this.magicHeaderValue = '', this.linkPreviewsTrustedProxyUrl = '', }); factory Environment.fromJson(Map<String, dynamic> jsonMap) { return new Environment( apiUrl: jsonMap["API_URL"], magicHeaderName: jsonMap["MAGIC_HEADER_NAME"], magicHeaderValue: jsonMap["MAGIC_HEADER_VALUE"], sentryDsn: jsonMap["SENTRY_DSN"], myappapiurl: jsonMap["KOSMOSNETWORK_SOCIAL_API_URL"], linkPreviewsTrustedProxyUrl: jsonMap["LINK_PREVIEWS_TRUSTED_PROXY_URL"], ); } }
.env.json
{ "API_URL": "http://'mydomain':80/", "MAGIC_HEADER_NAME": "", "MAGIC_HEADER_VALUE": "", "SENTRY_DSN": "", "APP_SOCIAL_API_URL": "http://'mydomain':80/", "LINK_PREVIEWS_TRUSTED_PROXY_URL": "http://'mydomain':80/" }
AndroidManifest.xml(相关配置)
<intent-filter android:autoVerify="true"> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <data android:scheme="http" android:host="mydomain" android:pathPrefix="/api/auth/"/> </intent-filter> <intent-filter android:autoVerify="true"> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <data android:scheme="https" android:host="mydomain" android:pathPrefix="/api/auth/"/>
问题分析与解决方法
核心问题
- 环境变量键名不匹配:
Environment.fromJson中读取myappapiurl用的键是KOSMOSNETWORK_SOCIAL_API_URL,但.env.json里对应的键是APP_SOCIAL_API_URL,导致该字段被赋值为null,触发非空String类型的转换错误。 - 未处理null值兜底:从JSON读取字段时直接赋值,没有处理键缺失或值为
null的情况,违反了Dart的空安全规则。 - ProxySettings.findProxy内部逻辑问题:报错堆栈显示该方法第14行将
null当作String处理,导致Future.value触发类型转换异常。
修复步骤
1. 修正环境变量键名
修改.env.json中的键名,与代码保持一致,同时清理URL中的多余单引号:
{ "API_URL": "http://mydomain:80/", "MAGIC_HEADER_NAME": "", "MAGIC_HEADER_VALUE": "", "SENTRY_DSN": "", "KOSMOSNETWORK_SOCIAL_API_URL": "http://mydomain:80/", "LINK_PREVIEWS_TRUSTED_PROXY_URL": "http://mydomain:80/" }
2. 给环境变量添加null安全兜底
修改Environment.fromJson方法,用空值合并运算符??确保字段不会为null:
factory Environment.fromJson(Map<String, dynamic> jsonMap) { return Environment( apiUrl: jsonMap["API_URL"] ?? "", magicHeaderName: jsonMap["MAGIC_HEADER_NAME"] ?? "", magicHeaderValue: jsonMap["MAGIC_HEADER_VALUE"] ?? "", sentryDsn: jsonMap["SENTRY_DSN"] ?? "", myappapiurl: jsonMap["KOSMOSNETWORK_SOCIAL_API_URL"] ?? "", linkPreviewsTrustedProxyUrl: jsonMap["LINK_PREVIEWS_TRUSTED_PROXY_URL"] ?? "", ); }
3. 修复ProxySettings.findProxy的空值问题
检查proxy_settings.dart第14行代码,确保返回值不为null,示例修正:
static Future<String> findProxy(Uri uri) async { String? proxyConfig = await getProxyConfig(); // 假设原方法可能返回null return proxyConfig ?? ""; // 兜底返回空字符串 }
4. 增加URL合法性校验
避免非法URL导致的解析错误:
void initAsyncState() async { Environment environment = await EnvironmentLoader(environmentPath: ".env.json").load(); httpService.setMagicHeader( environment.magicHeaderName, environment.magicHeaderValue); final uri = Uri.tryParse(environment.apiUrl); if (uri != null) { httpService.setProxy(await ProxySettings.findProxy(uri)); } else { httpService.setProxy(""); // 非法URL时使用默认值 } }
内容的提问来源于stack exchange,提问作者Ananth
相关产品推荐
相关产品推荐

