why does flutter app have bad performance when launching them - flutter

I'm trying to make my app performant.
I'm using dart devtools and when i check the graph I see that there is some shader compilation detected when launching the app for the first time, I thought that my app has a problem but i tried to run the code that flutter provides us when creating a new project and boom the result was the same.
I want to know if there is someone that encountred the same problem ?
Ps : i tested the app on a real device with os Android 12 and CPU ARM X64.
there is my code :
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Sample App',
home: MyHomePage(
title: 'App',
),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key, required this.title});
final String title;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Column(
children: const [
Text('hello'),
],
),
),
);
}
}

As I understand your problem, you want to reduce the time your app needs to start and found the shader compilation to be a big part of it. If that understanding is correct, this might help:
First, you can not "disable" shader compilation, every flutter application needs to compile the shaders for rendering, but it heavily depends on your application, how much time that takes (many animations for example are bad here)
Second, since Flutter 1.20, you can use the SkSL warmup to reduce the startup time for compiling your shaders. The idea being, that you compile the shader once and save it for faster startup times.
You can test this feature while in development with
flutter run --cache-sksl
this will take more time than before, but afterwards, your flutter run commands will be faster.
If you want to build your application with SkSL warmup, you have to write the SkSL shaders into a file by pressing "M" while in the command line of flutter run, then you can use:
flutter build ios --bundle-sksl-path flutter_01.sksl.json
to build the application. More information can be found here.
I tested this with the small program you sent, for normal startup it needed 25.9ms for the shader compilation, caching the sksl file needed 225.9ms, and flutter run afterwards needed 9.6ms for the shaders. Therefore caching sksl made it about 63% faster (it was only one short test, so the results are no medians or anything, so the meaningfulness of this test is debatable).
Lastly, you should always test your performance in release builds, not in debug mode. Debugging your application has a large overhead and much worse performance than released applications. Have a look at Flutter build modes for more information.

Related

In background flutter app works only for 1 minute after that it stops it's working, is Dart-Isolates good to try?

made a simple counter app with shake package to increment counter var by shaking phone, things works well when app is running in front (in active state) but opening other app stops this shake feature after one minute, it works only for one minute but not after one minute, i have tried to implement isolate but i couldn't do so, If someone can show me how to implement isolate in following code i will be very thanks full to him,
Thank you
Code is here:
import 'package:flutter/material.dart';
import 'package:shake/shake.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int _counter = 0;
ShakeDetector detector;
#override
void initState() {
detector = ShakeDetector.autoStart(onPhoneShake: () {
setState(() {
_counter++;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(child: Text('$_counter')),
),
);
}
}
Your app is not running in the background. This is not a desktop operating system, where the windows can overlap and be in the background and the process is still running regardless.
Mobile device operating systems are all optimized for foreground app handling. Once your app is no longer the app, it can be removed by the operating system at any time. The operating system will keep a screenshot of your app, to make you think it's still there, but if the system deems it necessary, your app will be shut down and selecting the last picture of your app (which you probably interpret as "get this running app into the foreground" as you know it from desktop operating systems) will actually start a new instance of your app, since the old instance is long gone.
Running code in the background is more complicated than it seems from a desktop mindset that we all have. You can find a good start in the Flutter documentation on running background processes. It might seem overly complicated, because running something in the background is not the norm for mobile operating systems.
You could try this package: https://pub.dev/packages/flutter_background
Just be careful to use dependencies that allow background execution. Location for example should have permissions for "Always Use Location"

Is there a way to remove this blankspace from this flutter webapp on Firefox Mobile?

I am trying to do a responsive webapp and everything was working fine debugging it on the desktop firefox and I did the entire layout with the switch device option in the debug tools, but when I uploaded to an HTTP server and access it through my phone I get this screen
On chrome I have no problems and everything displays just right, on firefox on the other hand I have that weird blank space... At chrome that space was occupied by the "add to the homescreen" prompt, maybe that has something to do?
Any ideas would be greatly apreciated. I'm leaving the code just in case it helps...
void main() => runApp(MyApp2());
class MyApp2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Material App',
home: Scaffold(
appBar: AppBar(
title: Text('Material App Bar'),
),
body: Container(
color: Colors.red,
// child: Text('Hello World'),
),
),
);
}
}
I guess its useful to say that on chrome I get the expected behaviour of getting the full screen red except for the AppBar
Add to Homescreen button is feature of PWA so you should dive into index.html probably. Can you debug your Firefox Mobile and play with css a little bit. You can check official Firefox Remote Debugging Docs.

Flutter run stuck on white screen

I have a Flutter issue I can't resolve. I tried all common things like flutter clean, restarting pc, wiping emulator data and few more things still getting stuck on white screen basically.
Launching lib\main.dart on Android SDK built for x86 in debug mode...
✓ Built build\app\outputs\flutter-apk\app-debug.apk.
Installing build\app\outputs\flutter-apk\app.apk...
Connecting to VM Service at ws://127.0.0.1:55863/xq7cW6jF1O8=/ws // this statement stays as its is
void main() => MaterialApp(
color: Colors.black,
home: Scaffold(
backgroundColor: Colors.black,
),
);
Basically connection to VM is not happening.
Edit
My dartDeveloperTool says unable to connect to vm service, but it opens in chrome and doesn't show any widget just clean dartDebugger tool.
Call to OpenGL ES API with no current context (logged once per thread).
Of course, it won't work.
Because you need to wrap it in runApp method. Like this:
void main() {
runApp(
MaterialApp(
color: Colors.black,
home: Scaffold(
backgroundColor: Colors.black,
),
),
);
}
But it's kinda bad practice to put your MaterialApp inside your main() function. Try to move it into a StatelessWidget or StatefulWidget.
Here's the example:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: null, // Change null with your own widgets
),
);
}
}
Don't underestimate the importance of runApp() - If you don't use it - your app (which is one big widget) will result in an indefinite white screen because it has no constraints...
According to the documentation it:
/// Inflate the given widget and attach it to the screen. The widget is given constraints during layout that force it to fill the entire screen.
In my case, run app on debug mode working normal but I build file apk for release mode, app only show white screen. I finally found the solution. The problem was with my grade version. I downgrade version of grade in android/build.grade to 3.5.0, it works normally again.
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
}
I just faced a similar issue today and removing the Dart/Flutter extensions and installing them back solved it for me.
I also had the same issue while trying to run my app, I ran flutter clean, flutter doctor everything was green until I notice I was not connected to the internet.
If you are running the app for the first time, just restart your IDE and run your app with internet connection.
I had faced the same issue. In my case culprit was corporate proxy.
I have fixed it by setting Environment variables (User variables section) as I was using Windows machine.
HTTP_PROXY to http://proxy-ip:port
HTTPS_PROXY to http://proxy-ip:port
NO_PROXY to localhost,127.0.0.1
I faced the same issue of white screen with my friend project, the mistake was missing runApp() in Main.dart file, given below
void main() {
WidgetsFlutterBinding.ensureInitialized();
MultiProvider(
providers: [
ChangeNotifierProvider<CircuitProvider>(
create: (ctx) => CircuitProvider()),
],
child: const MyApp(),
),
}
So then it was replaced like,
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider<CircuitProvider>(
create: (ctx) => CircuitProvider()),
],
child: const MyApp(),
),
);
}
I faced with this problem in working app so in my case I've restarted phone and it was ok. Also check memory on your device maybe you have no free space

Flutter widget vs Flutter driver

I'm writing tests for a mobile App written in Flutter.
I followed this Flutter Cookbook on testing Flutter apps, to learn how to write widget and integration tests.
This tutorial works perfectly, but I'm still stuck with my own Integration tests.
To simplify, let's assume I have an app, containing only a TextField:
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MyAppp',
home: Scaffold(
body: Center(child: TextField()),
),
);
}
}
I want to write a test for this app. For instance, I want to test the following scenario:
Open the app
Check that the TextField is empty
Select the TextField
Enter "hello, world!"
Check that TextField contains "hello, world!"
I wrote the following Widget test, which works fine:
void main() {
testWidgets('TextField behavior', (WidgetTester tester) async {
// Create app
await tester.pumpWidget(MyApp());
// Find TextField, check there is 1
final textFieldFinder = find.byType(TextField);
expect(textFieldFinder, findsOneWidget);
// Retrieve TextField Widget from Finder
TextField textField = tester.widget(textFieldFinder);
// Check TextField is empty
expect(textField.controller.text, equals(""));
// Enter text
await tester.enterText(textFieldFinder, "hello, world!");
// Check TextField contains text
expect(textField.controller.text, equals("hello, world!"));
});
}
This test passes, but I wanted to write an Integration test, doing more or less the same, to be able to test it on a real device.
Indeed if this Widget test passes, it will probably pass on all device. But in my app I have more complex widgets and interactions between them, I want to be able to launch tests on both Android and iOS.
I tried to write integration tests using Flutter driver, but I did not find what I wanted in the documentation and examples.
How can I check Widget properties, to verify that my App behaves as expected?
I wrote the following sample:
import 'package:flutter_driver/flutter_driver.dart';
import 'package:test/test.dart';
void main() {
group('TextField', () {
final textFieldFinder = find.byType('TextField');
FlutterDriver driver;
setUpAll(() async {
driver = await FlutterDriver.connect();
});
tearDownAll(() async {
if (driver != null) {
driver.close();
}
});
test('TextField behavior', () async {
// ??? how to check that the TextField is empty
await driver.tap(textFieldFinder);
await driver.enterText("hello, world!");
// ??? how to check that the TextField contains hello, world!
});
});
}
The Flutter Cookbook tutorial explains how to retrieve an object by its Text, this would help to check if the Text is present, but for instance is it possible to check that a Container color is red?
Where is the limit between Widget and Integration tests?
Writing Widget tests is pretty straighforward, but I didn't find many examples or documentation about how to write more complexe integration tests using Flutter driver.
If anyone is interested:
To be able to test what I want (not only the presence of widgets, but also theirs states, their properties,...) test driver was not enough for me.
What I did in my project, is to use the flutter_test to write widget tests and check the properties I want.
To test it on a real device (Android or iOS), I used the integration_test package (previously e2e package) available here, which adapts flutter_test results to a format compatible with flutter drive.
To use integration_test, add this line in the main of your widget tests:
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
Then create a file (e.g. integration_test.dart) in your test_driver folder with this content:
import 'package:integration_test/integration_test_driver.dart';
Future<void> main() => integrationDriver();
Then you can launch these driver test by running:
flutter drive \
--driver=test_driver/integration_test.dart \
--target=test/widget_test/widget_test.dart
With your widgets tests wrote in the file test/widget_test/widget_test.dart.
It really helped me, since some widgets did not have the same behavior on Android and iOS.
Today I use both flutter_test (launched on real device with integration_test) and real flutter_driver tests:
I write widget tests to check a single widget, or a single page,
I use flutter driver to write more sophisticated scenarios to test the whole application.
I think there's a difference between flutter widget and flutter driver. In that, flutter widgets is for widget tests and flutter driver is for integration tests. I'm not exactly sure what that means on a practical standpoint but I think integration test are easier to run tests on application interactions that would be made by a user since integration tests run on an actual device as compared to widget tests. Will update if I find more information on this.

Flutter hot reloading is not working to display changes

I have two files, main.dart and sections.dart.
I have defined a few widgets in section.dart and used them in main.dart file, when I run flutter run command changes are displayed on screen, but when I press R to hot reload, nothing changes on screen.
main.dart:
import 'package:flutter/material.dart';
import 'sections.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Share IDEASS',
home: Scaffold(
appBar: AppBar(
title: Text('IDEASs'),
),
body: ListView(
children: [
labelsSection,
],
),
),
);
}
}
Sections.dart:
import 'package:flutter/material.dart';
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Share IDEAS',
);
}
}
Column labelSectionMethod(color,IconData icon, String label,String numbers){
return Column(
children: <Widget>[
Icon(icon, color:color),
Container(
child: Text(label,
style: TextStyle(color: color
),
),
),
Container(
child:Text(numbers,
style:TextStyle(color:color
),
),
),
],
);
}
Widget labelsSection=Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
labelSectionMethod(Colors.red,Icons.supervised_user_circle,"IDEASS","35"),
labelSectionMethod(Colors.red,Icons.favorite,"LIKE","22"),
labelSectionMethod(Colors.red,Icons.data_usage,"STREAK","12"),
],
),
);
Maybe because I am repeating:
return MaterialApp(
title: 'Share IDEAS',
);
in sections.dart, or something to do with main function.
UPDATE:
i moved content of sections.dart file in main.dart file still hot reload is not working.
After moving a file to another directory, Android Studio changed my imports to absolute paths.
import 'file:///C:/Users/svenv/AndroidStudioProjects/sample_screen_collection/lib/welcome/reading_list_card.dart';
i had to change it to this
import 'package:samplescreencollection/components/reading_list_card.dart';
This usually happens when you have change a lot of code, added states, changed a widget from stateless to state full, etc. Preforming a hot restart (ctrl +F5) will fix this issue.
If this seems to not work still, try removing the app from your phone/simulator/emulator (closing the app, and deleting it) and running debug/flutter run again. This should fix your issue
There have been issue reported to Flutter regarding this,https://github.com/flutter/flutter/issues/17155#issue-319238844
Basically it's like Flutter is not properly identifying the changes in order to generate updated build files (my personal understanding):
Solution
Simple solution is Clean the project and rebuild it.
I'm using Android studio Android Studio 3.6, Following steps illustrate how to clean the flutter project
Navigate to Tools in navigationbar
Select Flutter > Flutter Clean
Finally Run the Project again by clicking the green playicon
Sometimes flutter gets confused with large amounts of changes, and you need to perform a restart, especially when interacting with the entire App or main function.
You can pressCtrl+C to kill the flutter run process, and try launching it again. Additionally, if you run Flutter through IntelliJ or Android Studio, the flutter plugin includes a "Hot Restart" feature which accomplishes the same thing.
My situation was - Flutter would neither hot reload nor stop on a break-point nor even provide fresh builds to Android emulator, whereas iOS was fine.
I tried suggestions from above but nothing really worked, spent a day on these things.I upgraded from Android Studio 3.x to 4.1 and nothing changed.
What worked for me was:
Create a totally new Flutter sample project.
Validate it works - new versions are deployed, debugging and hot reloads work
Transfer my project into this new project. This pretty much involved replace of the lib and .git folders and manual updates of pubspec.yaml, AndroidManifest.xml and Info.plist (manual file updates took most of the effort, but still much less time than my several day attempts to make things work again)
Verify everything works.