Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[BUG] v6: LateInitializationError when specifying initialCameraFit #1684

Closed
znromonk opened this issue Oct 10, 2023 · 5 comments · Fixed by #1691
Closed

[BUG] v6: LateInitializationError when specifying initialCameraFit #1684

znromonk opened this issue Oct 10, 2023 · 5 comments · Fixed by #1691
Labels
bug This issue reports broken functionality or another error P: 1 (important)

Comments

@znromonk
Copy link

znromonk commented Oct 10, 2023

What is the bug?

When running the sample code that includes initialCameraFit, LateInitializationError is thrown.

Console output
════════ Exception caught by widgets library ═══════════════════════════════════
The following LateError was thrown building LayoutBuilder:
LateInitializationError: Field '_interactiveViewerState@628435804' has not been initialized.

The relevant error-causing widget was
FlutterMap
main.dart:31
When the exception was thrown, this was the stack
#0      FlutterMapInternalController._interactiveViewerState (package:flutter_map/src/map/controller/internal.dart)
#1      FlutterMapInternalController._emitMapEvent
internal.dart:461
#2      FlutterMapInternalController.move
internal.dart:98
#3      FlutterMapInternalController.fitCamera
internal.dart:244
#4      _FlutterMapStateContainer._applyInitialCameraFit
widget.dart:212
#5      _FlutterMapStateContainer.build.<anonymous closure>
widget.dart:145
#6      _LayoutBuilderElement._layout.layoutCallback
layout_builder.dart:119
#7      BuildOwner.buildScope
framework.dart:2719
#8      _LayoutBuilderElement._layout
layout_builder.dart:153
#9      RenderObject.invokeLayoutCallback.<anonymous closure>
object.dart:2604
#10     PipelineOwner._enableMutationsToDirtySubtrees
object.dart:1059
#11     RenderObject.invokeLayoutCallback
object.dart:2604
#12     RenderConstrainedLayoutBuilder.rebuildIfNecessary
layout_builder.dart:228
#13     _RenderLayoutBuilder.performLayout
layout_builder.dart:313
#14     RenderObject.layout
object.dart:2493
#15     RenderBox.layout
box.dart:2382
#16     RenderProxyBoxMixin.performLayout
proxy_box.dart:104
#17     RenderObject.layout
object.dart:2493
#18     RenderBox.layout
box.dart:2382
#19     RenderConstrainedBox.performLayout
proxy_box.dart:279
#20     RenderObject.layout
object.dart:2493
#21     RenderBox.layout
box.dart:2382
#22     RenderPadding.performLayout
shifted_box.dart:238
#23     RenderObject.layout
object.dart:2493
#24     RenderBox.layout
box.dart:2382
#25     RenderProxyBoxMixin.performLayout
proxy_box.dart:104
#26     RenderObject.layout
object.dart:2493
#27     RenderBox.layout
box.dart:2382
#28     RenderProxyBoxMixin.performLayout
proxy_box.dart:104
#29     RenderObject.layout
object.dart:2493
#30     RenderBox.layout
box.dart:2382
#31     RenderSliverFixedExtentBoxAdaptor.performLayout
sliver_fixed_extent_list.dart:240
#32     RenderObject.layout
object.dart:2493
#33     RenderSliverEdgeInsetsPadding.performLayout
sliver_padding.dart:139
#34     _RenderSliverFractionalPadding.performLayout
sliver_fill.dart:160
#35     RenderObject.layout
object.dart:2493
#36     RenderViewportBase.layoutChildSequence
viewport.dart:534
#37     RenderViewport._attemptLayout
viewport.dart:1512
#38     RenderViewport.performLayout
viewport.dart:1421
#39     RenderObject._layoutWithoutResize
object.dart:2332
#40     PipelineOwner.flushLayout
object.dart:1013
#41     RendererBinding.drawFrame
binding.dart:494
#42     WidgetsBinding.drawFrame
binding.dart:918
#43     RendererBinding._handlePersistentFrameCallback
binding.dart:360
#44     SchedulerBinding._invokeFrameCallback
binding.dart:1297
#45     SchedulerBinding.handleDrawFrame
binding.dart:1227
#46     SchedulerBinding._handleDrawFrame
binding.dart:1085
#47     _invoke (dart:ui/hooks.dart:170:13)
#48     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:401:5)
#49     _drawFrame (dart:ui/hooks.dart:140:31)
════════════════════════════════════════════════════════════════════════════════

How can we reproduce it?

Sample Code
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 250,
      color: Colors.grey.shade100,
      child: FlutterMap(
        options: MapOptions(
          initialCameraFit: CameraFit.bounds(
            bounds: LatLngBounds.fromPoints(
              [
                const LatLng(0, 0),
                const LatLng(10, 0),
              ],
            ),
          ),
        ),
        children: [
          TileLayer(
            errorImage: Image.memory(base64Decode(
                    'iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAQAAAD2e2DtAAABnElEQVR42u3SQQEAAAQEMJdcdF5S2DIs08VjEUAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAAAQQQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEQQAABBEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAABEAAzgLXe38QsfcE+gAAAABJRU5ErkJggg=='))
                .image,
            fallbackUrl: '',
            tileProvider: NetworkTileProvider(),
            urlTemplate: '',
            tileSize: 256,
          ),
        ],
      ),
    );
  }
}

Do you have a potential solution?

Moving the initialCameraFit code to the onMapReady function can be an alternative approach.

onMapReady: () {
  _mapController.fitCamera(
    CameraFit.bounds(
      bounds: LatLngBounds.fromPoints(
        [
          const LatLng(0, 0),
          const LatLng(10, 0),
        ],
      ),
    ),
  );
},

Platforms

iOS

Severity

Erroneous: Prevents normal functioning and causes errors in the console

Details

  flutter_map: ^6.0.0
  latlong2: ^0.9.0
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.13.6, on macOS 14.0 23A344 darwin-arm64, locale en-US)
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 15.0)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2022.3)
[✓] VS Code (version 1.83.0)
[✓] Connected device (3 available)
[✓] Network resources

• No issues found!
@znromonk znromonk added bug This issue reports broken functionality or another error needs triage This new bug report needs reproducing and prioritizing labels Oct 10, 2023
@TesteurManiak
Copy link
Contributor

Can reproduce it with flutter_map v6 by adding the initialCameraFit in the HomePage widget.

@JaffaKetchup JaffaKetchup added needs triage This new bug report needs reproducing and prioritizing P: 1 (important) and removed needs triage This new bug report needs reproducing and prioritizing labels Oct 10, 2023
@BartoszStasiurka

This comment was marked as duplicate.

@JaffaKetchup
Copy link
Member

We're looking into this, please use the 👍 reaction to show you have the same issue unless you have more information to provide.

The internal call to _applyInitialCameraFit indirectly depends on the FlutterMapInteractiveViewer being built and initialized. At the moment, it is called before this point.
However, moving the call to the viewer's builder method causes the map to initially locate itself to the default point in Russia, then only locate after any new rebuild (for example, caused by a movement).

@JaffaKetchup JaffaKetchup changed the title [BUG] LateInitializationError when specifying initialCameraFit [BUG] LateInitializationError when specifying initialCameraFit Oct 11, 2023
@JaffaKetchup JaffaKetchup pinned this issue Oct 11, 2023
BartoszStasiurka added a commit to BartoszStasiurka/flutter_map that referenced this issue Oct 12, 2023
@BartoszStasiurka
Copy link

I've made some changes to fix this problem. It works, but it should be a better solution than mine. I had to use Future.delay because the map tiles were not loading. I have no idea why.
Have a look at my changes:
BartoszStasiurka@1bf5966
I hope it helps.

@JaffaKetchup
Copy link
Member

@BartoszStasiurka Thanks for this. Although it works in theory, if the tiles load within less than one frame, there'll be one frame before the camera fits. The chances of that happening are extremely unlikely of course, but something to think about.

TKFRvisionOfficial added a commit to tlm-solutions/strasi that referenced this issue Oct 14, 2023
- Fixes _interactiveviewerstate has not been initialized
- Reverse once fleaflet/flutter_map#1684 fixed
@JaffaKetchup JaffaKetchup changed the title [BUG] LateInitializationError when specifying initialCameraFit [BUG] v6: LateInitializationError when specifying initialCameraFit Oct 20, 2023
@JaffaKetchup JaffaKetchup unpinned this issue Oct 23, 2023
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
bug This issue reports broken functionality or another error P: 1 (important)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants