Stateful vs Stateless — أساسيات Flutter
StatelessWidget vs StatefulWidget
1. StatelessWidget - بدون حالة
لا يتغير بمرور الوقت:
class GreetingCard extends StatelessWidget {
final String name;
const GreetingCard({required this.name});
@override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: EdgeInsets.all(16),
child: Text('مرحباً $name!'),
),
);
}
}
// الاستخدام
GreetingCard(name: 'أحمد')2. StatefulWidget - مع حالة
يتغير ويُعاد بناؤه:
class Counter extends StatefulWidget {
@override
_CounterState createState() => _CounterState();
}
class _CounterState extends State<Counter> {
int _count = 0;
void _increment() {
setState(() {
_count++;
});
}
void _decrement() {
setState(() {
_count--;
});
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'$_count',
style: TextStyle(fontSize: 48, fontWeight: FontWeight.bold),
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: _decrement,
child: Icon(Icons.remove),
),
SizedBox(width: 20),
ElevatedButton(
onPressed: _increment,
child: Icon(Icons.add),
),
],
),
],
);
}
}3. دورة حياة StatefulWidget
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
@override
void initState() {
super.initState();
// يُستدعى مرة واحدة عند الإنشاء
print('initState');
_loadData();
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
// يُستدعى بعد initState وعند تغير dependencies
print('didChangeDependencies');
}
@override
void didUpdateWidget(MyWidget oldWidget) {
super.didUpdateWidget(oldWidget);
// يُستدعى عند تحديث الـ widget
print('didUpdateWidget');
}
@override
void dispose() {
// يُستدعى عند حذف الـ widget
print('dispose');
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container();
}
}4. TextEditingController
class LoginForm extends StatefulWidget {
@override
_LoginFormState createState() => _LoginFormState();
}
class _LoginFormState extends State<LoginForm> {
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
bool _isLoading = false;
@override
void dispose() {
_emailController.dispose();
_passwordController.dispose();
super.dispose();
}
Future<void> _login() async {
setState(() => _isLoading = true);
try {
// محاكاة تسجيل الدخول
await Future.delayed(Duration(seconds: 2));
print('Email: ${_emailController.text}');
print('Password: ${_passwordController.text}');
} finally {
setState(() => _isLoading = false);
}
}
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(16),
child: Column(
children: [
TextField(
controller: _emailController,
decoration: InputDecoration(labelText: 'البريد'),
keyboardType: TextInputType.emailAddress,
),
SizedBox(height: 16),
TextField(
controller: _passwordController,
decoration: InputDecoration(labelText: 'كلمة المرور'),
obscureText: true,
),
SizedBox(height: 24),
ElevatedButton(
onPressed: _isLoading ? null : _login,
child: _isLoading
? CircularProgressIndicator(color: Colors.white)
: Text('دخول'),
),
],
),
);
}
}5. مثال: قائمة مهام
class TodoList extends StatefulWidget {
@override
_TodoListState createState() => _TodoListState();
}
class _TodoListState extends State<TodoList> {
final List<Map<String, dynamic>> _todos = [];
final _controller = TextEditingController();
void _addTodo() {
if (_controller.text.isNotEmpty) {
setState(() {
_todos.add({
'id': DateTime.now().toString(),
'text': _controller.text,
'done': false,
});
_controller.clear();
});
}
}
void _toggleTodo(int index) {
setState(() {
_todos[index]['done'] = !_todos[index]['done'];
});
}
void _deleteTodo(int index) {
setState(() {
_todos.removeAt(index);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('مهامي')),
body: Column(
children: [
Padding(
padding: EdgeInsets.all(16),
child: Row(
children: [
Expanded(
child: TextField(
controller: _controller,
decoration: InputDecoration(
hintText: 'أضف مهمة...',
border: OutlineInputBorder(),
),
onSubmitted: (_) => _addTodo(),
),
),
SizedBox(width: 8),
IconButton(
icon: Icon(Icons.add),
onPressed: _addTodo,
),
],
),
),
Expanded(
child: ListView.builder(
itemCount: _todos.length,
itemBuilder: (context, index) {
final todo = _todos[index];
return ListTile(
leading: Checkbox(
value: todo['done'],
onChanged: (_) => _toggleTodo(index),
),
title: Text(
todo['text'],
style: TextStyle(
decoration: todo['done']
? TextDecoration.lineThrough
: null,
),
),
trailing: IconButton(
icon: Icon(Icons.delete, color: Colors.red),
onPressed: () => _deleteTodo(index),
),
);
},
),
),
],
),
);
}
}اختبر فهمك