我有一个错误,我只是找不到解决方案。我在 flutter 中创建了一个小消息,并且在我的一个聊天气泡中使用 NetworkImage 时遇到了问题。
当我将图像作为消息发送时,它在气泡中显示没有问题。此外,当我发送多张图像时,没有问题,它们超出了屏幕,我可以上下滚动而不会出现任何问题。
虽然当我重新打开房间屏幕并且有多个图像并且它们延伸到可见屏幕上时,我从 network_image dart 文件中得到了 _CastError(类型“Null”不是类型转换中类型“List”的子类型)。但这只发生在热重启后。如果我只是向后导航然后重新打开房间屏幕也一切正常,但是一旦我热重启,我在尝试打开一个房间时总是会出现错误,该房间的图像扩展了可见空间。
我对 flutter 还是有点陌生,所以我知道我的代码很烂,但这次我什至没有找到解决它的“肮脏”方法。
Flutter 2.2.0(测试版)
Dart 2.13.0
在 Android 模拟器 Pixel 4a API 30 上
编辑 1:我删除了很多内容以使其更易于阅读。
编辑 2:我发现它以某种方式连接到使用来自 Firebase 存储的 downloadURL。当我只用一些测试 png url 替换 url 时,它似乎不是问题。
import 'package:bubble/bubble.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:app/src/app/provider/firestore_provider.dart';
class MessageRoomCopy extends ConsumerWidget {
final String roomName;
final String roomID;
MessageRoomCopy(this.roomName, this.roomID);
@override
Widget build(BuildContext context, ScopedReader watch) {
final firestoreServ = watch(firestoreServiceProvider);
return Scaffold(
backgroundColor: Color(0xFFECE5DD),
appBar: AppBar(title: Text("$roomName", style: TextStyle(color: Colors.white))),
body: StreamBuilder(
stream: firestoreServ.messagesOfRoom("$roomID"),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> snapshot) {
if (snapshot.hasError) {
return Center(
child: Text("Error"),
);
} else if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else {
final List<QueryDocumentSnapshot<Map<String, dynamic>>> messagesList = snapshot.data!.docs;
return ListView.separated(
reverse: true,
//shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
var _messageBubble;
double? _elevation = 2.0;
BubbleEdges? _margin = BubbleEdges.only(top: 10);
BubbleNip? _nip = BubbleNip.rightTop;
bool? _showNip = true;
Alignment? _alignment = Alignment.topRight;
Color? _color = Color.fromRGBO(225, 255, 199, 1.0);
Widget? _messageChild;
if (messagesList[index].get("messagetype") == "text") {
_messageChild = Text(
messagesList[index].get("content"),
style: Theme.of(context).textTheme.bodyText2,
);
} else if (messagesList[index].get("messagetype") == "image") {
_messageChild = Image.network(
messagesList[index].get("content"),
errorBuilder: (BuildContext context, Object exception, StackTrace? stackTrace) {
return Text("Error Wdiget");
},
);
}
_messageBubble = Bubble(
elevation: _elevation,
margin: _margin,
nip: _nip,
showNip: _showNip,
alignment: _alignment,
color: _color,
child: _messageChild,
);
return Container(
child: Column(
children: [
_messageBubble,
],
),
);
},
separatorBuilder: (BuildContext context, int index) => Divider(
height: 1,
color: Colors.transparent,
),
itemCount: messagesList.length,
);
}
}),
);
}
}
这也是错误重新抛出来自 _network_image_io.dart 内部的地方Future<ui.Codec> _loadAsync(
NetworkImage key,
StreamController<ImageChunkEvent> chunkEvents,
image_provider.DecoderCallback decode,
) async {
try {
assert(key == this);
final Uri resolved = Uri.base.resolve(key.url);
final HttpClientRequest request = await _httpClient.getUrl(resolved);
headers?.forEach((String name, String value) {
request.headers.add(name, value);
});
final HttpClientResponse response = await request.close();
if (response.statusCode != HttpStatus.ok) {
// The network may be only temporarily unavailable, or the file will be
// added on the server later. Avoid having future calls to resolve
// fail to check the network again.
await response.drain<List<int>>();
throw image_provider.NetworkImageLoadException(statusCode: response.statusCode, uri: resolved);
}
final Uint8List bytes = await consolidateHttpClientResponseBytes(
response,
onBytesReceived: (int cumulative, int? total) {
chunkEvents.add(ImageChunkEvent(
cumulativeBytesLoaded: cumulative,
expectedTotalBytes: total,
));
},
);
if (bytes.lengthInBytes == 0)
throw Exception('NetworkImage is an empty file: $resolved');
return decode(bytes);
} catch (e) {
// Depending on where the exception was thrown, the image cache may not
// have had a chance to track the key in the cache at all.
// Schedule a microtask to give the cache a chance to add the key.
scheduleMicrotask(() {
PaintingBinding.instance!.imageCache!.evict(key);
});
rethrow; // here this one
} finally {
chunkEvents.close();
}
}
最佳答案
好的,我找到了问题所在。我将 Firebase servertimestamp 作为 Firebase 存储中文件名的变量。那当然只会导致文件名被
FieldValue('MethodChannelFieldValue'的实例)
虽然我真的不明白为什么这是一个问题,但现在使用正常的 Datetime toString 时间戳,它一切正常。也许它的一些特殊字符在从 Firebase Storage 生成的 downloadURL 中使用这种文件名转义。
关于flutter - _CastError(类型 'Null' 在类型转换中不是类型 'List<int>' 的子类型)当在 Listview 中有网络图像时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67909411/