Network image as Marker for google_maps_flutter

huangapple go评论47阅读模式
英文:

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 =
        &quot;http://domain/image.jpg&quot;;
        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,
            &quot;origin&quot;,
            markerbitmap ?? BitmapDescriptor.defaultMarker,
        );
        _addMarker(
            latLng_2,
            &quot;destination&quot;,
            markerbitmap ?? BitmapDescriptor.defaultMarker,
        );
        _addMarker(
            LatLng(31.5096673920523, 74.37318230126559),
            &quot;waypoint&quot;,
            markerbitmap ?? BitmapDescriptor.defaultMarker,
        );
        setState(() {
        });
    }
    
    GoogleMap(
        onMapCreated: _onMapCreated,
        initialCameraPosition: _kGooglePlex,
        mapType: MapType.normal,
        tiltGesturesEnabled: true,
        compassEnabled: true,
        scrollGesturesEnabled: true,
        zoomGesturesEnabled: true,
        polylines: Set &lt; Polyline &gt;.of(_polylines.values),
        markers: Set &lt; Marker &gt;.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:

  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.

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 &lt;Uint8List&gt;getpicture() async {
  String imgurl = &quot;http://domain/image.jpg&quot;;
  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 &lt;Uint8List&gt; _getPictureFuture;

@override
void initState() {
  super.initState();
  _getPictureFuture = getpicture();
}

Use the future function in a FutureBuilder:

FutureBuilder&lt;Uint8List&gt;(
  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());
  });
)

huangapple
  • 本文由 发表于 2023年3月8日 16:15:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/75670658.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定