Halim’in Günlüğü, Türkçe bir blog. O yüzden, Flutter sayfalarını da Türkçe başladım. Ama zor oldu. Şimdilik İngilizce devam edeceğim. İleride vakit olursa Türkçe’ye çeviririm diye umuyorum🤓
Widget Tree
In VS Code, one can display the widget tree by ⌘+SHIFT+P and delecting Flutter:OPenDev Tools Widget Inspector Page or by clicking on the widget inspector icon that appears on the hot start menu.
The Widget Inspector is only available when you are running the app. The game_template package has a relatively simple widget tree:
Notes on the Code
FirebaseCrashlytics? crashlytics;
crashlytics,
null
değer alabilir. Soru işareti, bunu ifade ediyor. Aksi halde, Dart değişkenleri normal olarak null
değer alamaz. Daha fazla bilgi için: https://dart.dev/codelabs/dart-cheatsheet#nullable-variables
More importantly, FireBase documentation says that
Firebase Crashlytics is a lightweight, realtime crash reporter that helps you track, prioritize, and fix stability issues that erode your app quality.
guardWithCrashlytics
Called by main()
in main.dart. The following is from src/crashlytics/crashlytics.dart.
WidgetsFlutterBinding.ensureInitialized();
Flutter documentation says that ‘This is the glue that binds the framework to the Flutter engine'. This is not very informative. If I delete that line in main.dart, I get the following error message:
ERROR: Binding has not yet been initialized. I/flutter (16326): The "instance" getter on the ServicesBinding binding mixin is only available once that binding has been initialized. I/flutter (16326): Typically, this is done by calling "WidgetsFlutterBinding.ensureInitialized()" or "runApp()" (the latter calls the former).
The main.dart calls runapp()
but this error message is printed AFTER the runapp()
is called. I ascertained this by logging after each line before runapp()
. However, it ios possible that some of the pre-runApp() calls are asynchronous the log message sequence may not be in sync with error generation. In fact, a stackfollower contributor comments that “you need to use this line (initialise WidgetsFlutterBinding), if your main function uses async keyword because you use await statement inside it”.
Anyway, I conclude that one should ALWAYS include the line
WidgetsFlutterBinding.ensureInitialized();
The earlier the better. The binding is idempotent, i.e. you can intialise WidgetsFlutterBinding
multiple times with no harm.
SystemChrome.setEnabledSystemUIMode
Flutter documentation says that the SystemChrome
class controls specific aspects of the operating system's graphical interface and how it interacts with the application. The SystemUIMode is an enum
that can be set to one of the following:
edgeToEdge
immersive
immersiveSticky
leanBack
manual
Not all choices are available for all operating systems and versions. The game_template
uses edgeToEdge
. This is apparently Fullscreen display with status and navigation elements rendered over the application.
I replaced edgeToEdge
with immersive
, in main.dart. On my Pixel 5 emulator, I noticed no difference. I reverted back to edgeToEdge
.
Ads, Game Services and InAppPurchase Controllers
These are commented out until I decide to incorporate them into the code.
runApp
This function expects a widget as an argument and it attaches that widget to the screen. Every Flutter program has at least one runApp. More information on Flutter documentation.
The main.dart widget MyApp
is the argument in this runApp
call. Let us examine MyApp
more closely.
MyApp
It has a super.key and five arguments:
const MyApp({
required this.playerProgressPersistence,
required this.settingsPersistence,
required this.inAppPurchaseController,
required this.adsController,
required this.gamesServicesController,
super.key,
});
Let us examine them separately.
PlayerProgressPersistence
PlayerProgressPersistence is a class in:
src\player_progress\persistence\local_storage_player_progress_persistence.dart
It is using SharedPreferences plugin to store/retrieve highestLevelReached. This is done on a two-stage call with
LocalStoragePlayerProgressPersistence in
src\player_progress\persistence\local_storage_player_progress_persistence.dart
extending PlayerProgressPersistence in
src\player_progress\persistence\player_progress_persistence.dart
probably to make it easier for users to customise this template for their own games.