App issues with flutter driver and compute
on Flutter, Mobile
Is flutter driver not running your app correctly? Are you using isolates in flutter?
I recently built my first mobile app using the Flutter framework. It was a podcasts management app, Netcasts OSS. When I started writing integrations testing and automating screenshots for the app, I found that the app just did not behave in the same way when running with the flutter driver.
Flutter Driver Caveat
What I observed was that the app would not load any
podcasts. I initially thought the app did not have any
internet permissions running via the driver. I followed
this rabbit hole briefly. Eventually, after debugging and tracing the
execution, I found that the trouble was with isolates and my use of the
compute
.
Flutter recommends that for better user experience,
apps should keep the main thread free and do anything
computationally intensive on separate threads via
background parsing.
The most common case where this is relevant
is when you obtain some JSON or XML data via a remote API
and are looking to parse the response.
Fix
Upon realizing that the issue was with running isolates, it was pretty easy to find the pertinent issue on github - Isolates don’t work with flutter_driver. A poster in the issue issue recommends not running isolates in debug (test) environments as a work around to the driver’s shortcoming.
/*
* Courtesy of https://github.com/flutter/flutter/issues/24703#issuecomment-473335593
*/
import 'package:flutter/foundation.dart' as flutter show compute;
import 'package:flutter/foundation.dart' show ComputeCallback;
Future<R> compute<Q, R>(ComputeCallback<Q, R> callback, Q message) async {
if (isInDebugMode) {
return callback(message);
}
return await flutter.compute(callback, message);
}
Expanding on this solution, you can leverage the fact
that assert
statements will run only in debug environments
in order to detect isInDebugMode
.
bool get isInDebugMode {
bool inDebugMode = false;
assert(inDebugMode = true);
return inDebugMode;
}
Ideally, you define this in one place and reuse this
custom compute
implementation. For example, I keep
the definition in a common helper file that I reuse this throughout
my project.