Refactor code
Presentation (Building the UI)
Summary
This lesson focuses on refactoring the Splash screen's code to improve readability and adhere to the Single Responsibility Principle (SRP). The instructor extracts the animation initialization and the navigation logic into their own dedicated methods, cleaning up the initState function. Additionally, the foundational folder structure for the new "Home" feature is created, demonstrating how to organize files into presentation and data layers while utilizing the Get package to implement a faded, timed route transition between the two screens.
Key Ideas
- Extracting initialization and routing logic from
initStateinto dedicated methods significantly improves code readability. - The Single Responsibility Principle (SRP) dictates that functions and methods should only perform one primary task.
- Feature-based folder structure isolates UI and data logic, keeping the project modular.
Future.delayedcan be used to wait for a specific duration before triggering navigation away from a Splash screen.- The
getpackage provides a simplified API (Get.to()) for screen routing and includes built-in animations likeTransition.fade. - Hardcoded durations and magic numbers should be extracted into a centralized constants file (e.g.,
kTransitionDuration) for app-wide consistency.
Code Snippets
class _SplashViewBodyState extends State<SplashViewBody>
with SingleTickerProviderStateMixin {
late AnimationController animationController;
late Animation<Offset> slidingAnimation;
@override
void initState() {
super.initState();
initSlidingAnimation();
navigateToHome();
}
@override
void dispose() {
super.dispose();
animationController.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Image.asset(AssetsData.logo),
const SizedBox(
height: 4,
),
SlidingText(slidingAnimation: slidingAnimation),
],
);
}
void initSlidingAnimation() {
animationController = AnimationController(
vsync: this,
duration: const Duration(seconds: 1),
);
slidingAnimation =
Tween<Offset>(begin: const Offset(0, 2), end: Offset.zero)
.animate(animationController);
animationController.forward();
}
void navigateToHome() {
Future.delayed(
const Duration(seconds: 2),
() {
Get.to(
() => const HomeView(),
transition: Transition.fade,
duration: kTransitionDuration,
);
},
);
}
}import 'package:flutter/material.dart';
const kPrimaryColor = Color(0xff100B20);
const kTransitionDuration = Duration(milliseconds: 250);import 'package:flutter/material.dart';
class HomeView extends StatelessWidget {
const HomeView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Scaffold();
}
}Architecture Insight
Widget extraction is the precursor to layer extraction. The same instinct — *"this thing has its own job, give it a name"* — drives the eventual split into use cases, repositories, and entities. Practicing it on widgets builds the muscle for the harder calls later.
A useful heuristic: if a widget needs more than three positional parameters, you're probably missing an abstraction. The same is true for use cases later.
My Notes
- The instructor strongly emphasizes the Single Responsibility Principle (SRP) at the method level. This is a crucial habit:
initStateshould orchestrate initializations, not contain the raw logic for them. [Editor's note]The instructor sets updataandpresentationfolders for the Home feature, explicitly stating it's a 2-layer approach (MVVM) instead of 3. In a pure Clean Architecture setup, you would typically still maintain adomainlayer to decouple the UI/Presentation from the Data layer. The instructor is blending standard MVVM folder structuring into a broader Clean Architecture context, which is common in Flutter but structurally distinct from Uncle Bob's strict definition.[Editor's note]The usage ofGet.to()for navigation is very quick, but it violates dependency rules by tightly coupling views to a specific third-party routing package. Abstracting this behind an interface (or using a standard Router API) is a safer long-term architectural choice.