🔧 Mobile
Flutter Mobile Development
Last updated: 2025-09-25 02:29:54
Flutter Cross-Platform Framework
Flutter is Google's UI toolkit for building beautiful, natively compiled applications for mobile, web, and desktop.
Basic Flutter App Structure
// main.dart
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
routes: {
'/second': (context) => SecondScreen(),
'/profile': (context) => ProfileScreen(),
},
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
int _counter = 0;
String _message = 'Hello Flutter!';
void _incrementCounter() {
setState(() {
_counter++;
_message = 'Button pressed $_counter times';
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: [
IconButton(
icon: Icon(Icons.settings),
onPressed: () {
Navigator.pushNamed(context, '/profile');
},
),
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
_message,
style: TextStyle(fontSize: 18),
),
SizedBox(height: 20),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/second');
},
child: Text('Go to Second Screen'),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
State Management with Provider
// counter_model.dart
import 'package:flutter/foundation.dart';
class Counter with ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
void decrement() {
if (_count > 0) {
_count--;
notifyListeners();
}
}
void reset() {
_count = 0;
notifyListeners();
}
}
// user_model.dart
class User {
final String id;
final String name;
final String email;
final String? profileImage;
User({
required this.id,
required this.name,
required this.email,
this.profileImage,
});
factory User.fromJson(Map json) {
return User(
id: json['id'],
name: json['name'],
email: json['email'],
profileImage: json['profileImage'],
);
}
Map toJson() {
return {
'id': id,
'name': name,
'email': email,
'profileImage': profileImage,
};
}
}
class UserProvider with ChangeNotifier {
User? _user;
bool _loading = false;
User? get user => _user;
bool get loading => _loading;
Future fetchUser(String userId) async {
_loading = true;
notifyListeners();
try {
// Simulate API call
await Future.delayed(Duration(seconds: 2));
_user = User(
id: userId,
name: 'John Doe',
email: 'john@example.com',
profileImage: 'https://example.com/avatar.jpg',
);
} catch (error) {
print('Error fetching user: $error');
} finally {
_loading = false;
notifyListeners();
}
}
void updateUser(User updatedUser) {
_user = updatedUser;
notifyListeners();
}
void logout() {
_user = null;
notifyListeners();
}
}
// main.dart with Provider
import 'package:provider/provider.dart';
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => Counter()),
ChangeNotifierProvider(create: (context) => UserProvider()),
],
child: MyApp(),
),
);
}
// Using Provider in widgets
class CounterScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Counter with Provider')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Consumer(
builder: (context, counter, child) {
return Text(
'Count: ${counter.count}',
style: TextStyle(fontSize: 24),
);
},
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () {
context.read().decrement();
},
child: Text('-'),
),
ElevatedButton(
onPressed: () {
context.read().increment();
},
child: Text('+'),
),
ElevatedButton(
onPressed: () {
context.read().reset();
},
child: Text('Reset'),
),
],
),
],
),
),
);
}
}
HTTP Requests and JSON
// api_service.dart
import 'dart:convert';
import 'package:http/http.dart' as http;
class ApiService {
static const String baseUrl = 'https://jsonplaceholder.typicode.com';
static Future> fetchPosts() async {
try {
final response = await http.get(
Uri.parse('$baseUrl/posts'),
headers: {'Content-Type': 'application/json'},
);
if (response.statusCode == 200) {
List jsonList = json.decode(response.body);
return jsonList.map((json) => Post.fromJson(json)).toList();
} else {
throw Exception('Failed to fetch posts: ${response.statusCode}');
}
} catch (error) {
throw Exception('Network error: $error');
}
}
static Future createPost(Post post) async {
try {
final response = await http.post(
Uri.parse('$baseUrl/posts'),
headers: {'Content-Type': 'application/json'},
body: json.encode(post.toJson()),
);
if (response.statusCode == 201) {
return Post.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to create post: ${response.statusCode}');
}
} catch (error) {
throw Exception('Network error: $error');
}
}
static Future updatePost(int id, Post post) async {
try {
final response = await http.put(
Uri.parse('$baseUrl/posts/$id'),
headers: {'Content-Type': 'application/json'},
body: json.encode(post.toJson()),
);
if (response.statusCode == 200) {
return Post.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to update post: ${response.statusCode}');
}
} catch (error) {
throw Exception('Network error: $error');
}
}
}
// post_model.dart
class Post {
final int? id;
final int userId;
final String title;
final String body;
Post({
this.id,
required this.userId,
required this.title,
required this.body,
});
factory Post.fromJson(Map json) {
return Post(
id: json['id'],
userId: json['userId'],
title: json['title'],
body: json['body'],
);
}
Map toJson() {
return {
if (id != null) 'id': id,
'userId': userId,
'title': title,
'body': body,
};
}
}
// posts_screen.dart
class PostsScreen extends StatefulWidget {
@override
_PostsScreenState createState() => _PostsScreenState();
}
class _PostsScreenState extends State {
List posts = [];
bool loading = true;
String? error;
@override
void initState() {
super.initState();
fetchPosts();
}
Future fetchPosts() async {
try {
setState(() {
loading = true;
error = null;
});
final fetchedPosts = await ApiService.fetchPosts();
setState(() {
posts = fetchedPosts;
loading = false;
});
} catch (e) {
setState(() {
error = e.toString();
loading = false;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Posts'),
actions: [
IconButton(
icon: Icon(Icons.refresh),
onPressed: fetchPosts,
),
],
),
body: loading
? Center(child: CircularProgressIndicator())
: error != null
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Error: $error'),
ElevatedButton(
onPressed: fetchPosts,
child: Text('Retry'),
),
],
),
)
: RefreshIndicator(
onRefresh: fetchPosts,
child: ListView.builder(
itemCount: posts.length,
itemBuilder: (context, index) {
final post = posts[index];
return Card(
margin: EdgeInsets.all(8.0),
child: ListTile(
title: Text(
post.title,
style: TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text(
post.body,
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
trailing: Text('User ${post.userId}'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PostDetailScreen(post: post),
),
);
},
),
);
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CreatePostScreen(),
),
).then((_) => fetchPosts());
},
child: Icon(Icons.add),
),
);
}
}