This is a Gemini generated project to provide an example project using get_it
Give me an example project using flutter with get_it which shows a view via this get_it location
The get_it package in Flutter is a service locator, not a routing or navigation solution. While you can register and retrieve objects (including Widgets or StatefulWidgets) from get_it, directly "showing a view via this get_it location" isn't its primary purpose or a typical use case for navigation.
Navigation in Flutter is handled by Navigator (using routes and pages). get_it's strength lies in dependency injection – providing access to services, repositories, or BLoCs/ChangeNotifiers throughout your app.
However, I can provide an example that demonstrates how you could use get_it to register a Widget and then retrieve it to display, though it's important to understand this isn't how you'd usually handle navigation.
Here's an example project demonstrating get_it with Flutter, where a Widget is registered and then displayed:
Project Structure:
flutter_get_it_example/
├── lib/
│ ├── main.dart
│ ├── services/
│ │ └── app_locator.dart
│ ├── views/
│ │ ├── home_view.dart
│ │ └── detail_view.dart
│ └── widgets/
│ └── custom_button.dart
├── pubspec.yaml
- pubspec.yaml:
Add get_it to your dependencies.
name: flutter_get_it_example
description: A Flutter project demonstrating get_it.
publish_to: 'none'
version: 1.0.0+1
environment:
sdk: '>=3.0.0 <4.0.0'
dependencies:
flutter:
sdk: flutter
get_it: ^7.2.0 # Use the latest stable version
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
flutter:
uses-material-design: true
- lib/services/app_locator.dart:
This file will handle the get_it setup.
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:flutter_get_it_example/views/detail_view.dart';
import 'package:flutter_get_it_example/views/home_view.dart';
final GetIt locator = GetIt.instance;
void setupLocator() {
// Registering a simple data object (Singleton)
locator.registerSingleton<String>('My App Title');
// Registering a HomeView (LazySingleton) - created only when needed
locator.registerLazySingleton<Widget>(() => HomeView(), instanceName: 'HomeView');
// Registering a DetailView (Factory) - a new instance every time it's requested
locator.registerFactory<Widget>(() => DetailView(), instanceName: 'DetailView');
// You can also register services or other objects
// locator.registerLazySingleton<MyService>(() => MyServiceImpl());
}
- lib/views/home_view.dart:
This is our main view, which will retrieve a Widget from get_it.
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:flutter_get_it_example/services/app_locator.dart';
import 'package:flutter_get_it_example/widgets/custom_button.dart';
class HomeView extends StatelessWidget {
const HomeView({super.key});
@override
Widget build(BuildContext context) {
// Retrieve the app title registered as a Singleton
final String appTitle = locator<String>();
return Scaffold(
appBar: AppBar(
title: Text(appTitle),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Welcome to the Home View!',
style: TextStyle(fontSize: 24),
),
const SizedBox(height: 20),
CustomButton(
text: 'Go to Detail View (via GetIt)',
onPressed: () {
// This is where we "show" the view.
// In a real app, you would use Navigator.push() here.
// For demonstration, we're just directly building the widget
// obtained from GetIt.
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => locator<Widget>(instanceName: 'DetailView'),
),
);
},
),
],
),
),
);
}
}
- lib/views/detail_view.dart:
A simple view that will be retrieved from get_it.
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:flutter_get_it_example/services/app_locator.dart';
class DetailView extends StatelessWidget {
const DetailView({super.key});
@override
Widget build(BuildContext context) {
final String appTitle = locator<String>(); // Still accessible from GetIt
return Scaffold(
appBar: AppBar(
title: Text('Detail View - $appTitle'),
),
body: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'You are in the Detail View!',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 20),
Text('This view was provided by GetIt.'),
],
),
),
);
}
}
- lib/widgets/custom_button.dart:
A reusable button widget.
import 'package:flutter/material.dart';
class CustomButton extends StatelessWidget {
final String text;
final VoidCallback onPressed;
const CustomButton({
super.key,
required this.text,
required this.onPressed,
});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: onPressed,
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 15),
),
child: Text(
text,
style: const TextStyle(fontSize: 18),
),
);
}
}
- lib/main.dart:
The entry point of our Flutter application.
import 'package:flutter/material.dart';
import 'package:flutter_get_it_example/services/app_locator.dart';
import 'package:flutter_get_it_example/views/home_view.dart'; // Or retrieve from GetIt
void main() {
setupLocator(); // Initialize GetIt registrations
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
// We can directly use HomeView here, or if you prefer,
// you could retrieve it from GetIt as well:
// final Widget homeView = locator<Widget>(instanceName: 'HomeView');
return MaterialApp(
title: locator<String>(), // Retrieve the app title from GetIt
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const HomeView(), // Using the HomeView directly
// Or if you want to be consistent with GetIt:
// home: locator<Widget>(instanceName: 'HomeView'),
);
}
}
get_it Initialization (setupLocator()):
We create a global GetIt instance called locator.
setupLocator() is called in main() before runApp(). This ensures all your dependencies are registered before your UI tries to access them.
Registering Objects:
locator.registerSingleton<String>('My App Title');: Registers a single instance of a String (our app title). This instance will be returned every time String is requested.
locator.registerLazySingleton<Widget>(() => HomeView(), instanceName: 'HomeView');: Registers HomeView as a lazy singleton. This means the HomeView instance will only be created the first time it's requested via locator<Widget>(instanceName: 'HomeView'), and the same instance will be returned on subsequent requests. We use instanceName because we're registering multiple Widget types.
locator.registerFactory<Widget>(() => DetailView(), instanceName: 'DetailView');: Registers DetailView as a factory. This means a new instance of DetailView will be created every single time locator<Widget>(instanceName: 'DetailView') is called.
Retrieving Objects (locator<Type>()):
In HomeView, we retrieve the app title using final String appTitle = locator<String>();.
When navigating to DetailView, we use locator<Widget>(instanceName: 'DetailView') to get an instance of DetailView and pass it to MaterialPageRoute.
Why this is not typical navigation and what you should do:
get_it is for Dependency Injection, not Routing: get_it excels at providing services, BLoCs, repositories, etc., to your widgets and other parts of your application without tightly coupling them.
Flutter's Navigator for Navigation: The standard and recommended way to navigate between screens in Flutter is using Navigator.push() and Navigator.pop() with MaterialPageRoute, named routes, or declarative routing solutions like go_router or auto_route.
The "View via GetIt" in this example: While the DetailView is indeed retrieved from get_it, it's still being passed to MaterialPageRoute which is the actual mechanism for displaying the view on the screen and managing the navigation stack. You wouldn't typically register entire Widgets for navigation this way, especially if they have complex constructors or need to manage their own state with dependencies.
Instead of registering the View itself, you'd register the dependencies that the View (or its BLoC/ViewModel) needs.
Example of a more typical get_it use for a DetailView: (not in the project)
// In app_locator.dart
locator.registerLazySingleton<UserRepository>(() => UserRepositoryImpl());
locator.registerFactory<DetailViewModel>(() => DetailViewModel(userRepository: locator<UserRepository>()));
// In HomeView (navigation logic)
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailView(viewModel: locator<DetailViewModel>()),
),
);
// In DetailView (constructor expects a viewModel)
class DetailView extends StatelessWidget {
final DetailViewModel viewModel;
const DetailView({Key? key, required this.viewModel}) : super(key: key);
// ...
}
This approach separates concerns: get_it provides the DetailViewModel (and its dependencies), and Navigator handles the display of the DetailView.