-
Notifications
You must be signed in to change notification settings - Fork 26.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[google_maps_flutter] Marker is flickering when marker update and rebuild. #147153
Comments
Thanks for your reminding. I have checked the issue before, but nothing useful. It's look like different from what I meet. Here is the minimal code sample without flutter_riverpod main.dartimport 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'GOOGLE MAP FLASH',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Google Map Flash'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[Expanded(child: MapWidget())],
),
),
);
}
}
class MapWidget extends StatefulWidget {
const MapWidget({super.key});
@override
State<StatefulWidget> createState() => _MapWidgetState();
}
class _MapWidgetState extends State<MapWidget> {
final Completer<GoogleMapController> _mapController = Completer<GoogleMapController>();
late final GoogleMapController controller;
static const defaultZoom = 16.0;
late List<Marker> markersList = markersNotifier.markerList;
late int lastRebuildTime;
@override
void initState() {
super.initState();
nowIndexProvider.addListener(() {
if (nowIndexProvider.nowIndex != -1) {
CameraPosition cameraPos = CameraPosition(target: getlocation[nowIndexProvider.nowIndex], zoom: defaultZoom);
controller.animateCamera(CameraUpdate.newCameraPosition(cameraPos));
}
if (nowIndexProvider.nowIndex == -1) {
// set all marker to default color
markersNotifier.changeMarker(nowIndexProvider.oldIndex, BitmapDescriptor.defaultMarker, 0);
} else if (nowIndexProvider.oldIndex != -1 && nowIndexProvider.oldIndex! < getlocation.length) {
// change the target marker to special color
markersNotifier.changeMarker(nowIndexProvider.oldIndex, BitmapDescriptor.defaultMarker, 0);
markersNotifier.changeMarker(nowIndexProvider.nowIndex, BitmapDescriptor.defaultMarkerWithHue(60), 1.0);
} else {
// change the target marker to special color
markersNotifier.changeMarker(nowIndexProvider.nowIndex, BitmapDescriptor.defaultMarkerWithHue(60), 1.0);
}
});
markersNotifier.addListener(() async {
int rebuildTimeDiff = DateTime.now().millisecondsSinceEpoch - lastRebuildTime;
if (rebuildTimeDiff < 200) {
await Future.delayed(Duration(milliseconds: 200 - rebuildTimeDiff));
}
setState(() {
// refresh marker when markersList update
markersList = markersNotifier.markerList;
});
});
WidgetsBinding.instance.addPostFrameCallback((_) async {
// refresh icon after get markersList from backend
markersNotifier.setState(getMarker());
controller = await _mapController.future;
});
}
/// a mock of api which returns a list of position
List<LatLng> getlocation = [
const LatLng(35.5594, 139.7210),
const LatLng(35.5604, 139.7210),
const LatLng(35.5614, 139.7210),
const LatLng(35.5624, 139.7210),
const LatLng(35.5634, 139.7210),
const LatLng(35.5644, 139.7210),
const LatLng(35.5654, 139.7210),
const LatLng(35.5664, 139.7210),
const LatLng(35.5674, 139.7210),
];
getMarker() {
List<Marker> markerList = [];
for (var i = 0; i < getlocation.length; i++) {
var marker = Marker(
markerId: MarkerId('$i'),
position: LatLng(getlocation[i].latitude, getlocation[i].longitude),
icon: BitmapDescriptor.defaultMarker,
consumeTapEvents: true,
onTap: () {
nowIndexProvider.changeIndex(i);
},
zIndex: 0,
);
markerList.add(marker);
}
return markerList;
}
@override
Widget build(BuildContext context) {
lastRebuildTime = DateTime.now().millisecondsSinceEpoch;
return GoogleMap(
mapType: MapType.normal,
initialCameraPosition: const CameraPosition(target: LatLng(35.5594, 139.7210), zoom: defaultZoom),
markers: Set.of(markersList),
onMapCreated: (GoogleMapController controller) {
if (!_mapController.isCompleted) {
_mapController.complete(controller);
}
},
mapToolbarEnabled: false,
zoomControlsEnabled: false,
myLocationButtonEnabled: false,
onTap: (argument) async {
nowIndexProvider.changeIndex(-1);
},
);
}
}
class MarkersNotifier extends ChangeNotifier {
List<Marker> _markerList = [];
List<Marker> get markerList => _markerList;
void changeMarker(int index, BitmapDescriptor bitmap, double zIndex) {
var item = _markerList[index];
var marker = Marker(
markerId: item.markerId,
position: item.position,
consumeTapEvents: item.consumeTapEvents,
icon: bitmap,
onTap: item.onTap,
zIndex: zIndex,
);
_markerList[index] = marker;
notifyListeners();
}
void setState(List<Marker> markerListTemp) {
_markerList = markerListTemp;
notifyListeners();
}
}
MarkersNotifier markersNotifier = MarkersNotifier();
class NowIndexProvider extends ChangeNotifier {
int _nowIndex = -1;
int _oldIndex = -1;
int get nowIndex => _nowIndex;
int get oldIndex => _oldIndex;
changeIndex(int index) {
_oldIndex = _nowIndex;
_nowIndex = index;
notifyListeners();
}
}
NowIndexProvider nowIndexProvider = NowIndexProvider();
pubspec.yamlname: google_map_flash
description: "A new Flutter project."
version: 1.0.0+1
environment:
sdk: '>=3.3.1 <4.0.0'
dependencies:
flutter:
sdk: flutter
google_maps_flutter: ^2.6.1
cupertino_icons: ^1.0.6
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^3.0.0
flutter:
uses-material-design: true still could reproduce the problem by this code. Screenrecorder-2024-04-23-09-21-11-563.mp4 |
Thanks for the update. I tried replicating on Pixel XL api 33 emulator, but wasn't able to see the reported behavior. |
Thanks for your trying. Look this video. Videorecord.online-video-cutter.com.mp4On real device, almost evetimes could reproduce the behavior. Here some information of device what I used. Emulator
Real Device
|
Thanks for the update. I tried on Samsung S10 device and also on PIxel XL emulator running Android 13, but was unable to see the flickering. Does the flickering occur while trying to drag the marker or while zooming in and out ? Screen_Recording_20240424_111624.mp4 |
Thanks for your trying. By your video, I think I caused a misunderstanding by not describing my operations in detail. try this.
Maybe useful This is my code sample. Same as the code I provided before. Just need to change the googleMapApiKey to yourself's By the way, did your see any black road in map on PIxel XL emulator? PIxel XL emulator has no Play Store on my mac. |
Thanks for the update and patience while we try to figure this out. 147153.movI ran on latest stable version and on Pixel XL emulator running Android 13. |
Could you click between marker and map, not between marker and marker? In addition, it is easier to reproduce the problem on a real device. My colleagues all reproduced this problem on their mobile phones. Anyway, thanks for your work. |
Thanks for the update. I was able to replicate this by running on S10 device with latest versions. Screen_Recording_20240426_115511.mp4stable, master flutter doctor -v
|
From triage: There are major changes planned for markers. We will re-investigate after flutter/packages#4055 lands. |
This issue is missing a priority label. Please set a priority label when adding the |
@jokerttu is currently working on marker improvements. I am not sure if this issue will be addressed as part of that work. |
Steps to reproduce
When update the marker List and rebuild, the target marker will flicker. Not every times but easy to reproduce.
Only happened on Android. iOS is good.
Device: Android 14 API 34(whatever simulator or real device)
try this with the minimal code sample.
it works good before I upgrade SDK version
Before:
After:
Anything helpful? Thanks to everyone.
Minimal Code sample
main.dart
pubspec.yaml
Video
Screenrecorder-2024-04-22-17-30-44-99.mp4
Logs
Flutter Doctor output
The text was updated successfully, but these errors were encountered: