英文:
Network image as Marker for google_maps_flutter
问题
以下是你要翻译的代码部分:
我正在尝试将网络图像用作[google_maps_flutter][1]的标记。它一直显示默认的图钉占位符。
var markerbitmap;
getpicture() async {
String imgurl =
"http://domain/image.jpg";
Uint8List bytes = (await NetworkAssetBundle(Uri.parse(imgurl)).load(imgurl))
.buffer
.asUint8List();
setState(() {
markerbitmap = BitmapDescriptor.fromBytes(bytes);
});
}
@override
void initState() {
getpicture();
}
_addMarker(LatLng position, String id, BitmapDescriptor descriptor) {
MarkerId markerId = MarkerId(id);
Marker marker =
Marker(markerId: markerId, icon: descriptor, position: position);
_markers[markerId] = marker;
}
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
LatLng latLng_1 = LatLng(startCoordinatesLat, startCoordinatesLng);
LatLng latLng_2 = LatLng(endCoordinatesLat, endCoordinatesLng);
_markers.clear();
_addMarker(
latLng_1,
"origin",
markerbitmap ?? BitmapDescriptor.defaultMarker,
);
_addMarker(
latLng_2,
"destination",
markerbitmap ?? BitmapDescriptor.defaultMarker,
);
_addMarker(
LatLng(31.5096673920523, 74.37318230126559),
"waypoint",
markerbitmap ?? BitmapDescriptor.defaultMarker,
);
setState(() {
});
}
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: _kGooglePlex,
mapType: MapType.normal,
tiltGesturesEnabled: true,
compassEnabled: true,
scrollGesturesEnabled: true,
zoomGesturesEnabled: true,
polylines: Set < Polyline >.of(_polylines.values),
markers: Set < Marker >.of(_markers.values),
onCameraMove: _onCameraMove,
myLocationButtonEnabled: false,
)
<details>
<summary>英文:</summary>
I am trying to use Network image as marker for the [google_maps_flutter][1]. It keeps on showing me the default pin holder instead.
var markerbitmap;
getpicture() async {
String imgurl =
"http://domain/image.jpg";
Uint8List bytes = (await NetworkAssetBundle(Uri.parse(imgurl)).load(imgurl))
.buffer
.asUint8List();
setState(() {
markerbitmap = BitmapDescriptor.fromBytes(bytes);
});
}
@override
void initState() {
getpicture();
}
_addMarker(LatLng position, String id, BitmapDescriptor descriptor) {
MarkerId markerId = MarkerId(id);
Marker marker =
Marker(markerId: markerId, icon: descriptor, position: position);
_markers[markerId] = marker;
}
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
LatLng latLng_1 = LatLng(startCoordinatesLat, startCoordinatesLng);
LatLng latLng_2 = LatLng(endCoordinatesLat, endCoordinatesLng);
_markers.clear();
_addMarker(
latLng_1,
"origin",
markerbitmap ?? BitmapDescriptor.defaultMarker,
);
_addMarker(
latLng_2,
"destination",
markerbitmap ?? BitmapDescriptor.defaultMarker,
);
_addMarker(
LatLng(31.5096673920523, 74.37318230126559),
"waypoint",
markerbitmap ?? BitmapDescriptor.defaultMarker,
);
setState(() {
});
}
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: _kGooglePlex,
mapType: MapType.normal,
tiltGesturesEnabled: true,
compassEnabled: true,
scrollGesturesEnabled: true,
zoomGesturesEnabled: true,
polylines: Set < Polyline >.of(_polylines.values),
markers: Set < Marker >.of(_markers.values),
onCameraMove: _onCameraMove,
myLocationButtonEnabled: false,
)
[1]: https://pub.dev/packages/google_maps_flutter
</details>
# 答案1
**得分**: 1
I think the problem here is that `getpicture()` is an async function, and you call it in `initState`, but the `build` method where you create `GoogleMap` widget will run **before this future completes**.
即刻问题出在 `getpicture()` 是一个异步函数,而你在 `initState` 中调用它,但在创建 `GoogleMap` widget 的 `build` 方法运行之前,这个未来可能尚未完成。
Even if you call `setState` after `getpicture()` fetches the network image, the `GoogleMap` widget will not be rebuilt because the variable `markerbitmap` is not used directly when building your widget: it is used only in `_onMapCreated` function, which runs once `GoogleMap` is created.
即使在 `getpicture()` 获取网络图像之后调用 `setState`,`GoogleMap` widget 也不会重新构建,因为变量 `markerbitmap` 在构建小部件时没有直接使用:它只在 `_onMapCreated` 函数中使用,该函数在创建 `GoogleMap` 后运行一次。
So this is what happens:
1. `initState` called
2. `getpicture` starts
3. `build` method is called
4. `GoogleMap` widget is built
5. `_onMapCreated` is called
6. `markerbitmap` is still empty so default marker is used
7. ... (async gap)
8. after some time `getpicture` is finished and `markerbitmap` is set but the widget is already built.
因此,情况如下:
1. 调用 `initState`
2. `getpicture` 开始
3. 调用 `build` 方法
4. 构建 `GoogleMap` 小部件
5. 调用 `_onMapCreated`
6. `markerbitmap` 仍然为空,因此使用默认标记
7. ...(异步间隔)
8. 一段时间后,`getpicture` 完成并设置了 `markerbitmap`,但小部件已经构建完成。
I would try to use a `FutureBuilder` to get the network image and build `GoogleMap` only when it is completed.
我建议尝试使用 `FutureBuilder` 来获取网络图像,并仅在完成时构建 `GoogleMap`。
Transform `getpicture` to future function:
将 `getpicture` 转换为 Future 函数:
```dart
Future<Uint8List> getpicture() async {
String imgurl = "http://domain/image.jpg";
Uint8List bytes = (await NetworkAssetBundle(Uri.parse(imgurl)).load(imgurl))
.buffer
.asUint8List();
return bytes;
}
Create a state class member for the future and assign a value to it in initState
:
在 initState
中为该 Future 创建一个状态类成员,并为其分配一个值:
late final Future<Uint8List> _getPictureFuture;
@override
void initState() {
super.initState();
_getPictureFuture = getpicture();
}
Use the future function in a FutureBuilder
:
在 FutureBuilder
中使用该 Future 函数:
FutureBuilder<Uint8List>(
future: _getPictureFuture,
builder: (context, snapshot) {
if (snapshot.hasData) {
// here you have the data from the completed future
markerbitmap = BitmapDescriptor.fromBytes(snapshot.data!);
return GoogleMap(...);
}
else if (snapshot.hasError) {
// handle error
}
// display progress indicator
return const Center(
child: CircularProgressIndicator());
});
)
英文:
I think the problem here is that getpicture()
is an async function, and you call it in initState
, but the build
method where you create GoogleMap
widget will run before this future completes.
Even if you call setState
after getpicture()
fetches the network image, the GoogleMap
widget will not be rebuilt because the variable markerbitmap
is not used directly when building your widget: it is used only in _onMapCreated
function, which runs once GoogleMap
is created.
So this is what happens:
initState
calledgetpicture
startsbuild
method is calledGoogleMap
widget is built_onMapCreated
is calledmarkerbitmap
is still empty so default marker is used- ... (async gap)
- after some time
getpicture
is finished andmarkerbitmap
is set but the widget is already built.
I would try to use a FutureBuilder
to get the network image and build GoogleMap
only when it is completed.
Transform getpicture
to future function:
Future <Uint8List>getpicture() async {
String imgurl = "http://domain/image.jpg";
Uint8List bytes = (await NetworkAssetBundle(Uri.parse(imgurl)).load(imgurl))
.buffer
.asUint8List();
return bytes;
}
Create a state class member for the future and assign a value to it in initState
:
late final Future <Uint8List> _getPictureFuture;
@override
void initState() {
super.initState();
_getPictureFuture = getpicture();
}
Use the future function in a FutureBuilder
:
FutureBuilder<Uint8List>(
future: _getPictureFuture,
builder: (context, snapshot) {
if (snapshot.hasData) {
// here you have the data from the completed future
markerbitmap = BitmapDescriptor.fromBytes(snapshot.data!);
return GoogleMap(...);
}
else if (snapshot.hasError) {
// handle error
}
// display progress indicator
return const Center(
child: CircularProgressIndicator());
});
)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论