Flutter Advanced |
This section introduces some advanced Flutter concepts to help enhance your development skills.
Rendering Principles
Flutter uses the Skia (gradually switching to Impeller since 3.0) rendering engine to directly draw UI, without relying on native components.
Widget Tree, Element Tree, and RenderObject Tree
- Widget Tree: Describes UI configuration (immutable)
- Element Tree: Instantiated objects of Widgets (mutable)
- RenderObject Tree: Responsible for actual rendering
Understanding rendering principles helps optimize UI performance and avoid unnecessary rebuilds.
InheritedWidget β Data Passing
InheritedWidget allows data to be passed down the Widget tree, enabling child widgets to access data from their ancestors.
Example: Custom InheritedWidget
// Define data container
class MyData extends InheritedWidget {
final int value;
const MyData({
super.key,
required this.value,
required super.child,
});
// Convenience method: get the nearest MyData
static MyData of(BuildContext context){
return context.dependOnInheritedWidgetOfExactType()!;
}
// Determine whether child widgets need to be rebuilt
@override
bool updateShouldNotify(MyData oldWidget){
return value != oldWidget.value;
}
}
// Usage
class ParentWidget extends StatelessWidget {
const ParentWidget({super.key});
@override
Widget build(BuildContext context){
return MyData(
value:42,
child:const ChildWidget(),
);
}
}
class ChildWidget extends StatelessWidget {
const ChildWidget({super.key});
@override
Widget build(BuildContext context){
// Get ancestor MyData
final myData = MyData.of(context);
return Text('Value: ${myData.value}');
}
}
RepaintBoundary β Local Repainting
Using RepaintBoundary restricts the repaint area, improving performance.
Example: Using RepaintBoundary
class MyWidget extends StatelessWidget {
const MyWidget({super.key});
@override
Widget build(BuildContext context){
return RepaintBoundary(
child: Container(
// Drawing in this area wonβt affect the outside
color: Colors.red,
child:const Text('Independent Area'),
),
);
}
}
Deep Understanding of Keys
Keys help Flutter identify Widgets and distinguish between new and existing Widgets.
ValueKey vs ObjectKey vs UniqueKey
| Type | Description |
|---|---|
| ValueKey | Uses a value as the key (e.g., ID, number, string) |
| ObjectKey | Uses an object reference as the key |
| UniqueKey | Generates a unique key each time itβs created, preventing rebuild reuse |
CustomPainter β Custom Drawing
CustomPainter enables fully custom graphics rendering.
Example: Using CustomPainter
class CustomPainterExample extends StatelessWidget {
const CustomPainterExample({super.key});
@override
Widget build(BuildContext context){
return CustomPaint(
painter: MyCirclePainter(),
size:const Size(200,200),
);
}
}
class MyCirclePainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size){
// Draw circle
final paint = Paint()
..color= Colors.blue
..style= PaintingStyle.fill;
final center = Offset(size.width/2, size.height/2);
final radius = size.width/2-10;
canvas.drawCircle(center, radius, paint);
// Draw border
final borderPaint = Paint()
..color= Colors.black
..style= PaintingStyle.stroke
..strokeWidth=2;
canvas.drawCircle(center, radius, borderPaint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate){
return false;
}
}
Stream and Future
Example: Using Stream
// Create Stream
Stream<int> countStream(int max) async*{
for(int i =1; i <= max; i++){
await Future.delayed(const Duration(seconds:1));
yield i;// Emit value
}
}
// Use StreamBuilder
class StreamExample extends StatelessWidget {
const StreamExample({super.key});
@override
Widget build(BuildContext context){
return StreamBuilder<int>(
stream: countStream(10),
builder:(context, snapshot){
if(snapshot.hasData){
return Text('Count: ${snapshot.data}');
}else if(snapshot.hasError){
return Text('Error: ${snapshot.error}');
}
return const CircularProgressIndicator();
},
);
}
}
Summary
This Flutter tutorial covers the following topics:
- Flutter installation and environment setup
- Widget fundamentals (StatelessWidget and StatefulWidget)
- Layout system (Row, Column, Stack)
- Handling user input
- State management (setState, Provider)
- Network requests and data storage
- Navigation and routing
- Testing and publishing
For further learning, consider exploring:
- BLoC pattern
- Riverpod state management
- GetX routing and state management
- Flutter performance optimization
- Flutter Web and desktop development
YouTip