Skip to content

Commit 485e597

Browse files
committed
--- v1.1.2 ---
1 parent b6a6c21 commit 485e597

File tree

3 files changed

+173
-106
lines changed

3 files changed

+173
-106
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
## 1.1.2
2+
3+
* Fixed chart disappearance on rebuild. (#65)
4+
15
## 1.1.1
26

3-
* Fixed blue box appearing after tab. (#63)
7+
* Fixed blue box appearing after tap. (#63)
48
* Improved generated documentation.
59

610
## 1.1.0

lib/utilities/highcharts_view.dart

Lines changed: 167 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
/* *
22
*
3-
* Highcharts Flutter
3+
* Highcharts Flutter
44
*
5-
* Copyright (c) 2023-2025, Highsoft AS
5+
* Copyright (c) 2023-2025, Highsoft AS
66
*
7-
* License: www.highcharts.com/license
7+
* License: www.highcharts.com/license
88
*
99
* */
1010

@@ -34,82 +34,7 @@ class HighchartsView extends StatefulWidget {
3434
this.onLoading,
3535
this.onMounted,
3636
}) {
37-
PlatformWebViewControllerCreationParams params;
38-
39-
if (WebViewPlatform.instance is AndroidWebViewPlatform) {
40-
params = AndroidWebViewControllerCreationParams();
41-
} else if (WebViewPlatform.instance is WebKitWebViewPlatform) {
42-
params = WebKitWebViewControllerCreationParams();
43-
} else {
44-
params = const PlatformWebViewControllerCreationParams();
45-
}
46-
47-
webViewController = WebViewController.fromPlatformCreationParams(params);
48-
49-
if (webViewController.platform is WebKitWebViewController) {
50-
(webViewController.platform as WebKitWebViewController)
51-
.setInspectable(true);
52-
}
53-
54-
if (webViewController.platform is AndroidWebViewController ||
55-
webViewController.platform is WebKitWebViewController) {
56-
webViewController
57-
..setBackgroundColor(const Color(0x00000000))
58-
..setJavaScriptMode(JavaScriptMode.unrestricted);
59-
}
60-
61-
webViewController
62-
..setNavigationDelegate(NavigationDelegate(onPageFinished: (_) {
63-
if (onMounted != null) {
64-
onMounted!(this);
65-
}
66-
}))
67-
..addJavaScriptChannel(
68-
'highcharts_flutter_channel',
69-
onMessageReceived: (e) async {
70-
final dataIndex = e.message.indexOf('\n');
71-
72-
final callbackKey =
73-
(dataIndex < 0 ? e.message : e.message.substring(0, dataIndex));
74-
final data = (dataIndex < 0
75-
? []
76-
: (jsonDecode(e.message.substring(dataIndex + 1)) ?? []));
77-
78-
if (callbackKey == 'highcharts_flutter.chart') {
79-
if (onLoaded != null) {
80-
onLoaded!(this);
81-
}
82-
return;
83-
}
84-
85-
if (HighchartsCallback.registry.containsKey(callbackKey)) {
86-
HighchartsCallback.registry[callbackKey]!(data);
87-
return;
88-
}
89-
90-
if (_events.containsKey(callbackKey)) {
91-
for (final callback in _events[callbackKey]!) {
92-
await callback(data);
93-
}
94-
return;
95-
}
96-
97-
if (debug) {
98-
debugPrint('Unhandled callback: ${e.message}');
99-
}
100-
},
101-
);
102-
103-
if (WebViewPlatform.instance is AndroidWebViewPlatform) {
104-
webView = WebViewWidget.fromPlatformCreationParams(
105-
params: AndroidWebViewWidgetCreationParams(
106-
controller: webViewController.platform,
107-
displayWithHybridComposition: true, // Fix scrolling interference
108-
),
109-
);
110-
} else {
111-
webView = WebViewWidget(controller: webViewController);
112-
}
37+
_stateBridge = _HighchartsViewStateBridge(this);
11338
}
11439

11540
final String? body;
@@ -132,9 +57,15 @@ class HighchartsView extends StatefulWidget {
13257

13358
final void Function(HighchartsView)? onMounted;
13459

135-
late final WebViewWidget webView;
60+
late final _HighchartsViewStateBridge _stateBridge;
13661

137-
late final WebViewController webViewController;
62+
WebViewController get webViewController {
63+
return _stateBridge.webViewController;
64+
}
65+
66+
WebViewWidget get webView {
67+
return _stateBridge.webView;
68+
}
13869

13970
@override
14071
State<HighchartsView> createState() {
@@ -175,11 +106,17 @@ class HighchartsView extends StatefulWidget {
175106
class _HighchartsViewState extends State<HighchartsView>
176107
with AutomaticKeepAliveClientMixin {
177108
List<String> _assets = [];
109+
178110
bool _disposed = false;
111+
179112
bool _prepared = false;
180113

114+
late _HighchartsViewStateBridge _stateBridge;
115+
181116
@override
182-
bool get wantKeepAlive => widget.keepAlive;
117+
bool get wantKeepAlive {
118+
return widget.keepAlive;
119+
}
183120

184121
@override
185122
Widget build(BuildContext context) {
@@ -191,24 +128,27 @@ class _HighchartsViewState extends State<HighchartsView>
191128
'packages/highcharts_flutter/assets/highcharts_flutter.js',
192129
'packages/highcharts_flutter/assets/highcharts_view.html',
193130
], assetBundle: DefaultAssetBundle.of(context))
194-
.then((loadedAssets) => {
195-
if (!_disposed)
196-
{
197-
setState(() {
198-
_assets = loadedAssets;
199-
})
200-
}
201-
});
131+
.then((loadedAssets) {
132+
if (!_disposed) {
133+
setState(() {
134+
_assets = loadedAssets;
135+
});
136+
}
137+
});
138+
139+
if (widget.onLoading != null) {
140+
return widget.onLoading!(widget);
141+
}
142+
143+
return Container();
202144
} catch (error) {
203145
if (widget.onError != null) {
204146
return widget.onError!(widget, error);
205147
}
206148

207149
throw error;
208150
}
209-
}
210-
211-
if (_assets.isNotEmpty && !_prepared) {
151+
} else if (!_prepared) {
212152
try {
213153
(() async {
214154
final String bridge = _assets[0];
@@ -218,14 +158,16 @@ class _HighchartsViewState extends State<HighchartsView>
218158
(widget.body ?? '') + HighchartsHelpers.scriptTag(bridge))
219159
.replaceAll('{HIGHCHARTS_VIEW_FOOT}', widget.foot ?? '');
220160

221-
await widget.webViewController.loadHtmlString(html);
161+
await _stateBridge.webViewController.loadHtmlString(html);
222162

223163
if (!_disposed) {
224164
setState(() {
225165
_prepared = true;
226166
});
227167
}
228168
})();
169+
170+
return Container();
229171
} catch (error) {
230172
if (widget.onError != null) {
231173
return widget.onError!(widget, error);
@@ -235,26 +177,147 @@ class _HighchartsViewState extends State<HighchartsView>
235177
}
236178
}
237179

238-
if (_assets.isEmpty || !_prepared) {
239-
if (widget.onLoading != null) {
240-
return widget.onLoading!(widget);
241-
}
242-
243-
return Container();
244-
}
245-
246-
return widget.webView;
180+
return _stateBridge.webView;
247181
}
248182

249183
@override
250184
void dispose() {
251-
super.dispose();
252185
_disposed = true;
186+
widget._stateBridge.dispose();
187+
super.dispose();
188+
}
189+
190+
@override
191+
void didUpdateWidget(HighchartsView oldWidget) {
192+
super.didUpdateWidget(oldWidget);
193+
widget._stateBridge.transfer(_stateBridge);
253194
}
254195

255196
@override
256197
void initState() {
257198
super.initState();
258199
_disposed = false;
200+
_stateBridge = widget._stateBridge;
201+
}
202+
}
203+
204+
/// Manages the exchange between state and widget for optimized rendering tasks.
205+
/// The widget can be assigned to new states, while the state can be
206+
/// assigned to new widgets.
207+
class _HighchartsViewStateBridge {
208+
_HighchartsViewStateBridge(
209+
this.widget,
210+
);
211+
212+
WebViewWidget? _webView;
213+
214+
WebViewWidget get webView {
215+
if (_webView == null) {
216+
init();
217+
}
218+
return _webView!;
219+
}
220+
221+
WebViewController? _webViewController;
222+
223+
WebViewController get webViewController {
224+
if (_webViewController == null) {
225+
init();
226+
}
227+
return _webViewController!;
228+
}
229+
230+
HighchartsView widget;
231+
232+
void dispose() {
233+
this._webView = null;
234+
this._webViewController = null;
235+
}
236+
237+
void init() {
238+
HighchartsView widget = this.widget;
239+
PlatformWebViewControllerCreationParams params;
240+
241+
if (WebViewPlatform.instance is AndroidWebViewPlatform) {
242+
params = AndroidWebViewControllerCreationParams();
243+
} else if (WebViewPlatform.instance is WebKitWebViewPlatform) {
244+
params = WebKitWebViewControllerCreationParams();
245+
} else {
246+
params = const PlatformWebViewControllerCreationParams();
247+
}
248+
249+
_webViewController = WebViewController.fromPlatformCreationParams(params);
250+
251+
if (webViewController.platform is WebKitWebViewController) {
252+
(webViewController.platform as WebKitWebViewController)
253+
.setInspectable(true);
254+
}
255+
256+
if (webViewController.platform is AndroidWebViewController ||
257+
webViewController.platform is WebKitWebViewController) {
258+
webViewController
259+
..setBackgroundColor(const Color(0x00000000))
260+
..setJavaScriptMode(JavaScriptMode.unrestricted);
261+
}
262+
263+
webViewController
264+
..setNavigationDelegate(NavigationDelegate(onPageFinished: (_) {
265+
if (widget.onMounted != null) {
266+
// Use `widget` to access properties of the *current* widget
267+
widget.onMounted!(widget);
268+
}
269+
}))
270+
..addJavaScriptChannel(
271+
'highcharts_flutter_channel',
272+
onMessageReceived: (e) async {
273+
final dataIndex = e.message.indexOf('\n');
274+
275+
final callbackKey =
276+
(dataIndex < 0 ? e.message : e.message.substring(0, dataIndex));
277+
final data = (dataIndex < 0
278+
? []
279+
: (jsonDecode(e.message.substring(dataIndex + 1)) ?? []));
280+
281+
if (callbackKey == 'highcharts_flutter.chart') {
282+
if (widget.onLoaded != null) {
283+
widget.onLoaded!(widget);
284+
}
285+
return;
286+
}
287+
288+
if (HighchartsCallback.registry.containsKey(callbackKey)) {
289+
HighchartsCallback.registry[callbackKey]!(data);
290+
return;
291+
}
292+
293+
// Use `widget._events` to access the map on the current widget
294+
if (widget._events.containsKey(callbackKey)) {
295+
for (final callback in widget._events[callbackKey]!) {
296+
await callback(data);
297+
}
298+
return;
299+
}
300+
301+
if (widget.debug) {
302+
debugPrint('Unhandled callback: ${e.message}');
303+
}
304+
},
305+
);
306+
307+
if (WebViewPlatform.instance is AndroidWebViewPlatform) {
308+
_webView = WebViewWidget.fromPlatformCreationParams(
309+
params: AndroidWebViewWidgetCreationParams(
310+
controller: webViewController.platform,
311+
displayWithHybridComposition: true, // Fix scrolling interference
312+
),
313+
);
314+
} else {
315+
_webView = WebViewWidget(controller: webViewController);
316+
}
317+
}
318+
319+
void transfer(_HighchartsViewStateBridge oldStateBridge) {
320+
_webView = oldStateBridge._webView;
321+
_webViewController = oldStateBridge._webViewController;
259322
}
260323
}

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: highcharts_flutter
2-
version: 1.1.1
2+
version: 1.1.2
33
description: >-
44
Official Flutter integration for Highcharts with many options for interactive
55
charts, that can be adjusted and dynamically loaded.

0 commit comments

Comments
 (0)